Skip to content

Commit 8caaa86

Browse files
fix : ensure a consistent format for request and response payloads for all APIs, covering both success and error scenarios
1 parent 8e9b1ab commit 8caaa86

28 files changed

+197
-189
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
## Overview
33

44
* In the Spring Security 6 ecosystem, compared to 5, there is a preference for JWT or Keycloak over traditional OAuth2 using a Password Grant method with Spring Security Authorization and Resource Server. I needed to incorporate the current OAuth2 Password Grant with the Spring Security new version and am showing the customization.
5-
* Set up access & refresh token APIs on both '/oauth2/token' and on our controller layer such as '/api/v1...', both of which function same.
5+
* Set up access & refresh token APIs on both '/oauth2/token' and on our controller layer such as '/api/v1...', both of which function same and have `the same request & response payloads for success and errors`.
66
* Authentication management based on a combination of username, client id, and an extra token (referred to in the source code as App-Token, which receives a unique value from the calling devices).
77
* Separated UserDetails implementation for Admin and Customer roles.
88
* Integration with spring-security-oauth2-authorization-server.
9-
* Provide MySQL DDL, which consists of oauth\_access\_token, oauth\_refresh\_token and oauth\_client\_details, which is tables in Security 5. As I mean to migrate current security system to Security 6, I haven't changed them to the ``authorization`` table indicated in https://github.com/spring-projects/spring-authorization-server.
9+
* Provide MySQL DDL, which consists of oauth\_access\_token, oauth\_refresh\_token and oauth\_client\_details, which is tables in Security 5. As I mean to migrate current security system to Security 6, I haven't changed them to the ``authorization`` table indicated in https://github.com/spring-projects/spring-authorization-server.
1010
* Application of Spring Rest Docs.
1111
## Dependencies
1212

@@ -28,5 +28,5 @@
2828

2929
### Running this App with Docker
3030
* Use the following module for Blue-Green deployment:
31-
* https://github.com/Andrew-Kang-G/docker-blue-green-runner
31+
* https://github.com/patternknife/docker-blue-green-runner
3232
* The above module references this app's Dockerfile and the entrypoint script in the .docker folder.

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/GlobalExceptionHandler.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33

44
import com.patternknife.securityhelper.oauth2.config.logger.dto.ErrorDetails;
5-
import com.patternknife.securityhelper.oauth2.config.response.error.exception.ErrorMessagesContainedExceptionForSecurityAuthentication;
65
import com.patternknife.securityhelper.oauth2.config.response.error.exception.auth.*;
76
import com.patternknife.securityhelper.oauth2.config.response.error.exception.data.*;
87
import com.patternknife.securityhelper.oauth2.config.response.error.exception.file.FileNotFoundException;
98
import com.patternknife.securityhelper.oauth2.config.response.error.exception.payload.SearchFilterException;
109
import com.patternknife.securityhelper.oauth2.config.response.error.message.GeneralErrorMessage;
11-
import com.patternknife.securityhelper.oauth2.config.response.error.message.SecurityExceptionMessage;
10+
import com.patternknife.securityhelper.oauth2.config.response.error.message.SecurityUserExceptionMessage;
1211
import jakarta.servlet.http.HttpServletRequest;
1312
import jakarta.validation.ConstraintViolationException;
1413
import org.springframework.core.Ordered;
@@ -43,15 +42,15 @@ public class GlobalExceptionHandler {
4342
* General
4443
* */
4544
// Login Failure
46-
@ExceptionHandler({InsufficientAuthenticationException.class, UnauthenticatedException.class, AuthenticationException.class})
45+
@ExceptionHandler({InsufficientAuthenticationException.class, CustomOauth2AuthenticationException.class, AuthenticationException.class})
4746
public ResponseEntity<?> authenticationException(Exception ex, WebRequest request) {
4847
ErrorDetails errorDetails;
49-
if(ex instanceof ErrorMessagesContainedExceptionForSecurityAuthentication && ((ErrorMessagesContainedExceptionForSecurityAuthentication) ex).getErrorMessages() != null) {
50-
errorDetails = new ErrorDetails(((ErrorMessagesContainedExceptionForSecurityAuthentication) ex).getErrorMessages(),
48+
if(ex instanceof CustomOauth2AuthenticationException && ((CustomOauth2AuthenticationException) ex).getErrorMessages() != null) {
49+
errorDetails = new ErrorDetails(((CustomOauth2AuthenticationException) ex).getErrorMessages(),
5150
ex, request.getDescription(false), CustomExceptionUtils.getAllStackTraces(ex),
5251
CustomExceptionUtils.getAllCauses(ex), null);
5352
}else {
54-
errorDetails = new ErrorDetails(CustomExceptionUtils.getAllCauses(ex), request.getDescription(false), SecurityExceptionMessage.AUTHENTICATION_FAILURE.getMessage(),
53+
errorDetails = new ErrorDetails(CustomExceptionUtils.getAllCauses(ex), request.getDescription(false), SecurityUserExceptionMessage.AUTHENTICATION_LOGIN_FAILURE.getMessage(),
5554
ex.getMessage(), ex.getStackTrace()[0].toString());
5655
}
5756
return new ResponseEntity<>(errorDetails, HttpStatus.UNAUTHORIZED);
@@ -60,13 +59,13 @@ public ResponseEntity<?> authenticationException(Exception ex, WebRequest reques
6059
@ExceptionHandler({UnauthorizedException.class, AccessDeniedException.class, DisabledException.class})
6160
public ResponseEntity<?> authorizationException(Exception ex, WebRequest request) {
6261
ErrorDetails errorDetails = new ErrorDetails(ex.getMessage() != null ? ex.getMessage() : CustomExceptionUtils.getAllCauses(ex), request.getDescription(false),
63-
ex.getMessage() == null || ex.getMessage().equals("Access Denied") ? SecurityExceptionMessage.AUTHORIZATION_FAILURE.getMessage() : ex.getMessage(), ex.getStackTrace()[0].toString());
62+
ex.getMessage() == null || ex.getMessage().equals("Access Denied") ? SecurityUserExceptionMessage.AUTHORIZATION_FAILURE.getMessage() : ex.getMessage(), ex.getStackTrace()[0].toString());
6463
return new ResponseEntity<>(errorDetails, HttpStatus.FORBIDDEN);
6564
}
6665
// Custom or Admin
6766
@ExceptionHandler({CustomAuthGuardException.class})
6867
public ResponseEntity<?> customAuthorizationException(Exception ex, WebRequest request) {
69-
ErrorDetails errorDetails = new ErrorDetails(CustomExceptionUtils.getAllCauses(ex), request.getDescription(false), SecurityExceptionMessage.AUTHORIZATION_FAILURE.getMessage(),
68+
ErrorDetails errorDetails = new ErrorDetails(CustomExceptionUtils.getAllCauses(ex), request.getDescription(false), SecurityUserExceptionMessage.AUTHORIZATION_FAILURE.getMessage(),
7069
ex.getMessage(), ex.getStackTrace()[0].toString());
7170
return new ResponseEntity<>(errorDetails, HttpStatus.FORBIDDEN);
7271
}

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/ErrorMessagesContainedExceptionForSecurityAuthentication.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/auth/AlreadySocialRegisteredException.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
package com.patternknife.securityhelper.oauth2.config.response.error.exception.auth;
22

3-
import org.springframework.http.HttpStatus;
4-
import org.springframework.web.bind.annotation.ResponseStatus;
5-
6-
// UNAUTHORIZED : 401
7-
// FORBIDDEN : 403
8-
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
93
public class AlreadySocialRegisteredException extends RuntimeException {
104
public AlreadySocialRegisteredException(String message) {
115
super(message);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.patternknife.securityhelper.oauth2.config.response.error.exception.auth;
2+
3+
import com.patternknife.securityhelper.oauth2.config.logger.dto.ErrorMessages;
4+
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
5+
6+
public class CustomOauth2AuthenticationException extends OAuth2AuthenticationException {
7+
protected ErrorMessages errorMessages;
8+
9+
public CustomOauth2AuthenticationException(){
10+
super("Default");
11+
}
12+
public CustomOauth2AuthenticationException(String message){
13+
super(message);
14+
errorMessages = ErrorMessages.builder().userMessage(message).message(message).build();
15+
}
16+
17+
public CustomOauth2AuthenticationException(ErrorMessages errorMessages){
18+
super(errorMessages.getMessage());
19+
this.errorMessages = errorMessages;
20+
}
21+
public ErrorMessages getErrorMessages() {
22+
return errorMessages;
23+
}
24+
25+
}

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/auth/OtpValueUnauthorizedException.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.patternknife.securityhelper.oauth2.config.response.error.exception.auth;
22

33

4-
public class OtpValueUnauthorizedException extends RuntimeException {
4+
import org.springframework.security.core.AuthenticationException;
5+
6+
public class OtpValueUnauthorizedException extends AuthenticationException {
57
public OtpValueUnauthorizedException(String message) {
68
super(message);
79
}

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/auth/SocialEmailNotProvidedException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import org.springframework.web.bind.annotation.ResponseStatus;
55

66

7-
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
7+
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
88
public class SocialEmailNotProvidedException extends RuntimeException {
99
public SocialEmailNotProvidedException(String message) {
1010
super(message);

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/auth/UnauthenticatedException.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/auth/UserDeletedException.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package com.patternknife.securityhelper.oauth2.config.response.error.exception.auth;
22

3-
import org.springframework.http.HttpStatus;
4-
import org.springframework.security.access.AccessDeniedException;
5-
import org.springframework.web.bind.annotation.ResponseStatus;
3+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
64

75

8-
@ResponseStatus(value = HttpStatus.FORBIDDEN)
9-
public class UserDeletedException extends AccessDeniedException {
6+
public class UserDeletedException extends UsernameNotFoundException {
107
public UserDeletedException(String message) {
118
super(message);
129
}

src/main/java/com/patternknife/securityhelper/oauth2/config/response/error/exception/data/customergift/CustomerGiftRequestStatusUpdateException.java

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)