Skip to content

Commit ed38308

Browse files
fix : important bugs on App-Token areas
1 parent 7a2b568 commit ed38308

File tree

14 files changed

+84
-65
lines changed

14 files changed

+84
-65
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<dependency>
88
<groupId>io.github.patternknife.securityhelper.oauth2.api</groupId>
99
<artifactId>spring-security-oauth2-password-jpa-implementation</artifactId>
10-
<version>3.0.0</version>
10+
<version>3.0.1</version>
1111
</dependency>
1212
```
1313
For v2, using the database tables from Spring Security 5 (only the database tables; follow the dependencies as above):

client/pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
77
<modelVersion>4.0.0</modelVersion>
88
<groupId>com.patternknife.securityhelper.oauth2.client</groupId>
99
<artifactId>spring-security-oauth2-password-jpa-implementation-client</artifactId>
10-
<version>3.0.0</version>
10+
<version>3.0.1</version>
1111
<packaging>jar</packaging>
1212

1313
<properties>
@@ -48,7 +48,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
4848
<dependency>
4949
<groupId>io.github.patternknife.securityhelper.oauth2.api</groupId>
5050
<artifactId>spring-security-oauth2-password-jpa-implementation</artifactId>
51-
<version>3.0.0</version>
51+
<version>3.0.1</version>
5252
</dependency>
5353

5454
<!-- DB -->

mysql/schema.sql

+12-10
Large diffs are not rendered by default.

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
88

99
<groupId>io.github.patternknife.securityhelper.oauth2.api</groupId>
1010
<artifactId>spring-security-oauth2-password-jpa-implementation</artifactId>
11-
<version>3.0.0</version>
11+
<version>3.0.1</version>
1212
<name>spring-security-oauth2-password-jpa-implementation</name>
1313
<description>The implementation of Spring Security 6 Spring Authorization Server for stateful OAuth2 Password Grant</description>
1414
<packaging>jar</packaging>

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/dao/KnifeAuthorizationRepository.java

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.springframework.data.jpa.repository.Modifying;
77
import org.springframework.data.jpa.repository.Query;
88
import org.springframework.data.repository.query.Param;
9+
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
910
import org.springframework.stereotype.Repository;
1011
import org.springframework.transaction.annotation.Transactional;
1112

@@ -90,6 +91,16 @@ public interface KnifeAuthorizationRepository extends JpaRepository<KnifeAuthori
9091

9192

9293
Optional<KnifeAuthorization> findByPrincipalNameAndRegisteredClientIdAndAccessTokenAppToken(String principalName, String registeredClientId, String accessTokenAppToken);
94+
95+
@Query("SELECT o FROM KnifeAuthorization o WHERE o.principalName = :principalName AND o.registeredClientId = :registeredClientId AND o.accessTokenAppToken = :accessTokenAppToken AND o.accessTokenExpiresAt > CURRENT_TIMESTAMP")
96+
Optional<KnifeAuthorization> findValidAuthorizationByPrincipalNameAndClientIdAndAppToken(
97+
@Param("principalName") String principalName,
98+
@Param("registeredClientId") String registeredClientId,
99+
@Param("accessTokenAppToken") String accessTokenAppToken
100+
);
101+
102+
103+
93104
Optional<List<KnifeAuthorization>> findListByPrincipalNameAndRegisteredClientIdAndAccessTokenAppToken(String principalName, String registeredClientId, String accessTokenAppToken);
94105
@Modifying
95106
@Transactional(rollbackFor=Exception.class)

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ public class KnifeAuthorization {
9090
private String refreshTokenValue;
9191

9292
@Column(name = "refresh_token_issued_at")
93-
private Instant refreshTokenIssuedAt;
93+
private LocalDateTime refreshTokenIssuedAt;
9494

9595
@Column(name = "refresh_token_expires_at")
96-
private Instant refreshTokenExpiresAt;
96+
private LocalDateTime refreshTokenExpiresAt;
9797

9898
@Lob
9999
@Column(name = "refresh_token_metadata")

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/provider/auth/endpoint/KnifeOauth2AuthenticationProvider.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.error.dto.ErrorMessages;
77
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.DefaultSecurityUserExceptionMessage;
88
import io.github.patternknife.securityhelper.oauth2.api.config.security.message.ISecurityUserExceptionMessageService;
9-
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.CommonOAuth2AuthorizationCycle;
9+
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.CommonOAuth2AuthorizationSaver;
1010
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.DefaultOauth2AuthenticationHashCheckService;
1111
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.persistence.authorization.OAuth2AuthorizationServiceImpl;
1212
import io.github.patternknife.securityhelper.oauth2.api.config.security.token.CustomGrantAuthenticationToken;
@@ -31,7 +31,7 @@
3131
@AllArgsConstructor
3232
public final class KnifeOauth2AuthenticationProvider implements AuthenticationProvider {
3333

34-
private final CommonOAuth2AuthorizationCycle commonOAuth2AuthorizationCycle;
34+
private final CommonOAuth2AuthorizationSaver commonOAuth2AuthorizationCycle;
3535
private final ConditionalDetailsService conditionalDetailsService;
3636
private final DefaultOauth2AuthenticationHashCheckService oauth2AuthenticationHashCheckService;
3737
private final OAuth2AuthorizationServiceImpl oAuth2AuthorizationService;
@@ -67,7 +67,7 @@ public Authentication authenticate(Authentication authentication)
6767
}
6868

6969

70-
OAuth2Authorization oAuth2Authorization = commonOAuth2AuthorizationCycle.run(userDetails, ((CustomGrantAuthenticationToken) authentication).getGrantType(), clientId, ((CustomGrantAuthenticationToken) authentication).getAdditionalParameters(), null);
70+
OAuth2Authorization oAuth2Authorization = commonOAuth2AuthorizationCycle.save(userDetails, ((CustomGrantAuthenticationToken) authentication).getGrantType(), clientId, ((CustomGrantAuthenticationToken) authentication).getAdditionalParameters(), null);
7171

7272
RegisteredClient registeredClient = oAuth2ClientAuthenticationToken.getRegisteredClient();
7373

Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
/*
1111
* Create = Build + Persist
1212
* */
13-
public interface CommonOAuth2AuthorizationCycle {
13+
public interface CommonOAuth2AuthorizationSaver {
1414

15-
OAuth2Authorization run(UserDetails userDetails, AuthorizationGrantType authorizationGrantType,
16-
String clientId, Map<String, Object> additionalParameters,
17-
@Nullable Map<String, Object> modifiableAdditionalParameters);
15+
OAuth2Authorization save(UserDetails userDetails, AuthorizationGrantType authorizationGrantType,
16+
String clientId, Map<String, Object> additionalParameters,
17+
@Nullable Map<String, Object> modifiableAdditionalParameters);
1818

1919
}
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@
2323

2424
@Service
2525
@RequiredArgsConstructor
26-
public class CommonOAuth2AuthorizationCycleImpl implements CommonOAuth2AuthorizationCycle {
26+
public class CommonOAuth2AuthorizationSaverImpl implements CommonOAuth2AuthorizationSaver {
2727

2828
private static final Logger logger = LoggerFactory.getLogger(KnifeSecurityLogConfig.class);
2929

3030
private final OAuth2AuthorizationBuildingService oAuth2AuthorizationBuildingService;
3131
private final OAuth2AuthorizationServiceImpl oAuth2AuthorizationService;
3232

3333
@Override
34-
public OAuth2Authorization run(UserDetails userDetails, AuthorizationGrantType authorizationGrantType, String clientId,
35-
Map<String, Object> additionalParameters, Map<String, Object> modifiableAdditionalParameters) {
34+
public OAuth2Authorization save(UserDetails userDetails, AuthorizationGrantType authorizationGrantType, String clientId,
35+
Map<String, Object> additionalParameters, Map<String, Object> modifiableAdditionalParameters) {
3636

3737
OAuth2Authorization oAuth2Authorization = oAuth2AuthorizationService.findByUserNameAndClientIdAndAppToken(userDetails.getUsername(), clientId, (String) additionalParameters.get(KnifeHttpHeaders.APP_TOKEN));
3838
if(authorizationGrantType.getValue().equals(AuthorizationGrantType.PASSWORD.getValue())){

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

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121

2222
import java.util.Map;
2323

24+
/*
25+
*
26+
* The term "build" means a "newly created OAuth2Authorization" (no update)
27+
*
28+
* */
2429
@Component
2530
@RequiredArgsConstructor
2631
public class OAuth2AuthorizationBuildingServiceImpl implements OAuth2AuthorizationBuildingService {

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

+23-29
Original file line numberDiff line numberDiff line change
@@ -42,61 +42,55 @@ public class OAuth2AuthorizationServiceImpl implements OAuth2AuthorizationServic
4242
/*
4343
1) Remove previous Access & Refresh Tokens for current OAuth2Authorization from Persistence
4444
2) Save Access & Refresh Tokens for current OAuth2Authorization into Persistence
45+
3) Only Insert (shouldBeNewAuthorization)
4546
*/
4647
@Override
47-
public void save(OAuth2Authorization authorization) {
48-
49-
String appTokenValue = authorization.getAttribute(KnifeHttpHeaders.APP_TOKEN);
50-
51-
if (authorization.getRefreshToken() != null) {
52-
if (findByToken(authorization.getRefreshToken().getToken().getTokenValue(), OAuth2TokenType.REFRESH_TOKEN) != null) {
53-
this.remove(authorization);
54-
}
55-
}
56-
if (authorization.getAccessToken() != null) {
57-
if (findByToken(authorization.getAccessToken().getToken().getTokenValue(), OAuth2TokenType.ACCESS_TOKEN) != null) {
58-
this.remove(authorization);
59-
}
60-
}
48+
public void save(OAuth2Authorization shouldBeNewAuthorization) {
6149

6250

6351
KnifeAuthorization knifeAuthorization = new KnifeAuthorization();
6452

6553

66-
knifeAuthorization.setId(authorization.getId());
54+
knifeAuthorization.setId(shouldBeNewAuthorization.getId());
6755

68-
knifeAuthorization.setPrincipalName(authorization.getPrincipalName());
69-
knifeAuthorization.setRegisteredClientId(authorization.getAttribute("client_id"));
70-
knifeAuthorization.setAccessTokenValue(authorization.getAccessToken().getToken().getTokenValue());
71-
knifeAuthorization.setRefreshTokenValue(authorization.getRefreshToken().getToken().getTokenValue());
56+
knifeAuthorization.setPrincipalName(shouldBeNewAuthorization.getPrincipalName());
57+
knifeAuthorization.setRegisteredClientId(shouldBeNewAuthorization.getAttribute("client_id"));
58+
knifeAuthorization.setAccessTokenValue(shouldBeNewAuthorization.getAccessToken().getToken().getTokenValue());
59+
knifeAuthorization.setRefreshTokenValue(shouldBeNewAuthorization.getRefreshToken().getToken().getTokenValue());
7260

61+
String appTokenValue = shouldBeNewAuthorization.getAttribute(KnifeHttpHeaders.APP_TOKEN);
7362
if (appTokenValue != null) {
7463
knifeAuthorization.setAccessTokenAppToken(appTokenValue);
7564
}
7665

77-
String userAgentValue = authorization.getAttribute(KnifeHttpHeaders.USER_AGENT);
66+
String userAgentValue = shouldBeNewAuthorization.getAttribute(KnifeHttpHeaders.USER_AGENT);
7867
if (!StringUtils.isEmpty(userAgentValue)) {
7968
knifeAuthorization.setAccessTokenUserAgent(userAgentValue);
8069
}
8170

82-
String remoteIp = authorization.getAttribute(KnifeHttpHeaders.X_Forwarded_For);
71+
String remoteIp = shouldBeNewAuthorization.getAttribute(KnifeHttpHeaders.X_Forwarded_For);
8372
if (remoteIp != null) {
8473
knifeAuthorization.setAccessTokenRemoteIp(remoteIp);
8574
}
8675

87-
knifeAuthorization.setAttributes(authorization);
88-
knifeAuthorization.setAccessTokenType(authorization.getAuthorizationGrantType().getValue());
89-
knifeAuthorization.setAccessTokenScopes(String.join(",", authorization.getAuthorizedScopes()));
90-
76+
knifeAuthorization.setAttributes(shouldBeNewAuthorization);
77+
knifeAuthorization.setAccessTokenType(shouldBeNewAuthorization.getAuthorizationGrantType().getValue());
78+
knifeAuthorization.setAccessTokenScopes(String.join(",", shouldBeNewAuthorization.getAuthorizedScopes()));
9179

80+
// Token Expiration
9281
knifeAuthorization.setAccessTokenIssuedAt(LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()));
82+
if (shouldBeNewAuthorization.getAccessToken().getToken().getExpiresAt() != null) {
83+
knifeAuthorization.setAccessTokenExpiresAt(LocalDateTime.ofInstant(shouldBeNewAuthorization.getAccessToken().getToken().getExpiresAt(), ZoneId.systemDefault()));
84+
}
9385

94-
if (authorization.getAccessToken().getToken().getExpiresAt() != null) {
95-
knifeAuthorization.setAccessTokenExpiresAt(LocalDateTime.ofInstant(authorization.getAccessToken().getToken().getExpiresAt(), ZoneId.systemDefault()));
86+
// Token Expiration
87+
knifeAuthorization.setRefreshTokenIssuedAt(LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()));
88+
if (shouldBeNewAuthorization.getRefreshToken().getToken().getExpiresAt() != null) {
89+
knifeAuthorization.setRefreshTokenExpiresAt(LocalDateTime.ofInstant(shouldBeNewAuthorization.getRefreshToken().getToken().getExpiresAt(), ZoneId.systemDefault()));
9690
}
9791

98-
knifeAuthorizationRepository.save(knifeAuthorization);
9992

93+
knifeAuthorizationRepository.save(knifeAuthorization);
10094

10195
if(securityPointCut != null){
10296
securityPointCut.afterTokensSaved(knifeAuthorization, null);
@@ -166,7 +160,7 @@ public OAuth2Authorization findByToken(@NotEmpty String tokenValue, @Nullable OA
166160
* Same ( org.springframework.security.core.userdetails : userName + spring-authorization-server : principalName )
167161
* */
168162
public @Nullable OAuth2Authorization findByUserNameAndClientIdAndAppToken(@NotEmpty String userName, @NotEmpty String clientId, @Nullable String appToken) {
169-
return findOAuth2AuthorizationByAccessTokenValueSafely(() -> knifeAuthorizationRepository.findByPrincipalNameAndRegisteredClientIdAndAccessTokenAppToken(userName, clientId, appToken).map(KnifeAuthorization::getAttributes),
163+
return findOAuth2AuthorizationByAccessTokenValueSafely(() -> knifeAuthorizationRepository.findValidAuthorizationByPrincipalNameAndClientIdAndAppToken(userName, clientId, appToken).map(KnifeAuthorization::getAttributes),
170164
e -> {
171165
knifeAuthorizationRepository.findListByPrincipalNameAndRegisteredClientIdAndAccessTokenAppToken(userName, clientId, appToken).ifPresent(knifeAuthorizationRepository::deleteAll);
172166
knifeAuthorizationRepository.deleteByPrincipalNameAndRegisteredClientIdAndAccessTokenAppToken(userName, clientId, appToken);

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/serivce/persistence/client/RegisteredClientRepositoryImpl.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -130,20 +130,27 @@ private RegisteredClient mapToRegisteredClient(KnifeClient detail) {
130130
.map(AuthorizationGrantType::new)
131131
.collect(Collectors.toSet());
132132

133+
// Assuming getTokenSettings() returns a map-like structure for token settings.
134+
Map<String, Object> tokenSettings = parseMap(detail.getTokenSettings());
135+
136+
// Extract token time-to-live values from tokenSettings (assuming they are stored as strings or numbers)
137+
Duration accessTokenTimeToLive = Duration.ofSeconds(Long.parseLong(tokenSettings.get("access_token_time_to_live").toString()));
138+
Duration refreshTokenTimeToLive = Duration.ofSeconds(Long.parseLong(tokenSettings.get("refresh_token_time_to_live").toString()));
139+
133140

134141
return RegisteredClient.withId(UUID.randomUUID().toString())
135142
.clientId(detail.getClientId())
136143
.clientSecret(detail.getClientSecret())
137-
.clientName(detail.getClientId()) // Adjust according to your needs.
144+
.clientName(detail.getClientId())
138145
.clientAuthenticationMethods(authenticationMethods ->
139146
authenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) // Adjust based on your entity
140147
.authorizationGrantTypes(grantTypes -> grantTypes.addAll(grantTypesSet))
141148
.scopes(scopes -> scopes.addAll(scopesSet))
142149
.redirectUri("")
143150
.tokenSettings(TokenSettings.builder()
144151
.accessTokenFormat(OAuth2TokenFormat.REFERENCE)
145-
.accessTokenTimeToLive(Duration.ofSeconds(3600))
146-
.refreshTokenTimeToLive(Duration.ofSeconds(9900))
152+
.accessTokenTimeToLive(accessTokenTimeToLive)
153+
.refreshTokenTimeToLive(refreshTokenTimeToLive)
147154
.build())
148155
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()) // Adjust accordingly
149156
.build();

src/main/java/io/github/patternknife/securityhelper/oauth2/api/config/security/server/ServerConfig.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.auth.authentication.DefaultAuthenticationFailureHandlerImpl;
1212
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.auth.authentication.DefaultAuthenticationSuccessHandlerImpl;
1313
import io.github.patternknife.securityhelper.oauth2.api.config.security.response.resource.authentication.DefaultAuthenticationEntryPoint;
14-
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.CommonOAuth2AuthorizationCycle;
14+
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.CommonOAuth2AuthorizationSaver;
1515
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.DefaultOauth2AuthenticationHashCheckService;
1616
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.IOauth2AuthenticationHashCheckService;
1717
import io.github.patternknife.securityhelper.oauth2.api.config.security.serivce.persistence.authorization.OAuth2AuthorizationServiceImpl;
@@ -67,7 +67,7 @@ public OAuth2TokenGenerator<OAuth2Token> tokenGenerator() {
6767
@Order(1)
6868
public SecurityFilterChain authorizationServerSecurityFilterChain(
6969
HttpSecurity http,
70-
CommonOAuth2AuthorizationCycle commonOAuth2AuthorizationCycle,
70+
CommonOAuth2AuthorizationSaver commonOAuth2AuthorizationCycle,
7171
OAuth2AuthorizationServiceImpl authorizationService,
7272
ConditionalDetailsService conditionalDetailsService,
7373
DefaultOauth2AuthenticationHashCheckService oauth2AuthenticationHashCheckService,

0 commit comments

Comments
 (0)