From d4d7199a6d98f404595585fe6715e1451f1e8e26 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Thu, 12 Oct 2017 06:13:53 -0400 Subject: [PATCH] Polish oauth2-core --- .../AuthorizationRequestRedirectFilter.java | 2 +- ...DefaultAuthorizationRequestUriBuilder.java | 2 +- ...rizationCodeAuthenticationFilterTests.java | 2 +- ...thorizationRequestRedirectFilterTests.java | 2 +- .../security/oauth2/core/AccessToken.java | 42 +++--- .../oauth2/core/AuthorizationGrantType.java | 3 - .../security/oauth2/core/ClaimAccessor.java | 6 +- .../core/ClientAuthenticationMethod.java | 2 +- .../security/oauth2/core/SecurityToken.java | 5 +- .../core/endpoint/AuthorizationRequest.java | 66 +++++---- .../oauth2/core/endpoint/ResponseType.java | 2 +- .../oauth2/core/endpoint/TokenResponse.java | 8 +- .../oauth2/core/user/DefaultOAuth2User.java | 20 ++- .../oauth2/core/user/OAuth2UserAuthority.java | 2 +- .../security/oauth2/oidc/core/Address.java | 92 ------------ .../oauth2/oidc/core/DefaultAddress.java | 136 ++++++++++++++++++ .../oidc/core/StandardClaimAccessor.java | 8 +- .../oauth2/oidc/core/user/OidcUser.java | 1 - .../oidc/core/user/OidcUserAuthority.java | 6 +- .../endpoint/AuthorizationRequestTest.java | 20 +-- .../oidc/core/user/DefaultOidcUserTests.java | 2 +- 21 files changed, 244 insertions(+), 185 deletions(-) create mode 100644 oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/DefaultAddress.java diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilter.java index 5e2d132028..cbc76fda36 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilter.java @@ -142,7 +142,7 @@ public class AuthorizationRequestRedirectFilter extends OncePerRequestFilter { } AuthorizationRequest authorizationRequest = builder .clientId(clientRegistration.getClientId()) - .authorizeUri(clientRegistration.getProviderDetails().getAuthorizationUri()) + .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) .redirectUri(redirectUriStr) .scope(clientRegistration.getScope()) .state(this.stateGenerator.generateKey()) diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultAuthorizationRequestUriBuilder.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultAuthorizationRequestUriBuilder.java index 456f97e7c6..0aa3883e3f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultAuthorizationRequestUriBuilder.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultAuthorizationRequestUriBuilder.java @@ -37,7 +37,7 @@ public class DefaultAuthorizationRequestUriBuilder implements AuthorizationReque @Override public URI build(AuthorizationRequest authorizationRequest) { UriComponentsBuilder uriBuilder = UriComponentsBuilder - .fromUriString(authorizationRequest.getAuthorizeUri()) + .fromUriString(authorizationRequest.getAuthorizationUri()) .queryParam(OAuth2Parameter.RESPONSE_TYPE, authorizationRequest.getResponseType().getValue()) .queryParam(OAuth2Parameter.CLIENT_ID, authorizationRequest.getClientId()) .queryParam(OAuth2Parameter.SCOPE, diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationCodeAuthenticationFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationCodeAuthenticationFilterTests.java index 24da2a645f..fab9a25266 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationCodeAuthenticationFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationCodeAuthenticationFilterTests.java @@ -199,7 +199,7 @@ public class AuthorizationCodeAuthenticationFilterTests { AuthorizationRequest authorizationRequest = AuthorizationRequest.authorizationCode() .clientId(clientRegistration.getClientId()) - .authorizeUri(clientRegistration.getProviderDetails().getAuthorizationUri()) + .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) .redirectUri(clientRegistration.getRedirectUri()) .scope(clientRegistration.getScope()) .state(state) diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilterTests.java index bab7590fa5..c01c1f973c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRedirectFilterTests.java @@ -104,7 +104,7 @@ public class AuthorizationRequestRedirectFilterTests { authorizationRequestRepository.loadAuthorizationRequest(request); Assertions.assertThat(authorizationRequest).isNotNull(); - Assertions.assertThat(authorizationRequest.getAuthorizeUri()).isNotNull(); + Assertions.assertThat(authorizationRequest.getAuthorizationUri()).isNotNull(); Assertions.assertThat(authorizationRequest.getGrantType()).isNotNull(); Assertions.assertThat(authorizationRequest.getResponseType()).isNotNull(); Assertions.assertThat(authorizationRequest.getClientId()).isNotNull(); diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AccessToken.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AccessToken.java index 4e640adce8..78a23bfe7b 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AccessToken.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AccessToken.java @@ -38,11 +38,31 @@ public class AccessToken extends SecurityToken { private final TokenType tokenType; private final Set scope; + public AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt) { + this(tokenType, tokenValue, issuedAt, expiresAt, Collections.emptySet()); + } + + public AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt, Set scope) { + super(tokenValue, issuedAt, expiresAt); + Assert.notNull(tokenType, "tokenType cannot be null"); + this.tokenType = tokenType; + this.scope = Collections.unmodifiableSet( + scope != null ? scope : Collections.emptySet()); + } + + public TokenType getTokenType() { + return this.tokenType; + } + + public Set getScope() { + return this.scope; + } + public static final class TokenType { public static final TokenType BEARER = new TokenType("Bearer"); private final String value; - public TokenType(String value) { + private TokenType(String value) { Assert.hasText(value, "value cannot be empty"); this.value = value; } @@ -68,24 +88,4 @@ public class AccessToken extends SecurityToken { return this.getValue().hashCode(); } } - - public AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt) { - this(tokenType, tokenValue, issuedAt, expiresAt, Collections.emptySet()); - } - - public AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt, Set scope) { - super(tokenValue, issuedAt, expiresAt); - Assert.notNull(tokenType, "tokenType cannot be null"); - this.tokenType = tokenType; - this.scope = Collections.unmodifiableSet( - scope != null ? scope : Collections.emptySet()); - } - - public TokenType getTokenType() { - return this.tokenType; - } - - public Set getScope() { - return this.scope; - } } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java index 750a3b7d7b..de7a7300b6 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java @@ -26,9 +26,6 @@ import org.springframework.util.Assert; * authorization code, implicit, resource owner password credentials, and client credentials. * It also provides an extensibility mechanism for defining additional grant types. * - *

- * NOTE: "authorization code" is currently the only supported grant type. - * * @author Joe Grandja * @since 5.0 * @see Section 1.3 Authorization Grant diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java index 3038aa2232..4e68579f4f 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java @@ -74,9 +74,9 @@ public interface ClaimAccessor { if (!this.containsClaim(claim) || !Map.class.isAssignableFrom(this.getClaims().get(claim).getClass())) { return null; } - Map claimFields = new HashMap<>(); - ((Map)this.getClaims().get(claim)).forEach((k, v) -> claimFields.put(k.toString(), v)); - return claimFields; + Map claimValues = new HashMap<>(); + ((Map)this.getClaims().get(claim)).forEach((k, v) -> claimValues.put(k.toString(), v)); + return claimValues; } default List getClaimAsStringList(String claim) { diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java index 957cd0a0c8..011234ade6 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java @@ -18,7 +18,7 @@ package org.springframework.security.oauth2.core; import org.springframework.util.Assert; /** - * The available authentication methods used when authenticating the client with the authorization server. + * The authentication methods used when authenticating the client with the authorization server. * * @author Joe Grandja * @since 5.0 diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/SecurityToken.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/SecurityToken.java index b319805b3b..6db165df61 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/SecurityToken.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/SecurityToken.java @@ -24,9 +24,6 @@ import java.time.Instant; /** * Base class for Security Token implementations. * - *

- * It is highly recommended that implementations be immutable. - * * @author Joe Grandja * @since 5.0 */ @@ -37,7 +34,7 @@ public abstract class SecurityToken implements Serializable { private final Instant expiresAt; protected SecurityToken(String tokenValue, Instant issuedAt, Instant expiresAt) { - Assert.hasLength(tokenValue, "tokenValue cannot be empty"); + Assert.hasText(tokenValue, "tokenValue cannot be empty"); Assert.notNull(issuedAt, "issuedAt cannot be null"); Assert.notNull(expiresAt, "expiresAt cannot be null"); this.tokenValue = tokenValue; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequest.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequest.java index 595455bcfa..ba7b217c47 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequest.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequest.java @@ -38,7 +38,7 @@ import java.util.Set; * @see Section 4.2.1 Implicit Grant Request */ public final class AuthorizationRequest implements Serializable { - private String authorizeUri; + private String authorizationUri; private AuthorizationGrantType authorizationGrantType; private ResponseType responseType; private String clientId; @@ -50,8 +50,8 @@ public final class AuthorizationRequest implements Serializable { private AuthorizationRequest() { } - public String getAuthorizeUri() { - return this.authorizeUri; + public String getAuthorizationUri() { + return this.authorizationUri; } public AuthorizationGrantType getGrantType() { @@ -91,62 +91,76 @@ public final class AuthorizationRequest implements Serializable { } public static class Builder { - private final AuthorizationRequest authorizationRequest; + private String authorizationUri; + private AuthorizationGrantType authorizationGrantType; + private ResponseType responseType; + private String clientId; + private String redirectUri; + private Set scope; + private String state; + private Map additionalParameters; private Builder(AuthorizationGrantType authorizationGrantType) { Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null"); - this.authorizationRequest = new AuthorizationRequest(); - this.authorizationRequest.authorizationGrantType = authorizationGrantType; + this.authorizationGrantType = authorizationGrantType; if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationGrantType)) { - this.authorizationRequest.responseType = ResponseType.CODE; + this.responseType = ResponseType.CODE; } else if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) { - this.authorizationRequest.responseType = ResponseType.TOKEN; + this.responseType = ResponseType.TOKEN; } } - public Builder authorizeUri(String authorizeUri) { - this.authorizationRequest.authorizeUri = authorizeUri; + public Builder authorizationUri(String authorizationUri) { + this.authorizationUri = authorizationUri; return this; } public Builder clientId(String clientId) { - this.authorizationRequest.clientId = clientId; + this.clientId = clientId; return this; } public Builder redirectUri(String redirectUri) { - this.authorizationRequest.redirectUri = redirectUri; + this.redirectUri = redirectUri; return this; } public Builder scope(Set scope) { - this.authorizationRequest.scope = scope; + this.scope = scope; return this; } public Builder state(String state) { - this.authorizationRequest.state = state; + this.state = state; return this; } public Builder additionalParameters(Map additionalParameters) { - this.authorizationRequest.additionalParameters = additionalParameters; + this.additionalParameters = additionalParameters; return this; } public AuthorizationRequest build() { - Assert.hasText(this.authorizationRequest.authorizeUri, "authorizeUri cannot be empty"); - Assert.hasText(this.authorizationRequest.clientId, "clientId cannot be empty"); - if (AuthorizationGrantType.IMPLICIT.equals(this.authorizationRequest.authorizationGrantType)) { - Assert.hasText(this.authorizationRequest.redirectUri, "redirectUri cannot be empty"); + Assert.hasText(this.authorizationUri, "authorizationUri cannot be empty"); + Assert.hasText(this.clientId, "clientId cannot be empty"); + if (AuthorizationGrantType.IMPLICIT.equals(this.authorizationGrantType)) { + Assert.hasText(this.redirectUri, "redirectUri cannot be empty"); } - this.authorizationRequest.scope = Collections.unmodifiableSet( - CollectionUtils.isEmpty(this.authorizationRequest.scope) ? - Collections.emptySet() : new LinkedHashSet<>(this.authorizationRequest.scope)); - this.authorizationRequest.additionalParameters = Collections.unmodifiableMap( - CollectionUtils.isEmpty(this.authorizationRequest.additionalParameters) ? - Collections.emptyMap() : new LinkedHashMap<>(this.authorizationRequest.additionalParameters)); - return this.authorizationRequest; + + AuthorizationRequest authorizationRequest = new AuthorizationRequest(); + authorizationRequest.authorizationUri = this.authorizationUri; + authorizationRequest.authorizationGrantType = this.authorizationGrantType; + authorizationRequest.responseType = this.responseType; + authorizationRequest.clientId = this.clientId; + authorizationRequest.redirectUri = this.redirectUri; + authorizationRequest.state = this.state; + authorizationRequest.scope = Collections.unmodifiableSet( + CollectionUtils.isEmpty(this.scope) ? + Collections.emptySet() : new LinkedHashSet<>(this.scope)); + authorizationRequest.additionalParameters = Collections.unmodifiableMap( + CollectionUtils.isEmpty(this.additionalParameters) ? + Collections.emptyMap() : new LinkedHashMap<>(this.additionalParameters)); + return authorizationRequest; } } } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/ResponseType.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/ResponseType.java index 7f040efa3e..f8feffcdd4 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/ResponseType.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/ResponseType.java @@ -35,7 +35,7 @@ public final class ResponseType { public static final ResponseType TOKEN = new ResponseType("token"); private final String value; - public ResponseType(String value) { + private ResponseType(String value) { Assert.hasText(value, "value cannot be empty"); this.value = value; } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/TokenResponse.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/TokenResponse.java index a4aa50f8d4..985425423f 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/TokenResponse.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/TokenResponse.java @@ -17,6 +17,7 @@ package org.springframework.security.oauth2.core.endpoint; import org.springframework.security.oauth2.core.AccessToken; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import java.time.Instant; import java.util.Collections; @@ -100,12 +101,11 @@ public final class TokenResponse { public TokenResponse build() { Assert.isTrue(this.expiresIn >= 0, "expiresIn must be a positive number"); Instant issuedAt = Instant.now(); - AccessToken accessToken = new AccessToken(this.tokenType, this.tokenValue, issuedAt, - issuedAt.plusSeconds(this.expiresIn), this.scope); TokenResponse tokenResponse = new TokenResponse(); - tokenResponse.accessToken = accessToken; + tokenResponse.accessToken = new AccessToken(this.tokenType, this.tokenValue, issuedAt, + issuedAt.plusSeconds(this.expiresIn), this.scope); tokenResponse.additionalParameters = Collections.unmodifiableMap( - this.additionalParameters != null ? this.additionalParameters : Collections.emptyMap()); + CollectionUtils.isEmpty(this.additionalParameters) ? Collections.emptyMap() : this.additionalParameters); return tokenResponse; } } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java index 2b6a96446a..706d397241 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java @@ -19,7 +19,15 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.util.Assert; -import java.util.*; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; /** @@ -37,10 +45,10 @@ import java.util.stream.Collectors; * @since 5.0 * @see OAuth2User */ -public class DefaultOAuth2User implements OAuth2User { +public class DefaultOAuth2User implements OAuth2User, Serializable { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final Set authorities; - private Map attributes; + private final Map attributes; private final String nameAttributeKey; public DefaultOAuth2User(Set authorities, Map attributes, String nameAttributeKey) { @@ -48,7 +56,7 @@ public class DefaultOAuth2User implements OAuth2User { Assert.notEmpty(attributes, "attributes cannot be empty"); Assert.hasText(nameAttributeKey, "nameAttributeKey cannot be empty"); if (!attributes.containsKey(nameAttributeKey)) { - throw new IllegalArgumentException("Invalid nameAttributeKey: " + nameAttributeKey); + throw new IllegalArgumentException("Missing attribute '" + nameAttributeKey + "' in attributes"); } this.authorities = Collections.unmodifiableSet(this.sortAuthorities(authorities)); this.attributes = Collections.unmodifiableMap(new LinkedHashMap<>(attributes)); @@ -72,8 +80,8 @@ public class DefaultOAuth2User implements OAuth2User { private Set sortAuthorities(Set authorities) { SortedSet sortedAuthorities = - new TreeSet<>((g1, g2) -> g1.getAuthority().compareTo(g2.getAuthority())); - authorities.stream().forEach(sortedAuthorities::add); + new TreeSet<>(Comparator.comparing(GrantedAuthority::getAuthority)); + sortedAuthorities.addAll(authorities); return sortedAuthorities; } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java index 2d460d5a8b..1dc4f2e1ea 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java @@ -33,7 +33,7 @@ import java.util.Map; public class OAuth2UserAuthority implements GrantedAuthority { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final String authority; - private Map attributes; + private final Map attributes; public OAuth2UserAuthority(Map attributes) { this("ROLE_USER", attributes); diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/Address.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/Address.java index 445926b4bd..0470fc5ad7 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/Address.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/Address.java @@ -15,8 +15,6 @@ */ package org.springframework.security.oauth2.oidc.core; -import java.util.Map; - /** * The Address Claim represents a physical mailing address defined by the OpenID Connect Core 1.0 specification * that can be returned either in the UserInfo Response or the ID Token. @@ -41,94 +39,4 @@ public interface Address { String getCountry(); - class Builder implements Address { - private static final String FORMATTED_FIELD_NAME = "formatted"; - private static final String STREET_ADDRESS_FIELD_NAME = "street_address"; - private static final String LOCALITY_FIELD_NAME = "locality"; - private static final String REGION_FIELD_NAME = "region"; - private static final String POSTAL_CODE_FIELD_NAME = "postal_code"; - private static final String COUNTRY_FIELD_NAME = "country"; - private String formatted; - private String streetAddress; - private String locality; - private String region; - private String postalCode; - private String country; - - public Builder() { - } - - public Builder(Map addressFields) { - this.formatted((String)addressFields.get(FORMATTED_FIELD_NAME)); - this.streetAddress((String)addressFields.get(STREET_ADDRESS_FIELD_NAME)); - this.locality((String)addressFields.get(LOCALITY_FIELD_NAME)); - this.region((String)addressFields.get(REGION_FIELD_NAME)); - this.postalCode((String)addressFields.get(POSTAL_CODE_FIELD_NAME)); - this.country((String)addressFields.get(COUNTRY_FIELD_NAME)); - } - - public Builder formatted(String formatted) { - this.formatted = formatted; - return this; - } - - public Builder streetAddress(String streetAddress) { - this.streetAddress = streetAddress; - return this; - } - - public Builder locality(String locality) { - this.locality = locality; - return this; - } - - public Builder region(String region) { - this.region = region; - return this; - } - - public Builder postalCode(String postalCode) { - this.postalCode = postalCode; - return this; - } - - public Builder country(String country) { - this.country = country; - return this; - } - - public Address build() { - return this; - } - - @Override - public String getFormatted() { - return this.formatted; - } - - @Override - public String getStreetAddress() { - return this.streetAddress; - } - - @Override - public String getLocality() { - return this.locality; - } - - @Override - public String getRegion() { - return this.region; - } - - @Override - public String getPostalCode() { - return this.postalCode; - } - - @Override - public String getCountry() { - return this.country; - } - } } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/DefaultAddress.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/DefaultAddress.java new file mode 100644 index 0000000000..3e0ade316a --- /dev/null +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/DefaultAddress.java @@ -0,0 +1,136 @@ +/* + * Copyright 2012-2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.oidc.core; + +import java.util.Map; + +/** + * The default implementation of an {@link Address}. + * + * @author Joe Grandja + * @since 5.0 + * @see Address + */ +public final class DefaultAddress implements Address { + private String formatted; + private String streetAddress; + private String locality; + private String region; + private String postalCode; + private String country; + + private DefaultAddress() { + } + + @Override + public String getFormatted() { + return this.formatted; + } + + @Override + public String getStreetAddress() { + return this.streetAddress; + } + + @Override + public String getLocality() { + return this.locality; + } + + @Override + public String getRegion() { + return this.region; + } + + @Override + public String getPostalCode() { + return this.postalCode; + } + + @Override + public String getCountry() { + return this.country; + } + + public static class Builder { + private static final String FORMATTED_FIELD_NAME = "formatted"; + private static final String STREET_ADDRESS_FIELD_NAME = "street_address"; + private static final String LOCALITY_FIELD_NAME = "locality"; + private static final String REGION_FIELD_NAME = "region"; + private static final String POSTAL_CODE_FIELD_NAME = "postal_code"; + private static final String COUNTRY_FIELD_NAME = "country"; + private String formatted; + private String streetAddress; + private String locality; + private String region; + private String postalCode; + private String country; + + public Builder() { + } + + public Builder(Map addressFields) { + this.formatted((String)addressFields.get(FORMATTED_FIELD_NAME)); + this.streetAddress((String)addressFields.get(STREET_ADDRESS_FIELD_NAME)); + this.locality((String)addressFields.get(LOCALITY_FIELD_NAME)); + this.region((String)addressFields.get(REGION_FIELD_NAME)); + this.postalCode((String)addressFields.get(POSTAL_CODE_FIELD_NAME)); + this.country((String)addressFields.get(COUNTRY_FIELD_NAME)); + } + + public Builder formatted(String formatted) { + this.formatted = formatted; + return this; + } + + public Builder streetAddress(String streetAddress) { + this.streetAddress = streetAddress; + return this; + } + + public Builder locality(String locality) { + this.locality = locality; + return this; + } + + public Builder region(String region) { + this.region = region; + return this; + } + + public Builder postalCode(String postalCode) { + this.postalCode = postalCode; + return this; + } + + public Builder country(String country) { + this.country = country; + return this; + } + + public Address build() { + DefaultAddress address = new DefaultAddress(); + address.formatted = this.formatted; + address.streetAddress = this.streetAddress; + address.locality = this.locality; + address.region = this.region; + address.postalCode = this.postalCode; + address.country = this.country; + + return address; + } + } +} diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/StandardClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/StandardClaimAccessor.java index 2b00fa9ec2..a8d162fc06 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/StandardClaimAccessor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/StandardClaimAccessor.java @@ -16,6 +16,7 @@ package org.springframework.security.oauth2.oidc.core; import org.springframework.security.oauth2.core.ClaimAccessor; +import org.springframework.util.CollectionUtils; import java.time.Instant; import java.util.Map; @@ -28,7 +29,6 @@ import java.util.Map; * @see StandardClaim * @see UserInfo * @see UserInfo Response - * @see ID Token * @see Standard Claims * @author Joe Grandja * @since 5.0 @@ -109,9 +109,9 @@ public interface StandardClaimAccessor extends ClaimAccessor { default Address getAddress() { Map addressFields = this.getClaimAsMap(StandardClaim.ADDRESS); - return (addressFields != null ? - new Address.Builder(addressFields).build() : - new Address.Builder().build()); + return (!CollectionUtils.isEmpty(addressFields) ? + new DefaultAddress.Builder(addressFields).build() : + new DefaultAddress.Builder().build()); } default Instant getUpdatedAt() { diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUser.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUser.java index 8c63fa8aac..204123ebd9 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUser.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUser.java @@ -48,7 +48,6 @@ import java.util.Map; * @see UserInfo * @see IdTokenClaimAccessor * @see StandardClaimAccessor - * @see OpenID Connect Core 1.0 * @see ID Token * @see Standard Claims */ diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUserAuthority.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUserAuthority.java index 23a98162ef..5d6e669622 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUserAuthority.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/oidc/core/user/OidcUserAuthority.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.oidc.core.user; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; import org.springframework.security.oauth2.oidc.core.IdToken; import org.springframework.security.oauth2.oidc.core.UserInfo; @@ -29,7 +28,6 @@ import org.springframework.security.oauth2.oidc.core.UserInfo; * @see OidcUser */ public class OidcUserAuthority extends OAuth2UserAuthority { - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final IdToken idToken; private final UserInfo userInfo; @@ -72,7 +70,9 @@ public class OidcUserAuthority extends OAuth2UserAuthority { if (!this.getIdToken().equals(that.getIdToken())) { return false; } - return this.getUserInfo() != null ? this.getUserInfo().equals(that.getUserInfo()) : that.getUserInfo() == null; + return this.getUserInfo() != null ? + this.getUserInfo().equals(that.getUserInfo()) : + that.getUserInfo() == null; } @Override diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequestTest.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequestTest.java index 49cb7f2dc4..7a56563e0c 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequestTest.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/AuthorizationRequestTest.java @@ -38,7 +38,7 @@ public class AuthorizationRequestTest { @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationUriIsNullThenThrowIllegalArgumentException() { AuthorizationRequest.authorizationCode() - .authorizeUri(null) + .authorizationUri(null) .clientId(CLIENT_ID) .redirectUri(REDIRECT_URI) .scope(SCOPE) @@ -59,7 +59,7 @@ public class AuthorizationRequestTest { @Test(expected = IllegalArgumentException.class) public void buildWhenClientIdIsNullThenThrowIllegalArgumentException() { AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(null) .redirectUri(REDIRECT_URI) .scope(SCOPE) @@ -70,7 +70,7 @@ public class AuthorizationRequestTest { @Test(expected = IllegalArgumentException.class) public void buildWhenClientIdNotSetThenThrowIllegalArgumentException() { AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .redirectUri(REDIRECT_URI) .scope(SCOPE) .state(STATE) @@ -81,7 +81,7 @@ public class AuthorizationRequestTest { public void buildWhenGetResponseTypeIsCalledThenReturnCode() { AuthorizationRequest authorizationRequest; authorizationRequest = AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .redirectUri(REDIRECT_URI) .scope(SCOPE) @@ -94,7 +94,7 @@ public class AuthorizationRequestTest { @Test public void buildWhenRedirectUriIsNullThenDoesNotThrowAnyException() { assertThatCode(() -> AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .redirectUri(null) .scope(SCOPE) @@ -105,7 +105,7 @@ public class AuthorizationRequestTest { @Test public void buildWhenRedirectUriNotSetThenDoesNotThrowAnyException() { assertThatCode(() -> AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .scope(SCOPE) .state(STATE) @@ -115,7 +115,7 @@ public class AuthorizationRequestTest { @Test public void buildWhenScopesIsNullThenDoesNotThrowAnyException() { assertThatCode(() -> AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .redirectUri(REDIRECT_URI) .scope(null) @@ -126,7 +126,7 @@ public class AuthorizationRequestTest { @Test public void buildWhenScopesNotSetThenDoesNotThrowAnyException() { assertThatCode(() -> AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .redirectUri(REDIRECT_URI) .state(STATE) @@ -136,7 +136,7 @@ public class AuthorizationRequestTest { @Test public void buildWhenStateIsNullThenDoesNotThrowAnyException() { assertThatCode(() -> AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .redirectUri(REDIRECT_URI) .scope(SCOPE) @@ -147,7 +147,7 @@ public class AuthorizationRequestTest { @Test public void buildWhenStateNotSetThenDoesNotThrowAnyException() { assertThatCode(() -> AuthorizationRequest.authorizationCode() - .authorizeUri(AUTHORIZE_URI) + .authorizationUri(AUTHORIZE_URI) .clientId(CLIENT_ID) .redirectUri(REDIRECT_URI) .scope(SCOPE) diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/oidc/core/user/DefaultOidcUserTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/oidc/core/user/DefaultOidcUserTests.java index be576a9fe3..b5ac3561a2 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/oidc/core/user/DefaultOidcUserTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/oidc/core/user/DefaultOidcUserTests.java @@ -114,7 +114,7 @@ public class DefaultOidcUserTests { @Test public void constructorWhenNameAttributeKeyClaimIsNotPresentThenThrowsException() { this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("Invalid nameAttributeKey: " + StandardClaim.NAME); + this.thrown.expectMessage("Missing attribute '" + StandardClaim.NAME + "' in attributes"); new DefaultOidcUser(TEST_AUTHORITIES, TEST_ID_TOKEN, TEST_USER_INFO, StandardClaim.NAME); }