AuthenticationServiceImpl.java
package com.siddharthgawas.apigateway.service.impl;
import com.siddharthgawas.apigateway.security.dto.TokenDetails;
import com.siddharthgawas.apigateway.service.AuthenticationService;
import com.siddharthgawas.apigateway.service.JWTService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* AuthenticationServiceImpl is responsible for handling user authentication and token generation.
* It implements the AuthenticationService interface to provide custom authentication logic.
*/
@Service
public class AuthenticationServiceImpl implements AuthenticationService {
private final Map<String, User> users;
private final PasswordEncoder passwordEncoder;
private final JWTService jwtService;
@Autowired
public AuthenticationServiceImpl(final PasswordEncoder passwordEncoder, final JWTService jwtService) {
this.jwtService = jwtService;
this.users = new HashMap<>();
this.users.put("johndoe", new User("johndoe", passwordEncoder.encode("johndoe"),
Collections.emptyList()));
this.users.put("janedoe", new User("janedoe", passwordEncoder.encode("janedoe"),
Collections.emptyList()));
this.passwordEncoder = passwordEncoder;
}
/**
* Authenticates a user with the provided username and password.
* If the credentials are valid, it generates access and refresh tokens.
*
* @param username the username of the user
* @param password the password of the user
* @return TokenDetails containing access and refresh tokens
* @throws AccessDeniedException if the username or password is invalid
*/
@Override
public TokenDetails authenticate(final String username, final String password) {
var user = this.users.get(username);
if (Objects.isNull(user) || !this.passwordEncoder.matches(password, user.getPassword())) {
throw new AccessDeniedException("Invalid username or password");
}
var accessToken = this.jwtService.generateAccessToken(user);
var refreshToken = this.jwtService.generateRefreshToken(user);
return new TokenDetails(accessToken, refreshToken);
}
/**
* Refreshes the access token using the provided refresh token.
* Validates the refresh token and generates a new access token if valid.
*
* @param refreshToken the refresh token to validate and use for generating a new access token
* @return TokenDetails containing the new access token and a new refresh token
* @throws AccessDeniedException if the refresh token is invalid or no user is found
*/
@Override
public TokenDetails refreshAccessToken(final String refreshToken) {
var isValid = this.jwtService.validateToken(refreshToken);
if (!isValid) {
throw new AccessDeniedException("Invalid refresh token");
}
var user = this.jwtService.getUserFromToken(refreshToken);
if (Objects.isNull(user)) {
throw new AccessDeniedException("No user found for the provided refresh token");
}
var accessToken = this.jwtService.generateAccessToken(user);
return new TokenDetails(accessToken, this.jwtService.generateRefreshToken(user));
}
}