Skip to content

Commit d8ab348

Browse files
committed
Merge branch 0.4.x into main
The following commits are merged using the default merge strategy. ccdd8ce Update README with documentation links c70255a Decompose OAuth2AuthorizationCodeRequestAuthenticationProvider 8d51722 Return registration_endpoint when client registration is enabled fdf1200 Polish spring-projectsgh-881 aee5613 Move integration tests for OidcProviderConfiguration
2 parents b6534df + aee5613 commit d8ab348

File tree

26 files changed

+1971
-1458
lines changed

26 files changed

+1971
-1458
lines changed

README.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ The goal is to leverage all the knowledge learned thus far and apply the same to
3636
Submitted work via pull requests should follow the same coding style/conventions and adopt the same or similar design patterns that have been established in Spring Security's OAuth 2.0 support.
3737

3838
== Documentation
39-
Be sure to read the https://docs.spring.io/spring-security/reference[Spring Security Reference], as well as the https://docs.spring.io/spring-security/reference/servlet/oauth2/index.html[OAuth 2.0 Reference], which describes the Client and Resource Server features available.
39+
Be sure to read the https://docs.spring.io/spring-authorization-server/docs/current/reference/html/[Spring Authorization Server Reference] and https://docs.spring.io/spring-security/reference[Spring Security Reference], as well as the https://docs.spring.io/spring-security/reference/servlet/oauth2/index.html[OAuth 2.0 Reference], which describes the Client and Resource Server features available.
4040

41-
Extensive JavaDoc for the Spring Security code is also available in the https://docs.spring.io/spring-security/site/docs/current/api/[Spring Security API Documentation].
41+
JavaDoc is also available for the https://docs.spring.io/spring-authorization-server/docs/current/api/[Spring Authorization Server API] and https://docs.spring.io/spring-security/site/docs/current/api/[Spring Security API].
4242

4343
== Code of Conduct
4444
This project adheres to the Contributor Covenant link:CODE_OF_CONDUCT.adoc[code of conduct].

docs/src/docs/asciidoc/protocol-endpoints.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
3232
return http.build();
3333
}
3434
----
35-
<1> `authorizationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization request] (or consent) from `HttpServletRequest` to an instance of `OAuth2AuthorizationCodeRequestAuthenticationToken`.
35+
<1> `authorizationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization request] (or consent) from `HttpServletRequest` to an instance of `OAuth2AuthorizationCodeRequestAuthenticationToken` or `OAuth2AuthorizationConsentAuthenticationToken`.
3636
<2> `authorizationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
37-
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationCodeRequestAuthenticationToken`.
37+
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationCodeRequestAuthenticationToken` or `OAuth2AuthorizationConsentAuthenticationToken`.
3838
<4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
3939
<5> `authorizationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2[OAuth2AuthorizationResponse].
4040
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthorizationCodeRequestAuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1[OAuth2Error response].
@@ -45,8 +45,8 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
4545

4646
`OAuth2AuthorizationEndpointFilter` is configured with the following defaults:
4747

48-
* `*AuthenticationConverter*` -- An `OAuth2AuthorizationCodeRequestAuthenticationConverter`.
49-
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeRequestAuthenticationProvider`.
48+
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeRequestAuthenticationConverter` and `OAuth2AuthorizationConsentAuthenticationConverter`.
49+
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeRequestAuthenticationProvider` and `OAuth2AuthorizationConsentAuthenticationProvider`.
5050
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returns the `OAuth2AuthorizationResponse`.
5151
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthorizationCodeRequestAuthenticationException` and returns the `OAuth2Error` response.
5252

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,17 @@ public B tokenIntrospectionEndpointAuthenticationMethods(Consumer<List<String>>
274274
return getThis();
275275
}
276276

277+
/**
278+
* Use this {@code registration_endpoint} in the resulting {@link AbstractOAuth2AuthorizationServerMetadata}, OPTIONAL.
279+
*
280+
* @param clientRegistrationEndpoint the {@code URL} of the OAuth 2.0 Dynamic Client Registration Endpoint
281+
* @return the {@link AbstractBuilder} for further configuration
282+
* @since 0.4.0
283+
*/
284+
public B clientRegistrationEndpoint(String clientRegistrationEndpoint) {
285+
return claim(OAuth2AuthorizationServerMetadataClaimNames.REGISTRATION_ENDPOINT, clientRegistrationEndpoint);
286+
}
287+
277288
/**
278289
* Add this Proof Key for Code Exchange (PKCE) {@code code_challenge_method} to the collection of {@code code_challenge_methods_supported}
279290
* in the resulting {@link AbstractOAuth2AuthorizationServerMetadata}, OPTIONAL.
@@ -369,6 +380,9 @@ protected void validate() {
369380
Assert.isInstanceOf(List.class, getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED), "tokenIntrospectionEndpointAuthenticationMethods must be of type List");
370381
Assert.notEmpty((List<?>) getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED), "tokenIntrospectionEndpointAuthenticationMethods cannot be empty");
371382
}
383+
if (getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.REGISTRATION_ENDPOINT) != null) {
384+
validateURL(getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.REGISTRATION_ENDPOINT), "clientRegistrationEndpoint must be a valid URL");
385+
}
372386
if (getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED) != null) {
373387
Assert.isInstanceOf(List.class, getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED), "codeChallengeMethods must be of type List");
374388
Assert.notEmpty((List<?>) getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED), "codeChallengeMethods cannot be empty");

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,16 @@ default List<String> getTokenIntrospectionEndpointAuthenticationMethods() {
141141
return getClaimAsStringList(OAuth2AuthorizationServerMetadataClaimNames.INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED);
142142
}
143143

144+
/**
145+
* Returns the {@code URL} of the OAuth 2.0 Dynamic Client Registration Endpoint {@code (registration_endpoint)}.
146+
*
147+
* @return the {@code URL} of the OAuth 2.0 Dynamic Client Registration Endpoint
148+
* @since 0.4.0
149+
*/
150+
default URL getClientRegistrationEndpoint() {
151+
return getClaimAsURL(OAuth2AuthorizationServerMetadataClaimNames.REGISTRATION_ENDPOINT);
152+
}
153+
144154
/**
145155
* Returns the Proof Key for Code Exchange (PKCE) {@code code_challenge_method} values supported {@code (code_challenge_methods_supported)}.
146156
*

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ public class OAuth2AuthorizationServerMetadataClaimNames {
8686
*/
8787
public static final String INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED = "introspection_endpoint_auth_methods_supported";
8888

89+
/**
90+
* {@code registration_endpoint} - the {@code URL} of the OAuth 2.0 Dynamic Client Registration Endpoint
91+
* @since 0.4.0
92+
*/
93+
public static final String REGISTRATION_ENDPOINT = "registration_endpoint";
94+
8995
/**
9096
* {@code code_challenge_methods_supported} - the Proof Key for Code Exchange (PKCE) {@code code_challenge_method} values supported
9197
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2020-2022 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+
package org.springframework.security.oauth2.server.authorization.authentication;
17+
18+
import java.time.Instant;
19+
import java.util.Base64;
20+
21+
import org.springframework.lang.Nullable;
22+
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
23+
import org.springframework.security.crypto.keygen.StringKeyGenerator;
24+
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
25+
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
26+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
27+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
28+
29+
/**
30+
* An {@link OAuth2TokenGenerator} that generates an {@link OAuth2AuthorizationCode}.
31+
*
32+
* @author Joe Grandja
33+
* @since 0.4.0
34+
* @see OAuth2TokenGenerator
35+
* @see OAuth2AuthorizationCode
36+
* @see OAuth2AuthorizationCodeRequestAuthenticationProvider
37+
* @see OAuth2AuthorizationConsentAuthenticationProvider
38+
*/
39+
final class OAuth2AuthorizationCodeGenerator implements OAuth2TokenGenerator<OAuth2AuthorizationCode> {
40+
private final StringKeyGenerator authorizationCodeGenerator =
41+
new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
42+
43+
@Nullable
44+
@Override
45+
public OAuth2AuthorizationCode generate(OAuth2TokenContext context) {
46+
if (context.getTokenType() == null ||
47+
!OAuth2ParameterNames.CODE.equals(context.getTokenType().getValue())) {
48+
return null;
49+
}
50+
Instant issuedAt = Instant.now();
51+
Instant expiresAt = issuedAt.plus(context.getRegisteredClient().getTokenSettings().getAuthorizationCodeTimeToLive());
52+
return new OAuth2AuthorizationCode(this.authorizationCodeGenerator.generateKey(), issuedAt, expiresAt);
53+
}
54+
55+
}

0 commit comments

Comments
 (0)