Skip to content

Commit a223fc3

Browse files
refactor : utils, saver
1 parent 6435ad2 commit a223fc3

File tree

16 files changed

+85
-118
lines changed

16 files changed

+85
-118
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.exception.KnifeOauth2AuthenticationException;
88
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.DefaultSecurityUserExceptionMessage;
99
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.ISecurityUserExceptionMessageService;
10-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.OrderConstants;
10+
import io.github.patternknife.securityhelper.oauth2.api.config.util.OrderConstants;
1111
import lombok.RequiredArgsConstructor;;
1212
import org.springframework.core.annotation.Order;
1313
import org.springframework.http.HttpStatus;

client/src/test/java/com/patternknife/securityhelper/oauth2/client/integration/auth/CustomerIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.patternknife.securityhelper.oauth2.client.integration.auth;
22

33

4-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.KnifeHttpHeaders;
4+
import io.github.patternknife.securityhelper.oauth2.api.config.util.KnifeHttpHeaders;
55
import com.patternknife.securityhelper.oauth2.client.config.securityimpl.message.CustomSecurityUserExceptionMessage;
66
import jakarta.xml.bind.DatatypeConverter;
77
import lombok.SneakyThrows;

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/converter/auth/endpoint/AuthorizationCodeAuthenticationConverter.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package io.github.patternknife.securityhelper.oauth2.api.config.security.converter.auth.endpoint;
22

33

4-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.RequestOAuth2Distiller;
4+
import io.github.patternknife.securityhelper.oauth2.api.config.util.RequestOAuth2Distiller;
55
import jakarta.servlet.http.HttpServletRequest;
66
import lombok.RequiredArgsConstructor;
77
import org.springframework.lang.Nullable;
@@ -11,7 +11,6 @@
1111
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
1212
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
1313
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
14-
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
1514
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
1615
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
1716
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/converter/auth/endpoint/AuthorizationCodeRequestAuthenticationConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
import io.github.patternknife.securityhelper.oauth2.api.config.security.dao.KnifeAuthorizationConsentRepository;
5-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.RequestOAuth2Distiller;
5+
import io.github.patternknife.securityhelper.oauth2.api.config.util.RequestOAuth2Distiller;
66
import jakarta.servlet.http.HttpServletRequest;
77
import lombok.RequiredArgsConstructor;
88
import org.springframework.lang.Nullable;

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/converter/auth/endpoint/PasswordAuthenticationConverter.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package io.github.patternknife.securityhelper.oauth2.api.config.security.converter.auth.endpoint;
22

3-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.RequestOAuth2Distiller;
3+
import io.github.patternknife.securityhelper.oauth2.api.config.util.RequestOAuth2Distiller;
44
import io.github.patternknife.securityhelper.oauth2.api.config.security.token.CustomGrantAuthenticationToken;
55
import jakarta.servlet.http.HttpServletRequest;
66
import lombok.RequiredArgsConstructor;
77
import org.springframework.security.core.Authentication;
88
import org.springframework.security.core.context.SecurityContextHolder;
99
import org.springframework.security.oauth2.core.AuthorizationGrantType;
10-
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
11-
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
1210
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
1311
import org.springframework.security.web.authentication.AuthenticationConverter;
1412

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/entity/KnifeAuthorization.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package io.github.patternknife.securityhelper.oauth2.api.config.security.entity;
22

33
import io.github.patternknife.securityhelper.oauth2.api.config.security.token.generator.CustomAuthenticationKeyGenerator;
4-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.SerializableObjectConverter;
4+
import io.github.patternknife.securityhelper.oauth2.api.config.util.SerializableObjectConverter;
55
import jakarta.persistence.*;
66

77
import lombok.Getter;

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/response/error/handler/SecurityKnifeExceptionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.exception.KnifeOauth2AuthenticationException;
5-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.OrderConstants;
5+
import io.github.patternknife.securityhelper.oauth2.api.config.util.OrderConstants;
66
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.dto.SecurityKnifeErrorResponsePayload;
77

88
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.DefaultSecurityUserExceptionMessage;

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/serivce/CommonOAuth2AuthorizationSaverImpl.java

Lines changed: 47 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,24 @@
22

33

44
import io.github.patternknife.securityhelper.oauth2.api.config.logger.KnifeSecurityLogConfig;
5+
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.DefaultSecurityUserExceptionMessage;
6+
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.ISecurityUserExceptionMessageService;
7+
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.dto.ErrorMessages;
58
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.exception.KnifeOauth2AuthenticationException;
6-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.KnifeHttpHeaders;
9+
import io.github.patternknife.securityhelper.oauth2.api.config.util.KnifeHttpHeaders;
710
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.authentication.OAuth2AuthorizationBuildingService;
811
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.persistence.authorization.OAuth2AuthorizationServiceImpl;
912

13+
import io.github.patternknife.securityhelper.oauth2.api.config.util.SecurityExceptionUtils;
1014
import jakarta.validation.constraints.NotNull;
1115
import lombok.RequiredArgsConstructor;
1216
import org.slf4j.Logger;
1317
import org.slf4j.LoggerFactory;
14-
import org.springframework.dao.DataIntegrityViolationException;
18+
1519
import org.springframework.security.core.userdetails.UserDetails;
1620
import org.springframework.security.oauth2.core.AuthorizationGrantType;
1721
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
1822
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
19-
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
2023
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
2124
import org.springframework.stereotype.Service;
2225

@@ -31,118 +34,63 @@ public class CommonOAuth2AuthorizationSaverImpl implements CommonOAuth2Authoriza
3134

3235
private final OAuth2AuthorizationBuildingService oAuth2AuthorizationBuildingService;
3336
private final OAuth2AuthorizationServiceImpl oAuth2AuthorizationService;
37+
private final ISecurityUserExceptionMessageService iSecurityUserExceptionMessageService;
3438

39+
/*
40+
* While the Spring Authorization Server is generally not expected to cause duplicate exceptions,
41+
* I have observed such errors in the past. This is a preventive measure to handle potential issues gracefully.
42+
*/
3543
@Override
3644
public @NotNull OAuth2Authorization save(UserDetails userDetails, AuthorizationGrantType authorizationGrantType, String clientId,
3745
Map<String, Object> additionalParameters, Map<String, Object> modifiableAdditionalParameters) {
3846

39-
OAuth2Authorization oAuth2Authorization = null;
4047
if (authorizationGrantType.getValue().equals(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())) {
48+
return SecurityExceptionUtils.retryOnDuplicateException(() -> {
49+
OAuth2Authorization oAuth2Authorization = oAuth2AuthorizationBuildingService.build(
50+
userDetails, authorizationGrantType, clientId, additionalParameters, null);
51+
oAuth2AuthorizationService.save(oAuth2Authorization);
52+
return oAuth2Authorization;
53+
}, 5, logger, "[Authorization Code] An error occurred with the Key during the execution of persistOAuth2Authorization for " + userDetails.getUsername());
54+
}
4155

42-
int retryLogin = 0;
43-
while (retryLogin < 5) {
44-
try {
45-
oAuth2Authorization = oAuth2AuthorizationBuildingService.build(
46-
userDetails,
47-
authorizationGrantType,
48-
clientId,
49-
additionalParameters,
50-
null
51-
);
52-
oAuth2AuthorizationService.save(oAuth2Authorization);
53-
return oAuth2Authorization;
54-
} catch (DataIntegrityViolationException e) {
55-
logger.error("[Authorization Code] An error occurred with the Key during the execution of persistOAuth2Authorization for " + userDetails.getUsername() + "... Retrying up to 5 times.... (Count: " + retryLogin + ") - " + e.getMessage());
56-
retryLogin += 1;
57-
if (retryLogin == 4) {
58-
throw e;
59-
}
60-
}
56+
OAuth2Authorization oAuth2Authorization = oAuth2AuthorizationService.findByUserNameAndClientIdAndAppToken(
57+
userDetails.getUsername(), clientId, (String) additionalParameters.get(KnifeHttpHeaders.APP_TOKEN));
58+
59+
if (authorizationGrantType.getValue().equals(AuthorizationGrantType.PASSWORD.getValue())) {
60+
if (oAuth2Authorization == null || oAuth2Authorization.getAccessToken().isExpired()) {
61+
return SecurityExceptionUtils.retryOnDuplicateException(() -> {
62+
OAuth2Authorization authorization = oAuth2AuthorizationBuildingService.build(
63+
userDetails, authorizationGrantType, clientId, additionalParameters, null);
64+
oAuth2AuthorizationService.save(authorization);
65+
return authorization;
66+
}, 5, logger, "[Access Token] An error occurred with the Key during the execution of persistOAuth2Authorization for " + userDetails.getUsername());
6167
}
62-
}else{
63-
oAuth2Authorization = oAuth2AuthorizationService.findByUserNameAndClientIdAndAppToken(userDetails.getUsername(), clientId, (String) additionalParameters.get(KnifeHttpHeaders.APP_TOKEN));
64-
65-
if(authorizationGrantType.getValue().equals(AuthorizationGrantType.PASSWORD.getValue())){
66-
if (oAuth2Authorization == null || oAuth2Authorization.getAccessToken().isExpired()) {
67-
int retryLogin = 0;
68-
while (retryLogin < 5) {
69-
try {
70-
oAuth2Authorization = oAuth2AuthorizationBuildingService.build(
71-
userDetails, authorizationGrantType, clientId, additionalParameters, null);
72-
73-
oAuth2AuthorizationService.save(oAuth2Authorization);
74-
75-
return oAuth2Authorization;
68+
} else if (authorizationGrantType.getValue().equals(AuthorizationGrantType.REFRESH_TOKEN.getValue())) {
69+
return SecurityExceptionUtils.retryOnDuplicateException(() -> {
70+
String refreshTokenValue = (String) (additionalParameters.containsKey("refresh_token") ? additionalParameters.get("refresh_token")
71+
: modifiableAdditionalParameters.get("refresh_token"));
7672

77-
} catch (DataIntegrityViolationException e) {
73+
OAuth2Authorization oAuth2AuthorizationFromRefreshToken = oAuth2AuthorizationService.findByToken(refreshTokenValue, OAuth2TokenType.REFRESH_TOKEN);
7874

79-
logger.error("[Access Token] An error occurred with the Key during the execution of persistOAuth2Authorization for " + userDetails.getUsername() + "... Retrying up to 5 times.... (Count: " + retryLogin + ") - " + e.getMessage());
80-
retryLogin += 1;
81-
82-
if(retryLogin == 4){
83-
throw e;
84-
}
85-
86-
}
87-
}
88-
}else{
89-
// Keep the previous OAuth2Authorization
75+
if (oAuth2AuthorizationFromRefreshToken == null || oAuth2AuthorizationFromRefreshToken.getRefreshToken().isExpired()) {
76+
oAuth2AuthorizationService.remove(oAuth2AuthorizationFromRefreshToken);
77+
throw new KnifeOauth2AuthenticationException("Refresh Token Expired.");
9078
}
91-
}else if(authorizationGrantType.getValue().equals(AuthorizationGrantType.REFRESH_TOKEN.getValue())){
92-
int retryLogin = 0;
93-
while (retryLogin < 5) {
94-
try {
95-
String refreshTokenValue = null;
96-
if(additionalParameters.containsKey("refresh_token")){
97-
refreshTokenValue = (String) additionalParameters.get("refresh_token");
98-
}else{
99-
assert modifiableAdditionalParameters != null;
100-
refreshTokenValue = (String)modifiableAdditionalParameters.get("refresh_token");
101-
}
102-
assert refreshTokenValue != null;
103-
104-
105-
OAuth2Authorization oAuth2AuthorizationFromRefreshToken = oAuth2AuthorizationService.findByToken(refreshTokenValue, OAuth2TokenType.REFRESH_TOKEN);
106-
107-
if(oAuth2AuthorizationFromRefreshToken == null){
108-
throw new KnifeOauth2AuthenticationException("Refresh Token Expired.");
109-
}
110-
if(oAuth2AuthorizationFromRefreshToken.getRefreshToken() == null || oAuth2AuthorizationFromRefreshToken.getRefreshToken().isExpired()){
111-
oAuth2AuthorizationService.remove(oAuth2AuthorizationFromRefreshToken);
112-
throw new KnifeOauth2AuthenticationException("Refresh Token Expired.");
113-
}
114-
115-
OAuth2RefreshToken shouldBePreservedRefreshToken = oAuth2AuthorizationFromRefreshToken.getRefreshToken().getToken();
11679

117-
oAuth2AuthorizationService.remove(oAuth2AuthorizationFromRefreshToken);
80+
OAuth2RefreshToken shouldBePreservedRefreshToken = oAuth2AuthorizationFromRefreshToken.getRefreshToken().getToken();
81+
oAuth2AuthorizationService.remove(oAuth2AuthorizationFromRefreshToken);
11882

119-
oAuth2Authorization = oAuth2AuthorizationBuildingService.build(
120-
userDetails, authorizationGrantType, clientId, additionalParameters, shouldBePreservedRefreshToken);
83+
OAuth2Authorization authorization = oAuth2AuthorizationBuildingService.build(
84+
userDetails, authorizationGrantType, clientId, additionalParameters, shouldBePreservedRefreshToken);
85+
oAuth2AuthorizationService.save(authorization);
86+
return authorization;
12187

122-
oAuth2AuthorizationService.save(oAuth2Authorization);
123-
124-
return oAuth2Authorization;
125-
126-
} catch (DataIntegrityViolationException e) {
127-
128-
logger.error("[Refresh Token] An error occurred with the Key during the execution of persistOAuth2Authorization for " + userDetails.getUsername() + "... Retrying up to 5 times.... (Count: " + retryLogin + ") - " + e.getMessage());
129-
retryLogin += 1;
130-
131-
if(retryLogin == 4){
132-
throw e;
133-
}
134-
}
135-
}
136-
137-
}else{
138-
// TO DO. Exception & Message that should be thrown
139-
}
88+
}, 5, logger, "[Refresh Token] An error occurred with the Key during the execution of persistOAuth2Authorization for " + userDetails.getUsername());
89+
} else {
90+
throw new KnifeOauth2AuthenticationException(ErrorMessages.builder().message("Wrong grant type from Req : " + authorizationGrantType.getValue()).userMessage(iSecurityUserExceptionMessageService.getUserMessage(DefaultSecurityUserExceptionMessage.AUTHENTICATION_WRONG_GRANT_TYPE)).build());
14091
}
141-
142-
143-
14492

14593
return oAuth2Authorization;
146-
14794
}
14895
}
96+

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/serivce/persistence/authorization/OAuth2AuthorizationServiceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import io.github.patternknife.securityhelper.oauth2.api.config.security.dao.KnifeAuthorizationRepository;
66
import io.github.patternknife.securityhelper.oauth2.api.config.security.entity.KnifeAuthorization;
77
import io.github.patternknife.securityhelper.oauth2.api.config.security.token.generator.CustomAuthenticationKeyGenerator;
8-
import io.github.patternknife.securityhelper.oauth2.api.config.security.util.KnifeHttpHeaders;
8+
import io.github.patternknife.securityhelper.oauth2.api.config.util.KnifeHttpHeaders;
99

1010
import jakarta.annotation.Nullable;
1111
import jakarta.validation.constraints.NotEmpty;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.github.patternknife.securityhelper.oauth2.api.config.security.util;
1+
package io.github.patternknife.securityhelper.oauth2.api.config.util;
22

33
import org.springframework.http.HttpHeaders;
44

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.github.patternknife.securityhelper.oauth2.api.config.security.util;
1+
package io.github.patternknife.securityhelper.oauth2.api.config.util;
22

33
public class OrderConstants {
44
public static final int SECURITY_KNIFE_EXCEPTION_HANDLER_ORDER = -9977;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.github.patternknife.securityhelper.oauth2.api.config.security.util;
1+
package io.github.patternknife.securityhelper.oauth2.api.config.util;
22

33

44
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.exception.KnifeOauth2AuthenticationException;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.github.patternknife.securityhelper.oauth2.api.config.util;
2+
3+
import org.slf4j.Logger;
4+
import org.springframework.dao.DataIntegrityViolationException;
5+
6+
import java.util.function.Supplier;
7+
8+
public class SecurityExceptionUtils {
9+
10+
public static <T> T retryOnDuplicateException(Supplier<T> action, int maxRetries, Logger logger, String errorMessage) {
11+
int attempt = 0;
12+
while (attempt < maxRetries) {
13+
try {
14+
return action.get();
15+
} catch (DataIntegrityViolationException e) {
16+
logger.error(String.format("%s... Retrying up to %d times.... (Count: %d) - %s", errorMessage, maxRetries, attempt, e.getMessage()));
17+
attempt++;
18+
if (attempt == maxRetries) {
19+
throw e;
20+
}
21+
}
22+
}
23+
return null;
24+
}
25+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.github.patternknife.securityhelper.oauth2.api.config.security.util;
1+
package io.github.patternknife.securityhelper.oauth2.api.config.util;
22

33

44
import org.apache.tomcat.util.codec.binary.Base64;

0 commit comments

Comments
 (0)