Skip to content

Commit a19daab

Browse files
committed
Add OAuth2TokenIssuerUtil class to generate access and refresh tokens
This will be replaced with a OAuth2TokenIssuer interface and implementation later.
1 parent f4b219f commit a19daab

File tree

4 files changed

+97
-119
lines changed

4 files changed

+97
-119
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java

+4-43
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@
2424
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
2525
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
2626
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
27-
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
28-
import org.springframework.security.oauth2.jose.JoseHeader;
29-
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
30-
import org.springframework.security.oauth2.jwt.Jwt;
31-
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
3227
import org.springframework.security.oauth2.jwt.JwtEncoder;
3328
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
3429
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationAttributeNames;
@@ -42,14 +37,6 @@
4237
import org.springframework.util.Assert;
4338
import org.springframework.util.StringUtils;
4439

45-
import java.net.MalformedURLException;
46-
import java.net.URI;
47-
import java.net.URL;
48-
import java.time.Duration;
49-
import java.time.Instant;
50-
import java.time.temporal.ChronoUnit;
51-
import java.util.Collections;
52-
import java.util.UUID;
5340
import java.util.Set;
5441

5542
/**
@@ -130,42 +117,16 @@ public Authentication authenticate(Authentication authentication) throws Authent
130117
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
131118
}
132119

133-
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
134-
135-
// TODO Allow configuration for issuer claim
136-
URL issuer = null;
137-
try {
138-
issuer = URI.create("https://oauth2.provider.com").toURL();
139-
} catch (MalformedURLException e) { }
140-
141-
Instant issuedAt = Instant.now();
142-
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); // TODO Allow configuration for access token time-to-live
143120
Set<String> authorizedScopes = authorization.getAttribute(OAuth2AuthorizationAttributeNames.AUTHORIZED_SCOPES);
144-
145-
JwtClaimsSet jwtClaimsSet = JwtClaimsSet.withClaims()
146-
.issuer(issuer)
147-
.subject(authorization.getPrincipalName())
148-
.audience(Collections.singletonList(registeredClient.getClientId()))
149-
.issuedAt(issuedAt)
150-
.expiresAt(expiresAt)
151-
.notBefore(issuedAt)
152-
.claim(OAuth2ParameterNames.SCOPE, authorizedScopes)
153-
.build();
154-
155-
Jwt jwt = this.jwtEncoder.encode(joseHeader, jwtClaimsSet);
156-
157-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
158-
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaim(OAuth2ParameterNames.SCOPE));
121+
OAuth2AccessToken accessToken = OAuth2TokenIssuerUtil
122+
.issueJwtAccessToken(this.jwtEncoder, clientPrincipal.getName(), registeredClient.getClientId(), authorizedScopes);
159123

160124
OAuth2Tokens.Builder tokensBuilder = OAuth2Tokens.from(authorization.getTokens())
161125
.accessToken(accessToken);
162126

163127
OAuth2RefreshToken refreshToken = null;
164128
if (registeredClient.getTokenSettings().enableRefreshTokens()) {
165-
Duration refreshTokenTimeToLive = registeredClient.getTokenSettings().refreshTokenTimeToLive();
166-
Instant refreshTokenExpiresAt = refreshTokenTimeToLive == Duration.ZERO ? null : issuedAt.plus(refreshTokenTimeToLive);
167-
168-
refreshToken = new OAuth2RefreshToken(UUID.randomUUID().toString(), issuedAt, refreshTokenExpiresAt);
129+
refreshToken = OAuth2TokenIssuerUtil.issueRefreshToken(registeredClient.getTokenSettings().refreshTokenTimeToLive());
169130
tokensBuilder.refreshToken(refreshToken);
170131
}
171132

@@ -174,7 +135,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
174135

175136
authorization = OAuth2Authorization.from(authorization)
176137
.tokens(tokens)
177-
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
138+
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, accessToken)
178139
.build();
179140
this.authorizationService.save(authorization);
180141

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java

+3-37
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@
2222
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2323
import org.springframework.security.oauth2.core.OAuth2Error;
2424
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
25-
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
26-
import org.springframework.security.oauth2.jose.JoseHeader;
27-
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
28-
import org.springframework.security.oauth2.jwt.Jwt;
29-
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
3025
import org.springframework.security.oauth2.jwt.JwtEncoder;
3126
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
3227
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationAttributeNames;
@@ -36,12 +31,6 @@
3631
import org.springframework.util.Assert;
3732
import org.springframework.util.CollectionUtils;
3833

39-
import java.net.MalformedURLException;
40-
import java.net.URI;
41-
import java.net.URL;
42-
import java.time.Instant;
43-
import java.time.temporal.ChronoUnit;
44-
import java.util.Collections;
4534
import java.util.LinkedHashSet;
4635
import java.util.Set;
4736
import java.util.stream.Collectors;
@@ -101,34 +90,11 @@ public Authentication authenticate(Authentication authentication) throws Authent
10190
scopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes());
10291
}
10392

104-
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
105-
106-
// TODO Allow configuration for issuer claim
107-
URL issuer = null;
108-
try {
109-
issuer = URI.create("https://oauth2.provider.com").toURL();
110-
} catch (MalformedURLException e) { }
111-
112-
Instant issuedAt = Instant.now();
113-
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); // TODO Allow configuration for access token time-to-live
114-
115-
JwtClaimsSet jwtClaimsSet = JwtClaimsSet.withClaims()
116-
.issuer(issuer)
117-
.subject(clientPrincipal.getName())
118-
.audience(Collections.singletonList(registeredClient.getClientId()))
119-
.issuedAt(issuedAt)
120-
.expiresAt(expiresAt)
121-
.notBefore(issuedAt)
122-
.claim(OAuth2ParameterNames.SCOPE, scopes)
123-
.build();
124-
125-
Jwt jwt = this.jwtEncoder.encode(joseHeader, jwtClaimsSet);
126-
127-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
128-
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes);
93+
OAuth2AccessToken accessToken = OAuth2TokenIssuerUtil
94+
.issueJwtAccessToken(this.jwtEncoder, clientPrincipal.getName(), registeredClient.getClientId(), scopes);
12995

13096
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(registeredClient)
131-
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
97+
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, accessToken)
13298
.principalName(clientPrincipal.getName())
13399
.tokens(OAuth2Tokens.builder().accessToken(accessToken).build())
134100
.build();

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java

+12-39
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,8 @@
1616

1717
package org.springframework.security.oauth2.server.authorization.authentication;
1818

19-
import java.net.MalformedURLException;
20-
import java.net.URI;
21-
import java.net.URL;
2219
import java.time.Instant;
23-
import java.time.temporal.ChronoUnit;
24-
import java.util.Collections;
2520
import java.util.Set;
26-
import java.util.UUID;
2721

2822
import org.springframework.security.authentication.AuthenticationProvider;
2923
import org.springframework.security.core.Authentication;
@@ -33,17 +27,13 @@
3327
import org.springframework.security.oauth2.core.OAuth2Error;
3428
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
3529
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
36-
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
37-
import org.springframework.security.oauth2.jose.JoseHeader;
38-
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
39-
import org.springframework.security.oauth2.jwt.Jwt;
40-
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
4130
import org.springframework.security.oauth2.jwt.JwtEncoder;
4231
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
4332
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationAttributeNames;
4433
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
4534
import org.springframework.security.oauth2.server.authorization.TokenType;
4635
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
36+
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
4737
import org.springframework.security.oauth2.server.authorization.token.OAuth2Tokens;
4838

4939
/**
@@ -111,39 +101,22 @@ public Authentication authenticate(Authentication authentication) throws Authent
111101
refreshTokenScopes = approvedScopes;
112102
}
113103

114-
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
104+
OAuth2AccessToken accessToken = OAuth2TokenIssuerUtil
105+
.issueJwtAccessToken(this.jwtEncoder, clientPrincipal.getName(), registeredClient.getClientId(), refreshTokenScopes);
115106

116-
// TODO Allow configuration for issuer claim
117-
URL issuer = null;
118-
try {
119-
issuer = URI.create("https://oauth2.provider.com").toURL();
120-
} catch (MalformedURLException e) { }
121-
122-
Instant issuedAt = Instant.now();
123-
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); // TODO Allow configuration for access token time-to-live
124-
125-
JwtClaimsSet jwtClaimsSet = JwtClaimsSet.withClaims()
126-
.issuer(issuer)
127-
.subject(clientPrincipal.getName())
128-
.audience(Collections.singletonList(registeredClient.getClientId()))
129-
.issuedAt(issuedAt)
130-
.expiresAt(expiresAt)
131-
.notBefore(issuedAt)
132-
.claim(OAuth2ParameterNames.SCOPE, refreshTokenScopes)
133-
.build();
134-
135-
Jwt jwt = this.jwtEncoder.encode(joseHeader, jwtClaimsSet);
136-
137-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
138-
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), refreshTokenScopes);
139-
140-
OAuth2RefreshToken refreshToken = clientPrincipal.getRegisteredClient().getTokenSettings().reuseRefreshTokens() ?
141-
authorization.getTokens().getRefreshToken() : new OAuth2RefreshToken(UUID.randomUUID().toString(), issuedAt);
107+
TokenSettings tokenSettings = registeredClient.getTokenSettings();
108+
OAuth2RefreshToken refreshToken;
109+
if (tokenSettings.reuseRefreshTokens()) {
110+
refreshToken = authorization.getTokens().getRefreshToken();
111+
} else {
112+
refreshToken = OAuth2TokenIssuerUtil.issueRefreshToken(tokenSettings.refreshTokenTimeToLive());
113+
}
142114

143115
authorization = OAuth2Authorization.from(authorization)
144-
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
116+
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, accessToken)
145117
.tokens(OAuth2Tokens.builder().accessToken(accessToken).refreshToken(refreshToken).build())
146118
.build();
119+
147120
this.authorizationService.save(authorization);
148121

149122
return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.oauth2.server.authorization.authentication;
18+
19+
import java.net.MalformedURLException;
20+
import java.net.URI;
21+
import java.net.URL;
22+
import java.time.Duration;
23+
import java.time.Instant;
24+
import java.time.temporal.ChronoUnit;
25+
import java.util.Collections;
26+
import java.util.Set;
27+
import java.util.UUID;
28+
29+
import org.springframework.security.oauth2.core.OAuth2AccessToken;
30+
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
31+
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
32+
import org.springframework.security.oauth2.jose.JoseHeader;
33+
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
34+
import org.springframework.security.oauth2.jwt.Jwt;
35+
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
36+
import org.springframework.security.oauth2.jwt.JwtEncoder;
37+
38+
/**
39+
* @author Alexey Nesterov
40+
* @since 0.0.3
41+
*/
42+
class OAuth2TokenIssuerUtil {
43+
44+
static OAuth2AccessToken issueJwtAccessToken(JwtEncoder jwtEncoder, String subject, String audience, Set<String> scopes) {
45+
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
46+
47+
// TODO Allow configuration for issuer claim
48+
URL issuer = null;
49+
try {
50+
issuer = URI.create("https://oauth2.provider.com").toURL();
51+
} catch (MalformedURLException e) { }
52+
53+
Instant issuedAt = Instant.now();
54+
Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); // TODO Allow configuration for access token time-to-live
55+
56+
JwtClaimsSet jwtClaimsSet = JwtClaimsSet.withClaims()
57+
.issuer(issuer)
58+
.subject(subject)
59+
.audience(Collections.singletonList(audience))
60+
.issuedAt(issuedAt)
61+
.expiresAt(expiresAt)
62+
.notBefore(issuedAt)
63+
.claim(OAuth2ParameterNames.SCOPE, scopes)
64+
.build();
65+
66+
Jwt jwt = jwtEncoder.encode(joseHeader, jwtClaimsSet);
67+
68+
return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
69+
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes);
70+
}
71+
72+
static OAuth2RefreshToken issueRefreshToken(Duration refreshTokenTimeToLive) {
73+
Instant issuedAt = Instant.now();
74+
Instant refreshTokenExpiresAt = refreshTokenTimeToLive == Duration.ZERO ? null : issuedAt.plus(refreshTokenTimeToLive);
75+
76+
return new OAuth2RefreshToken(UUID.randomUUID().toString(), issuedAt, refreshTokenExpiresAt);
77+
}
78+
}

0 commit comments

Comments
 (0)