Skip to content

Commit a2167a5

Browse files
committed
Polish gh-128
1 parent 78d4bd0 commit a2167a5

File tree

14 files changed

+154
-143
lines changed

14 files changed

+154
-143
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationServerConfigurer.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,18 @@ public void init(B builder) {
144144
jwtEncoder);
145145
builder.authenticationProvider(postProcess(authorizationCodeAuthenticationProvider));
146146

147+
OAuth2RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider =
148+
new OAuth2RefreshTokenAuthenticationProvider(
149+
getAuthorizationService(builder),
150+
jwtEncoder);
151+
builder.authenticationProvider(postProcess(refreshTokenAuthenticationProvider));
152+
147153
OAuth2ClientCredentialsAuthenticationProvider clientCredentialsAuthenticationProvider =
148154
new OAuth2ClientCredentialsAuthenticationProvider(
149155
getAuthorizationService(builder),
150156
jwtEncoder);
151157
builder.authenticationProvider(postProcess(clientCredentialsAuthenticationProvider));
152158

153-
OAuth2RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider =
154-
new OAuth2RefreshTokenAuthenticationProvider(getAuthorizationService(builder), jwtEncoder);
155-
builder.authenticationProvider(postProcess(refreshTokenAuthenticationProvider));
156-
157159
OAuth2TokenRevocationAuthenticationProvider tokenRevocationAuthenticationProvider =
158160
new OAuth2TokenRevocationAuthenticationProvider(
159161
getAuthorizationService(builder));

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

+3-7
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,12 @@ private boolean hasToken(OAuth2Authorization authorization, String token, TokenT
6666
} else if (TokenType.AUTHORIZATION_CODE.equals(tokenType)) {
6767
OAuth2AuthorizationCode authorizationCode = authorization.getTokens().getToken(OAuth2AuthorizationCode.class);
6868
return authorizationCode != null && authorizationCode.getTokenValue().equals(token);
69-
}
70-
71-
if (TokenType.ACCESS_TOKEN.equals(tokenType)) {
69+
} else if (TokenType.ACCESS_TOKEN.equals(tokenType)) {
7270
return authorization.getTokens().getAccessToken() != null &&
7371
authorization.getTokens().getAccessToken().getTokenValue().equals(token);
74-
}
75-
76-
if (TokenType.REFRESH_TOKEN.equals(tokenType)) {
72+
} else if (TokenType.REFRESH_TOKEN.equals(tokenType)) {
7773
return authorization.getTokens().getRefreshToken() != null &&
78-
authorization.getTokens().getRefreshToken().getTokenValue().equals(token);
74+
authorization.getTokens().getRefreshToken().getTokenValue().equals(token);
7975
}
8076

8177
return false;

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

+9-9
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,25 @@
1818
import org.springframework.lang.Nullable;
1919
import org.springframework.security.authentication.AbstractAuthenticationToken;
2020
import org.springframework.security.core.Authentication;
21-
import org.springframework.security.oauth2.server.authorization.Version;
2221
import org.springframework.security.oauth2.core.OAuth2AccessToken;
2322
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
23+
import org.springframework.security.oauth2.server.authorization.Version;
2424
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
2525
import org.springframework.util.Assert;
2626

2727
import java.util.Collections;
2828

2929
/**
30-
* An {@link Authentication} implementation used when issuing an OAuth 2.0 Access Token.
30+
* An {@link Authentication} implementation used when issuing an
31+
* OAuth 2.0 Access Token and (optional) Refresh Token.
3132
*
3233
* @author Joe Grandja
3334
* @author Madhu Bhat
3435
* @since 0.0.1
3536
* @see AbstractAuthenticationToken
36-
* @see OAuth2AuthorizationCodeAuthenticationProvider
3737
* @see RegisteredClient
3838
* @see OAuth2AccessToken
39+
* @see OAuth2RefreshToken
3940
* @see OAuth2ClientAuthenticationToken
4041
*/
4142
public class OAuth2AccessTokenAuthenticationToken extends AbstractAuthenticationToken {
@@ -65,8 +66,8 @@ public OAuth2AccessTokenAuthenticationToken(RegisteredClient registeredClient,
6566
* @param accessToken the access token
6667
* @param refreshToken the refresh token
6768
*/
68-
public OAuth2AccessTokenAuthenticationToken(RegisteredClient registeredClient,
69-
Authentication clientPrincipal, OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) {
69+
public OAuth2AccessTokenAuthenticationToken(RegisteredClient registeredClient, Authentication clientPrincipal,
70+
OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) {
7071
super(Collections.emptyList());
7172
Assert.notNull(registeredClient, "registeredClient cannot be null");
7273
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
@@ -105,14 +106,13 @@ public OAuth2AccessToken getAccessToken() {
105106
return this.accessToken;
106107
}
107108

108-
109109
/**
110-
* Returns the {@link OAuth2RefreshToken} if provided
110+
* Returns the {@link OAuth2RefreshToken refresh token}.
111111
*
112-
* @return the {@link OAuth2RefreshToken}
112+
* @return the {@link OAuth2RefreshToken} or {@code null} if not available
113113
*/
114114
@Nullable
115115
public OAuth2RefreshToken getRefreshToken() {
116-
return refreshToken;
116+
return this.refreshToken;
117117
}
118118
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ public Authentication authenticate(Authentication authentication) throws Authent
9797
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes);
9898

9999
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(registeredClient)
100-
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
101100
.principalName(clientPrincipal.getName())
102101
.tokens(OAuth2Tokens.builder().accessToken(accessToken).build())
102+
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
103103
.build();
104104
this.authorizationService.save(authorization);
105105

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

+36-31
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.security.oauth2.server.authorization.authentication;
1817

19-
import java.time.Instant;
20-
import java.util.Set;
21-
2218
import org.springframework.security.authentication.AuthenticationProvider;
2319
import org.springframework.security.core.Authentication;
2420
import org.springframework.security.core.AuthenticationException;
@@ -38,6 +34,9 @@
3834
import org.springframework.security.oauth2.server.authorization.token.OAuth2Tokens;
3935
import org.springframework.util.Assert;
4036

37+
import java.time.Instant;
38+
import java.util.Set;
39+
4140
/**
4241
* An {@link AuthenticationProvider} implementation for the OAuth 2.0 Refresh Token Grant.
4342
*
@@ -47,19 +46,23 @@
4746
* @see OAuth2AccessTokenAuthenticationToken
4847
* @see OAuth2AuthorizationService
4948
* @see JwtEncoder
50-
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-1.5">Section 1.5 Refresh Token</a>
49+
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-1.5">Section 1.5 Refresh Token Grant</a>
5150
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-6">Section 6 Refreshing an Access Token</a>
5251
*/
53-
5452
public class OAuth2RefreshTokenAuthenticationProvider implements AuthenticationProvider {
55-
5653
private final OAuth2AuthorizationService authorizationService;
5754
private final JwtEncoder jwtEncoder;
5855

59-
public OAuth2RefreshTokenAuthenticationProvider(OAuth2AuthorizationService authorizationService, JwtEncoder jwtEncoder) {
56+
/**
57+
* Constructs an {@code OAuth2RefreshTokenAuthenticationProvider} using the provided parameters.
58+
*
59+
* @param authorizationService the authorization service
60+
* @param jwtEncoder the jwt encoder
61+
*/
62+
public OAuth2RefreshTokenAuthenticationProvider(OAuth2AuthorizationService authorizationService,
63+
JwtEncoder jwtEncoder) {
6064
Assert.notNull(authorizationService, "authorizationService cannot be null");
6165
Assert.notNull(jwtEncoder, "jwtEncoder cannot be null");
62-
6366
this.authorizationService = authorizationService;
6467
this.jwtEncoder = jwtEncoder;
6568
}
@@ -73,43 +76,45 @@ public Authentication authenticate(Authentication authentication) throws Authent
7376
if (OAuth2ClientAuthenticationToken.class.isAssignableFrom(refreshTokenAuthentication.getPrincipal().getClass())) {
7477
clientPrincipal = (OAuth2ClientAuthenticationToken) refreshTokenAuthentication.getPrincipal();
7578
}
76-
7779
if (clientPrincipal == null || !clientPrincipal.isAuthenticated()) {
7880
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT));
7981
}
82+
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
8083

81-
OAuth2Authorization authorization = this.authorizationService.findByToken(refreshTokenAuthentication.getRefreshToken(), TokenType.REFRESH_TOKEN);
84+
OAuth2Authorization authorization = this.authorizationService.findByToken(
85+
refreshTokenAuthentication.getRefreshToken(), TokenType.REFRESH_TOKEN);
8286
if (authorization == null) {
8387
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
8488
}
8589

86-
Instant refreshTokenExpiration = authorization.getTokens().getRefreshToken().getExpiresAt();
87-
if (refreshTokenExpiration.isBefore(Instant.now())) {
88-
// as per https://tools.ietf.org/html/rfc6749#section-5.2
89-
// invalid_grant: The provided authorization grant (e.g., authorization
90-
// code, resource owner credentials) or refresh token is invalid, expired, revoked [...].
91-
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
90+
if (!registeredClient.getId().equals(authorization.getRegisteredClientId())) {
91+
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT));
9292
}
9393

94-
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
94+
Instant refreshTokenExpiresAt = authorization.getTokens().getRefreshToken().getExpiresAt();
95+
if (refreshTokenExpiresAt.isBefore(Instant.now())) {
96+
// As per https://tools.ietf.org/html/rfc6749#section-5.2
97+
// invalid_grant: The provided authorization grant (e.g., authorization code,
98+
// resource owner credentials) or refresh token is invalid, expired, revoked [...].
99+
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
100+
}
95101

96-
// https://tools.ietf.org/html/rfc6749#section-6
102+
// As per https://tools.ietf.org/html/rfc6749#section-6
97103
// The requested scope MUST NOT include any scope not originally granted by the resource owner,
98104
// and if omitted is treated as equal to the scope originally granted by the resource owner.
99-
Set<String> refreshTokenScopes = refreshTokenAuthentication.getScopes();
105+
Set<String> scopes = refreshTokenAuthentication.getScopes();
100106
Set<String> authorizedScopes = authorization.getAttribute(OAuth2AuthorizationAttributeNames.AUTHORIZED_SCOPES);
101-
if (!authorizedScopes.containsAll(refreshTokenScopes)) {
107+
if (!authorizedScopes.containsAll(scopes)) {
102108
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_SCOPE));
103109
}
104-
105-
if (refreshTokenScopes.isEmpty()) {
106-
refreshTokenScopes = authorizedScopes;
110+
if (scopes.isEmpty()) {
111+
scopes = authorizedScopes;
107112
}
108113

109114
Jwt jwt = OAuth2TokenIssuerUtil
110-
.issueJwtAccessToken(this.jwtEncoder, authorization.getPrincipalName(), registeredClient.getClientId(), refreshTokenScopes);
115+
.issueJwtAccessToken(this.jwtEncoder, authorization.getPrincipalName(), registeredClient.getClientId(), scopes);
111116
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
112-
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), refreshTokenScopes);
117+
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), scopes);
113118

114119
TokenSettings tokenSettings = registeredClient.getTokenSettings();
115120
OAuth2RefreshToken refreshToken;
@@ -120,13 +125,13 @@ public Authentication authenticate(Authentication authentication) throws Authent
120125
}
121126

122127
authorization = OAuth2Authorization.from(authorization)
123-
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
124-
.tokens(OAuth2Tokens.builder().accessToken(accessToken).refreshToken(refreshToken).build())
125-
.build();
126-
128+
.tokens(OAuth2Tokens.builder().accessToken(accessToken).refreshToken(refreshToken).build())
129+
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
130+
.build();
127131
this.authorizationService.save(authorization);
128132

129-
return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken);
133+
return new OAuth2AccessTokenAuthenticationToken(
134+
registeredClient, clientPrincipal, accessToken, refreshToken);
130135
}
131136

132137
@Override

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

+25-20
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.security.oauth2.server.authorization.authentication;
1817

19-
import java.util.Collections;
20-
import java.util.Set;
21-
2218
import org.springframework.security.authentication.AbstractAuthenticationToken;
2319
import org.springframework.security.core.Authentication;
20+
import org.springframework.security.oauth2.server.authorization.Version;
2421
import org.springframework.util.Assert;
2522

23+
import java.util.Collections;
24+
import java.util.Set;
25+
2626
/**
2727
* An {@link Authentication} implementation used for the OAuth 2.0 Refresh Token Grant.
2828
*
@@ -33,49 +33,54 @@
3333
* @see OAuth2ClientAuthenticationToken
3434
*/
3535
public class OAuth2RefreshTokenAuthenticationToken extends AbstractAuthenticationToken {
36-
37-
private final Authentication clientPrincipal;
36+
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
3837
private final String refreshToken;
38+
private final Authentication clientPrincipal;
3939
private final Set<String> scopes;
4040

4141
/**
4242
* Constructs an {@code OAuth2RefreshTokenAuthenticationToken} using the provided parameters.
4343
*
44-
* @param refreshToken refresh token value
44+
* @param refreshToken the refresh token
4545
* @param clientPrincipal the authenticated client principal
4646
*/
4747
public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal) {
48-
this(clientPrincipal, refreshToken, Collections.emptySet());
48+
this(refreshToken, clientPrincipal, Collections.emptySet());
4949
}
5050

5151
/**
5252
* Constructs an {@code OAuth2RefreshTokenAuthenticationToken} using the provided parameters.
5353
*
54+
* @param refreshToken the refresh token
5455
* @param clientPrincipal the authenticated client principal
55-
* @param refreshToken refresh token value
56-
* @param requestedScopes scopes requested by refresh token
56+
* @param scopes the requested scope(s)
5757
*/
58-
public OAuth2RefreshTokenAuthenticationToken(Authentication clientPrincipal, String refreshToken, Set<String> requestedScopes) {
58+
public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal,
59+
Set<String> scopes) {
5960
super(Collections.emptySet());
60-
61+
Assert.hasText(refreshToken, "refreshToken cannot be empty");
6162
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
62-
Assert.hasText(refreshToken, "refreshToken cannot be null or empty");
63-
64-
this.clientPrincipal = clientPrincipal;
63+
Assert.notNull(scopes, "scopes cannot be null");
6564
this.refreshToken = refreshToken;
66-
this.scopes = requestedScopes;
65+
this.clientPrincipal = clientPrincipal;
66+
this.scopes = scopes;
6767
}
6868

6969
@Override
70-
public Object getCredentials() {
71-
return "";
70+
public Object getPrincipal() {
71+
return this.clientPrincipal;
7272
}
7373

7474
@Override
75-
public Object getPrincipal() {
76-
return this.clientPrincipal;
75+
public Object getCredentials() {
76+
return "";
7777
}
7878

79+
/**
80+
* Returns the refresh token.
81+
*
82+
* @return the refresh token
83+
*/
7984
public String getRefreshToken() {
8085
return this.refreshToken;
8186
}

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

+13-14
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.security.oauth2.server.authorization.authentication;
1817

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.Base64;
26-
import java.util.Collections;
27-
import java.util.Set;
28-
2918
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
3019
import org.springframework.security.crypto.keygen.StringKeyGenerator;
3120
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
@@ -36,13 +25,23 @@
3625
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
3726
import org.springframework.security.oauth2.jwt.JwtEncoder;
3827

28+
import java.net.MalformedURLException;
29+
import java.net.URI;
30+
import java.net.URL;
31+
import java.time.Duration;
32+
import java.time.Instant;
33+
import java.time.temporal.ChronoUnit;
34+
import java.util.Base64;
35+
import java.util.Collections;
36+
import java.util.Set;
37+
3938
/**
4039
* @author Alexey Nesterov
4140
* @since 0.0.3
4241
*/
4342
class OAuth2TokenIssuerUtil {
4443

45-
private static final StringKeyGenerator CODE_GENERATOR = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
44+
private static final StringKeyGenerator TOKEN_GENERATOR = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
4645

4746
static Jwt issueJwtAccessToken(JwtEncoder jwtEncoder, String subject, String audience, Set<String> scopes) {
4847
JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
@@ -71,8 +70,8 @@ static Jwt issueJwtAccessToken(JwtEncoder jwtEncoder, String subject, String aud
7170

7271
static OAuth2RefreshToken issueRefreshToken(Duration refreshTokenTimeToLive) {
7372
Instant issuedAt = Instant.now();
74-
Instant refreshTokenExpiresAt = issuedAt.plus(refreshTokenTimeToLive);
73+
Instant expiresAt = issuedAt.plus(refreshTokenTimeToLive);
7574

76-
return new OAuth2RefreshToken(CODE_GENERATOR.generateKey(), issuedAt, refreshTokenExpiresAt);
75+
return new OAuth2RefreshToken(TOKEN_GENERATOR.generateKey(), issuedAt, expiresAt);
7776
}
7877
}

0 commit comments

Comments
 (0)