Skip to content

Commit 7c46236

Browse files
committed
Implement Client Configuration Endpoint
See: https://openid.net/specs/openid-connect-registration-1_0.html#ClientConfigurationEndpoint Generate registration_client_uri and registration_access_token when registering a new client (see: https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration) Closes gh-355
1 parent 8e8979a commit 7c46236

File tree

14 files changed

+1160
-76
lines changed

14 files changed

+1160
-76
lines changed

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcClientRegistrationEndpointFilter;
2525
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
2626
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
27+
import org.springframework.security.web.util.matcher.OrRequestMatcher;
2728
import org.springframework.security.web.util.matcher.RequestMatcher;
2829

2930
/**
@@ -47,13 +48,16 @@ public final class OidcClientRegistrationEndpointConfigurer extends AbstractOAut
4748
@Override
4849
<B extends HttpSecurityBuilder<B>> void init(B builder) {
4950
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
50-
this.requestMatcher = new AntPathRequestMatcher(
51-
providerSettings.getOidcClientRegistrationEndpoint(), HttpMethod.POST.name());
51+
this.requestMatcher = new OrRequestMatcher(
52+
new AntPathRequestMatcher(providerSettings.getOidcClientRegistrationEndpoint(), HttpMethod.POST.name()),
53+
new AntPathRequestMatcher(providerSettings.getOidcClientRegistrationEndpoint(), HttpMethod.GET.name())
54+
);
5255

5356
OidcClientRegistrationAuthenticationProvider oidcClientRegistrationAuthenticationProvider =
5457
new OidcClientRegistrationAuthenticationProvider(
5558
OAuth2ConfigurerUtils.getRegisteredClientRepository(builder),
56-
OAuth2ConfigurerUtils.getAuthorizationService(builder));
59+
OAuth2ConfigurerUtils.getAuthorizationService(builder),
60+
OAuth2ConfigurerUtils.getJwtEncoder(builder));
5761
builder.authenticationProvider(postProcess(oidcClientRegistrationAuthenticationProvider));
5862
}
5963

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcClientMetadataClaimAccessor.java

+21
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.security.oauth2.core.oidc;
1717

18+
import java.net.URL;
1819
import java.time.Instant;
1920
import java.util.List;
2021

@@ -134,4 +135,24 @@ default String getIdTokenSignedResponseAlgorithm() {
134135
return getClaimAsString(OidcClientMetadataClaimNames.ID_TOKEN_SIGNED_RESPONSE_ALG);
135136
}
136137

138+
/**
139+
* Returns the Registration Access Token that can be used at the Client Configuration Endpoint.
140+
*
141+
* @return the Registration Access Token that can be used at the Client Configuration Endpoint
142+
* @since 0.2.1
143+
*/
144+
default String getRegistrationAccessToken() {
145+
return getClaimAsString(OidcClientMetadataClaimNames.REGISTRATION_ACCESS_TOKEN);
146+
}
147+
148+
/**
149+
* Returns the {@code URL} of the OAuth 2.0 Client Configuration Endpoint.
150+
*
151+
* @return the {@code URL} of the OAuth 2.0 Client Configuration Endpoint
152+
* @since 0.2.1
153+
*/
154+
default URL getRegistrationClientUri() {
155+
return getClaimAsURL(OidcClientMetadataClaimNames.REGISTRATION_CLIENT_URI);
156+
}
157+
137158
}

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcClientMetadataClaimNames.java

+12
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,16 @@ public interface OidcClientMetadataClaimNames {
8383
*/
8484
String ID_TOKEN_SIGNED_RESPONSE_ALG = "id_token_signed_response_alg";
8585

86+
/**
87+
* {@code registration_access_token} - Registration Access Token that can be used at the Client Configuration Endpoint to perform subsequent operations upon the Client registration
88+
* @since 0.2.1
89+
*/
90+
String REGISTRATION_ACCESS_TOKEN = "registration_access_token";
91+
92+
/**
93+
* {@code registration_client_uri} - the {@code URL} of the OAuth 2.0 Client Configuration Endpoint
94+
* @since 0.2.1
95+
*/
96+
String REGISTRATION_CLIENT_URI = "registration_client_uri";
97+
8698
}

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcClientRegistration.java

+20
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,26 @@ public Builder idTokenSignedResponseAlgorithm(String idTokenSignedResponseAlgori
251251
return claim(OidcClientMetadataClaimNames.ID_TOKEN_SIGNED_RESPONSE_ALG, idTokenSignedResponseAlgorithm);
252252
}
253253

254+
/**
255+
* Sets the Registration Access Token that can be used at the Client Configuration Endpoint to perform subsequent operations upon the Client registration, OPTIONAL.
256+
*
257+
* @param registrationAccessToken the Registration Access Token that can be used at the Client Configuration Endpoint to perform subsequent operations upon the Client registration
258+
* @return the {@link Builder} for further configuration
259+
*/
260+
public Builder registrationAccessToken(String registrationAccessToken) {
261+
return claim(OidcClientMetadataClaimNames.REGISTRATION_ACCESS_TOKEN, registrationAccessToken);
262+
}
263+
264+
/**
265+
* Sets the {@code URL} of the OAuth 2.0 Client Configuration Endpoint, OPTIONAL.
266+
*
267+
* @param registrationClientUri the {@code URL} of the OAuth 2.0 Client Configuration Endpoint
268+
* @return the {@link Builder} for further configuration
269+
*/
270+
public Builder registrationClientUri(String registrationClientUri) {
271+
return claim(OidcClientMetadataClaimNames.REGISTRATION_CLIENT_URI, registrationClientUri);
272+
}
273+
254274
/**
255275
* Sets the claim.
256276
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2020-2021 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.oidc.authentication;
17+
18+
import java.time.Instant;
19+
import java.util.Collections;
20+
import java.util.Set;
21+
22+
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
23+
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
24+
import org.springframework.security.oauth2.jwt.JoseHeader;
25+
import org.springframework.security.oauth2.jwt.Jwt;
26+
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
27+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
28+
import org.springframework.util.CollectionUtils;
29+
import org.springframework.util.StringUtils;
30+
31+
/**
32+
*
33+
* Utility methods used by the {@link OidcClientRegistrationAuthenticationProvider} when issuing {@link Jwt}'s.
34+
* @author Ovidiu Popa
35+
* @since 0.2.1
36+
*/
37+
final class JwtUtils {
38+
39+
//TODO Duplicate of {@code org.springframework.security.oauth2.server.authorization.authentication.JwtUtils}. To be refactored
40+
private JwtUtils() {
41+
}
42+
43+
static JoseHeader.Builder headers() {
44+
return JoseHeader.withAlgorithm(SignatureAlgorithm.RS256);
45+
}
46+
47+
static JwtClaimsSet.Builder accessTokenClaims(RegisteredClient registeredClient,
48+
String issuer, String subject, Set<String> authorizedScopes) {
49+
50+
Instant issuedAt = Instant.now();
51+
Instant expiresAt = issuedAt.plus(registeredClient.getTokenSettings().getAccessTokenTimeToLive());
52+
53+
// @formatter:off
54+
JwtClaimsSet.Builder claimsBuilder = JwtClaimsSet.builder();
55+
if (StringUtils.hasText(issuer)) {
56+
claimsBuilder.issuer(issuer);
57+
}
58+
claimsBuilder
59+
.subject(subject)
60+
.audience(Collections.singletonList(registeredClient.getClientId()))
61+
.issuedAt(issuedAt)
62+
.expiresAt(expiresAt)
63+
.notBefore(issuedAt);
64+
if (!CollectionUtils.isEmpty(authorizedScopes)) {
65+
claimsBuilder.claim(OAuth2ParameterNames.SCOPE, authorizedScopes);
66+
}
67+
// @formatter:on
68+
69+
return claimsBuilder;
70+
}
71+
72+
}

0 commit comments

Comments
 (0)