Browse Source

Polish gh-489

pull/491/head
Steve Riesenberg 4 years ago
parent
commit
5412f10ff8
  1. 17
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2AuthorizationServerMetadata.java
  2. 5
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationServerMetadataClaimNames.java
  3. 16
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcProviderConfiguration.java
  4. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcProviderMetadataClaimAccessor.java
  5. 8
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcProviderMetadataClaimNames.java
  6. 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java
  7. 1
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java
  8. 18
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/core/oidc/OidcProviderConfigurationTests.java
  9. 3
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -138,16 +138,6 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth @@ -138,16 +138,6 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth
return claim(OAuth2AuthorizationServerMetadataClaimNames.JWKS_URI, jwkSetUrl);
}
/**
* Use this {@code userinfo_endpoint} in the resulting {@link AbstractOAuth2AuthorizationServerMetadata}, OPTIONAL.
*
* @param userInfoEndpoint the {@code URL} of the OAuth 2.0 UserInfo Endpoint
* @return the {@link AbstractBuilder} for further configuration
*/
public B userInfoEndpoint(String userInfoEndpoint) {
return claim(OAuth2AuthorizationServerMetadataClaimNames.USER_INFO_ENDPOINT, userInfoEndpoint);
}
/**
* Add this OAuth 2.0 {@code scope} to the collection of {@code scopes_supported}
* in the resulting {@link AbstractOAuth2AuthorizationServerMetadata}, RECOMMENDED.
@ -353,9 +343,6 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth @@ -353,9 +343,6 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth
if (getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.JWKS_URI) != null) {
validateURL(getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.JWKS_URI), "jwksUri must be a valid URL");
}
if (getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.USER_INFO_ENDPOINT) != null) {
validateURL(getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.USER_INFO_ENDPOINT), "userInfoEndpoint must be a valid URL");
}
if (getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED) != null) {
Assert.isInstanceOf(List.class, getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED), "scopes must be of type List");
Assert.notEmpty((List<?>) getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED), "scopes cannot be empty");
@ -404,7 +391,7 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth @@ -404,7 +391,7 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth
valuesConsumer.accept(values);
}
private static void validateURL(Object url, String errorMessage) {
protected static void validateURL(Object url, String errorMessage) {
if (URL.class.isAssignableFrom(url.getClass())) {
return;
}

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

@ -51,11 +51,6 @@ public interface OAuth2AuthorizationServerMetadataClaimNames { @@ -51,11 +51,6 @@ public interface OAuth2AuthorizationServerMetadataClaimNames {
*/
String JWKS_URI = "jwks_uri";
/**
* {@code userinfo_endpoint} - the {@code URL} of the OAuth 2.0 UserInfo Endpoint
*/
String USER_INFO_ENDPOINT = "userinfo_endpoint";
/**
* {@code scopes_supported} - the OAuth 2.0 {@code scope} values supported
*/

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -118,6 +118,17 @@ public final class OidcProviderConfiguration extends AbstractOAuth2Authorization @@ -118,6 +118,17 @@ public final class OidcProviderConfiguration extends AbstractOAuth2Authorization
return this;
}
/**
* Use this {@code userinfo_endpoint} in the resulting {@link OidcProviderConfiguration}, OPTIONAL.
*
* @param userInfoEndpoint the {@code URL} of the OpenID Connect 1.0 UserInfo Endpoint
* @return the {@link Builder} for further configuration
* @since 0.2.2
*/
public Builder userInfoEndpoint(String userInfoEndpoint) {
return claim(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT, userInfoEndpoint);
}
/**
* Validate the claims and build the {@link OidcProviderConfiguration}.
* <p>
@ -144,6 +155,9 @@ public final class OidcProviderConfiguration extends AbstractOAuth2Authorization @@ -144,6 +155,9 @@ public final class OidcProviderConfiguration extends AbstractOAuth2Authorization
Assert.notNull(getClaims().get(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED), "idTokenSigningAlgorithms cannot be null");
Assert.isInstanceOf(List.class, getClaims().get(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED), "idTokenSigningAlgorithms must be of type List");
Assert.notEmpty((List<?>) getClaims().get(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED), "idTokenSigningAlgorithms cannot be empty");
if (getClaims().get(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT) != null) {
validateURL(getClaims().get(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT), "userInfoEndpoint must be a valid URL");
}
}
@SuppressWarnings("unchecked")

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.security.oauth2.core.oidc;
import java.net.URL;
import java.util.List;
import org.springframework.security.oauth2.core.ClaimAccessor;
@ -56,4 +57,14 @@ public interface OidcProviderMetadataClaimAccessor extends OAuth2AuthorizationSe @@ -56,4 +57,14 @@ public interface OidcProviderMetadataClaimAccessor extends OAuth2AuthorizationSe
return getClaimAsStringList(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED);
}
/**
* Returns the {@code URL} of the OpenID Connect 1.0 UserInfo Endpoint {@code (userinfo_endpoint)}.
*
* @return the {@code URL} of the OpenID Connect 1.0 UserInfo Endpoint
* @since 0.2.2
*/
default URL getUserInfoEndpoint() {
return getClaimAsURL(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT);
}
}

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -39,4 +39,10 @@ public interface OidcProviderMetadataClaimNames extends OAuth2AuthorizationServe @@ -39,4 +39,10 @@ public interface OidcProviderMetadataClaimNames extends OAuth2AuthorizationServe
*/
String ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED = "id_token_signing_alg_values_supported";
/**
* {@code userinfo_endpoint} - the {@code URL} of the OpenID Connect 1.0 UserInfo Endpoint
* @since 0.2.2
*/
String USER_INFO_ENDPOINT = "userinfo_endpoint";
}

2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java

@ -88,7 +88,7 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques @@ -88,7 +88,7 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
.tokenEndpoint(asUrl(issuer, this.providerSettings.getTokenEndpoint()))
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())
.jwkSetUrl(asUrl(issuer, this.providerSettings.getJwkSetEndpoint()))
.userInfoEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getOidcUserInfoEndpoint()))
.userInfoEndpoint(asUrl(issuer, this.providerSettings.getOidcUserInfoEndpoint()))
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())

1
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java

@ -86,7 +86,6 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP @@ -86,7 +86,6 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
.tokenEndpoint(asUrl(issuer, this.providerSettings.getTokenEndpoint()))
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())
.jwkSetUrl(asUrl(issuer, this.providerSettings.getJwkSetEndpoint()))
.userInfoEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getOidcUserInfoEndpoint()))
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())

18
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/core/oidc/OidcProviderConfigurationTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -59,6 +59,7 @@ public class OidcProviderConfigurationTests { @@ -59,6 +59,7 @@ public class OidcProviderConfigurationTests {
.grantType("client_credentials")
.subjectType("public")
.idTokenSigningAlgorithm("RS256")
.userInfoEndpoint("https://example.com/issuer1/userinfo")
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.claim("a-claim", "a-value")
.build();
@ -72,6 +73,7 @@ public class OidcProviderConfigurationTests { @@ -72,6 +73,7 @@ public class OidcProviderConfigurationTests {
assertThat(providerConfiguration.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "client_credentials");
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
assertThat(providerConfiguration.getIdTokenSigningAlgorithms()).containsExactly("RS256");
assertThat(providerConfiguration.getUserInfoEndpoint()).isEqualTo(url("https://example.com/issuer1/userinfo"));
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).containsExactly(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue());
assertThat(providerConfiguration.<String>getClaim("a-claim")).isEqualTo("a-value");
}
@ -112,6 +114,7 @@ public class OidcProviderConfigurationTests { @@ -112,6 +114,7 @@ public class OidcProviderConfigurationTests {
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.singletonList("code"));
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.singletonList("public"));
claims.put(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED, Collections.singletonList("RS256"));
claims.put(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT, "https://example.com/issuer1/userinfo");
claims.put("some-claim", "some-value");
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.withClaims(claims).build();
@ -125,6 +128,7 @@ public class OidcProviderConfigurationTests { @@ -125,6 +128,7 @@ public class OidcProviderConfigurationTests {
assertThat(providerConfiguration.getGrantTypes()).isNull();
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
assertThat(providerConfiguration.getIdTokenSigningAlgorithms()).containsExactly("RS256");
assertThat(providerConfiguration.getUserInfoEndpoint()).isEqualTo(url("https://example.com/issuer1/userinfo"));
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).isNull();
assertThat(providerConfiguration.<String>getClaim("some-claim")).isEqualTo("some-value");
}
@ -140,6 +144,7 @@ public class OidcProviderConfigurationTests { @@ -140,6 +144,7 @@ public class OidcProviderConfigurationTests {
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.singletonList("code"));
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.singletonList("public"));
claims.put(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED, Collections.singletonList("RS256"));
claims.put(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT, url("https://example.com/issuer1/userinfo"));
claims.put("some-claim", "some-value");
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.withClaims(claims).build();
@ -153,6 +158,7 @@ public class OidcProviderConfigurationTests { @@ -153,6 +158,7 @@ public class OidcProviderConfigurationTests {
assertThat(providerConfiguration.getGrantTypes()).isNull();
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
assertThat(providerConfiguration.getIdTokenSigningAlgorithms()).containsExactly("RS256");
assertThat(providerConfiguration.getUserInfoEndpoint()).isEqualTo(url("https://example.com/issuer1/userinfo"));
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).isNull();
assertThat(providerConfiguration.<String>getClaim("some-claim")).isEqualTo("some-value");
}
@ -380,6 +386,16 @@ public class OidcProviderConfigurationTests { @@ -380,6 +386,16 @@ public class OidcProviderConfigurationTests {
.withMessageContaining("idTokenSigningAlgorithms cannot be empty");
}
@Test
public void buildWhenUserInfoEndpointNotUrlThenThrowIllegalArgumentException() {
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.USER_INFO_ENDPOINT, "not an url"));
assertThatIllegalArgumentException()
.isThrownBy(builder::build)
.withMessage("userInfoEndpoint must be a valid URL");
}
@Test
public void responseTypesWhenAddingOrRemovingThenCorrectValues() {
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder

3
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java

@ -94,12 +94,14 @@ public class OidcProviderConfigurationEndpointFilterTests { @@ -94,12 +94,14 @@ public class OidcProviderConfigurationEndpointFilterTests {
String authorizationEndpoint = "/oauth2/v1/authorize";
String tokenEndpoint = "/oauth2/v1/token";
String jwkSetEndpoint = "/oauth2/v1/jwks";
String userInfoEndpoint = "/userinfo";
ProviderSettings providerSettings = ProviderSettings.builder()
.issuer(issuer)
.authorizationEndpoint(authorizationEndpoint)
.tokenEndpoint(tokenEndpoint)
.jwkSetEndpoint(jwkSetEndpoint)
.oidcUserInfoEndpoint(userInfoEndpoint)
.build();
ProviderContextHolder.setProviderContext(new ProviderContext(providerSettings, null));
OidcProviderConfigurationEndpointFilter filter =
@ -126,6 +128,7 @@ public class OidcProviderConfigurationEndpointFilterTests { @@ -126,6 +128,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\"]");
assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]");
assertThat(providerConfigurationResponse).contains("\"id_token_signing_alg_values_supported\":[\"RS256\"]");
assertThat(providerConfigurationResponse).contains("\"userinfo_endpoint\":\"https://example.com/issuer1/userinfo\"");
assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\"]");
}

Loading…
Cancel
Save