浏览代码

Add tests to oauth2-core

Fixes gh-4298
Joe Grandja 7 年之前
父节点
当前提交
db35dc6c03
共有 20 个文件被更改,包括 1187 次插入210 次删除
  1. 2 0
      oauth2/oauth2-core/spring-security-oauth2-core.gradle
  2. 1 0
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2Token.java
  3. 1 1
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java
  4. 40 0
      oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaim.java
  5. 43 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthorizationGrantTypeTests.java
  6. 43 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClientAuthenticationMethodTests.java
  7. 85 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2AccessTokenTests.java
  8. 45 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2ErrorTests.java
  9. 43 25
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java
  10. 54 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationExchangeTests.java
  11. 78 58
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java
  12. 127 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTests.java
  13. 38 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTypeTests.java
  14. 85 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaimTests.java
  15. 121 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java
  16. 142 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java
  17. 68 62
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java
  18. 79 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthorityTests.java
  19. 36 64
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java
  20. 56 0
      oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthorityTests.java

+ 2 - 0
oauth2/oauth2-core/spring-security-oauth2-core.gradle

@@ -3,4 +3,6 @@ apply plugin: 'io.spring.convention.spring-module'
 dependencies {
 	compile project(':spring-security-core')
 	compile springCoreDependency
+
+	testCompile powerMock2Dependencies
 }

+ 1 - 0
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2Token.java

@@ -37,6 +37,7 @@ public abstract class AbstractOAuth2Token implements Serializable {
 		Assert.hasText(tokenValue, "tokenValue cannot be empty");
 		Assert.notNull(issuedAt, "issuedAt cannot be null");
 		Assert.notNull(expiresAt, "expiresAt cannot be null");
+		Assert.isTrue(expiresAt.isAfter(issuedAt), "expiresAt must be after issuedAt");
 		this.tokenValue = tokenValue;
 		this.issuedAt = issuedAt;
 		this.expiresAt = expiresAt;

+ 1 - 1
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java

@@ -53,7 +53,7 @@ public interface ClaimAccessor {
 			return null;
 		}
 		try {
-			return Instant.ofEpochSecond(Long.valueOf(this.getClaimAsString(claim)));
+			return Instant.ofEpochMilli(Long.valueOf(this.getClaimAsString(claim)));
 		} catch (NumberFormatException ex) {
 			throw new IllegalArgumentException("Unable to convert claim '" + claim + "' to Instant: " + ex.getMessage(), ex);
 		}

+ 40 - 0
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaim.java

@@ -65,6 +65,46 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
 		return this.country;
 	}
 
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj == null || !AddressStandardClaim.class.isAssignableFrom(obj.getClass())) {
+			return false;
+		}
+
+		AddressStandardClaim that = (AddressStandardClaim) obj;
+
+		if (this.getFormatted() != null ? !this.getFormatted().equals(that.getFormatted()) : that.getFormatted() != null) {
+			return false;
+		}
+		if (this.getStreetAddress() != null ? !this.getStreetAddress().equals(that.getStreetAddress()) : that.getStreetAddress() != null) {
+			return false;
+		}
+		if (this.getLocality() != null ? !this.getLocality().equals(that.getLocality()) : that.getLocality() != null) {
+			return false;
+		}
+		if (this.getRegion() != null ? !this.getRegion().equals(that.getRegion()) : that.getRegion() != null) {
+			return false;
+		}
+		if (this.getPostalCode() != null ? !this.getPostalCode().equals(that.getPostalCode()) : that.getPostalCode() != null) {
+			return false;
+		}
+		return this.getCountry() != null ? this.getCountry().equals(that.getCountry()) : that.getCountry() == null;
+	}
+
+	@Override
+	public int hashCode() {
+		int result = this.getFormatted() != null ? this.getFormatted().hashCode() : 0;
+		result = 31 * result + (this.getStreetAddress() != null ? this.getStreetAddress().hashCode() : 0);
+		result = 31 * result + (this.getLocality() != null ? this.getLocality().hashCode() : 0);
+		result = 31 * result + (this.getRegion() != null ? this.getRegion().hashCode() : 0);
+		result = 31 * result + (this.getPostalCode() != null ? this.getPostalCode().hashCode() : 0);
+		result = 31 * result + (this.getCountry() != null ? this.getCountry().hashCode() : 0);
+		return result;
+	}
+
 	public static class Builder {
 		private static final String FORMATTED_FIELD_NAME = "formatted";
 		private static final String STREET_ADDRESS_FIELD_NAME = "street_address";

+ 43 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthorizationGrantTypeTests.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-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.core;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link AuthorizationGrantType}.
+ *
+ * @author Joe Grandja
+ */
+public class AuthorizationGrantTypeTests {
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenValueIsNullThenThrowIllegalArgumentException() {
+		new AuthorizationGrantType(null);
+	}
+
+	@Test
+	public void getValueWhenAuthorizationCodeGrantTypeThenReturnAuthorizationCode() {
+		assertThat(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()).isEqualTo("authorization_code");
+	}
+
+	@Test
+	public void getValueWhenImplicitGrantTypeThenReturnImplicit() {
+		assertThat(AuthorizationGrantType.IMPLICIT.getValue()).isEqualTo("implicit");
+	}
+}

+ 43 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClientAuthenticationMethodTests.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-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.core;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ClientAuthenticationMethod}.
+ *
+ * @author Joe Grandja
+ */
+public class ClientAuthenticationMethodTests {
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenValueIsNullThenThrowIllegalArgumentException() {
+		new ClientAuthenticationMethod(null);
+	}
+
+	@Test
+	public void getValueWhenAuthenticationMethodBasicThenReturnBasic() {
+		assertThat(ClientAuthenticationMethod.BASIC.getValue()).isEqualTo("basic");
+	}
+
+	@Test
+	public void getValueWhenAuthenticationMethodPostThenReturnPost() {
+		assertThat(ClientAuthenticationMethod.POST.getValue()).isEqualTo("post");
+	}
+}

+ 85 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2AccessTokenTests.java

@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002-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.core;
+
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link OAuth2AccessToken}.
+ *
+ * @author Joe Grandja
+ */
+public class OAuth2AccessTokenTests {
+	private static final OAuth2AccessToken.TokenType TOKEN_TYPE = OAuth2AccessToken.TokenType.BEARER;
+	private static final String TOKEN_VALUE = "access-token";
+	private static final Instant ISSUED_AT = Instant.now();
+	private static final Instant EXPIRES_AT = Instant.from(ISSUED_AT).plusSeconds(60);
+	private static final Set<String> SCOPES = new LinkedHashSet<>(Arrays.asList("scope1", "scope2"));
+
+	@Test
+	public void tokenTypeGetValueWhenTokenTypeBearerThenReturnBearer() {
+		assertThat(OAuth2AccessToken.TokenType.BEARER.getValue()).isEqualTo("Bearer");
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenTokenTypeIsNullThenThrowIllegalArgumentException() {
+		new OAuth2AccessToken(null, TOKEN_VALUE, ISSUED_AT, EXPIRES_AT);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenTokenValueIsNullThenThrowIllegalArgumentException() {
+		new OAuth2AccessToken(TOKEN_TYPE, null, ISSUED_AT, EXPIRES_AT);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenIssuedAtIsNullThenThrowIllegalArgumentException() {
+		new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, null, EXPIRES_AT);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenExpiresAtIsNullThenThrowIllegalArgumentException() {
+		new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, null);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenIssuedAtAfterExpiresAtThenThrowIllegalArgumentException() {
+		new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, Instant.from(EXPIRES_AT).plusSeconds(1), EXPIRES_AT);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenExpiresAtBeforeIssuedAtThenThrowIllegalArgumentException() {
+		new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, Instant.from(ISSUED_AT).minusSeconds(1));
+	}
+
+	@Test
+	public void constructorWhenAllParametersProvidedAndValidThenCreated() {
+		OAuth2AccessToken accessToken = new OAuth2AccessToken(
+			TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, EXPIRES_AT, SCOPES);
+
+		assertThat(accessToken.getTokenType()).isEqualTo(TOKEN_TYPE);
+		assertThat(accessToken.getTokenValue()).isEqualTo(TOKEN_VALUE);
+		assertThat(accessToken.getIssuedAt()).isEqualTo(ISSUED_AT);
+		assertThat(accessToken.getExpiresAt()).isEqualTo(EXPIRES_AT);
+		assertThat(accessToken.getScopes()).isEqualTo(SCOPES);
+	}
+}

+ 45 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2ErrorTests.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-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.core;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link OAuth2Error}.
+ *
+ * @author Joe Grandja
+ */
+public class OAuth2ErrorTests {
+	private static final String ERROR_CODE = "error-code";
+	private static final String ERROR_DESCRIPTION = "error-description";
+	private static final String ERROR_URI = "error-uri";
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenErrorCodeIsNullThenThrowIllegalArgumentException() {
+		new OAuth2Error(null, ERROR_DESCRIPTION, ERROR_URI);
+	}
+
+	@Test
+	public void constructorWhenAllParametersProvidedAndValidThenCreated() {
+		OAuth2Error error = new OAuth2Error(ERROR_CODE, ERROR_DESCRIPTION, ERROR_URI);
+
+		assertThat(error.getErrorCode()).isEqualTo(ERROR_CODE);
+		assertThat(error.getDescription()).isEqualTo(ERROR_DESCRIPTION);
+		assertThat(error.getUri()).isEqualTo(ERROR_URI);
+	}
+}

+ 43 - 25
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java

@@ -18,53 +18,71 @@ package org.springframework.security.oauth2.core.endpoint;
 import org.junit.Test;
 import org.springframework.security.oauth2.core.OAuth2AccessToken;
 
-import java.util.Collections;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
 
 /**
- * Tests {@link OAuth2AccessTokenResponse}
+ * Tests for {@link OAuth2AccessTokenResponse}.
  *
  * @author Luander Ribeiro
+ * @author Joe Grandja
  */
 public class OAuth2AccessTokenResponseTests {
-
-	private static final String TOKEN = "token";
-	private static final long INVALID_EXPIRES_IN = -1L;
-	private static final long EXPIRES_IN = System.currentTimeMillis();
+	private static final String TOKEN_VALUE = "access-token";
+	private static final long EXPIRES_IN = Instant.now().plusSeconds(5).toEpochMilli();
 
 	@Test(expected = IllegalArgumentException.class)
 	public void buildWhenTokenValueIsNullThenThrowIllegalArgumentException() {
 		OAuth2AccessTokenResponse.withToken(null)
-			.expiresIn(EXPIRES_IN)
-			.additionalParameters(Collections.emptyMap())
-			.scopes(Collections.emptySet())
 			.tokenType(OAuth2AccessToken.TokenType.BEARER)
+			.expiresIn(EXPIRES_IN)
 			.build();
 	}
 
 	@Test(expected = IllegalArgumentException.class)
-	public void buildWhenExpiresInIsNegativeThenThrowIllegalArgumentException() {
-		OAuth2AccessTokenResponse.withToken(TOKEN)
-			.expiresIn(INVALID_EXPIRES_IN)
-			.additionalParameters(Collections.emptyMap())
-			.scopes(Collections.emptySet())
-			.tokenType(OAuth2AccessToken.TokenType.BEARER)
+	public void buildWhenTokenTypeIsNullThenThrowIllegalArgumentException() {
+		OAuth2AccessTokenResponse.withToken(TOKEN_VALUE)
+			.tokenType(null)
+			.expiresIn(EXPIRES_IN)
 			.build();
 	}
 
 	@Test(expected = IllegalArgumentException.class)
-	public void buildWhenTokenTypeIsInvalidThenThrowIllegalArgumentException() {
-		OAuth2AccessTokenResponse.withToken(TOKEN)
-			.expiresIn(EXPIRES_IN)
-			.additionalParameters(Collections.emptyMap())
-			.tokenType(null)
+	public void buildWhenExpiresInIsNegativeThenThrowIllegalArgumentException() {
+		OAuth2AccessTokenResponse.withToken(TOKEN_VALUE)
+			.tokenType(OAuth2AccessToken.TokenType.BEARER)
+			.expiresIn(-1L)
 			.build();
 	}
 
-	@Test(expected = IllegalArgumentException.class)
-	public void buildWhenTokenTypeNotSetThenThrowIllegalArgumentException() {
-		OAuth2AccessTokenResponse.withToken(TOKEN)
-			.expiresIn(EXPIRES_IN)
-			.additionalParameters(Collections.emptyMap())
+	@Test
+	public void buildWhenAllAttributesProvidedThenAllAttributesAreSet() {
+		Instant expiresAt = Instant.now().plusSeconds(5);
+		Set<String> scopes = new LinkedHashSet<>(Arrays.asList("scope1", "scope2"));
+		Map<String, Object> additionalParameters = new HashMap<>();
+		additionalParameters.put("param1", "value1");
+		additionalParameters.put("param2", "value2");
+
+		OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse
+			.withToken(TOKEN_VALUE)
+			.tokenType(OAuth2AccessToken.TokenType.BEARER)
+			.expiresIn(expiresAt.toEpochMilli())
+			.scopes(scopes)
+			.additionalParameters(additionalParameters)
 			.build();
+
+		assertThat(tokenResponse.getAccessToken()).isNotNull();
+		assertThat(tokenResponse.getAccessToken().getTokenValue()).isEqualTo(TOKEN_VALUE);
+		assertThat(tokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
+		assertThat(tokenResponse.getAccessToken().getIssuedAt()).isNotNull();
+		assertThat(tokenResponse.getAccessToken().getExpiresAt()).isAfterOrEqualTo(expiresAt);
+		assertThat(tokenResponse.getAccessToken().getScopes()).isEqualTo(scopes);
+		assertThat(tokenResponse.getAdditionalParameters()).isEqualTo(additionalParameters);
 	}
 }

+ 54 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationExchangeTests.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-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.core.endpoint;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link OAuth2AuthorizationExchange}.
+ *
+ * @author Joe Grandja
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({OAuth2AuthorizationExchange.class, OAuth2AuthorizationRequest.class, OAuth2AuthorizationResponse.class})
+public class OAuth2AuthorizationExchangeTests {
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthorizationRequestIsNullThenThrowIllegalArgumentException() {
+		new OAuth2AuthorizationExchange(null, mock(OAuth2AuthorizationResponse.class));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthorizationResponseIsNullThenThrowIllegalArgumentException() {
+		new OAuth2AuthorizationExchange(mock(OAuth2AuthorizationRequest.class), null);
+	}
+
+	@Test
+	public void constructorWhenRequiredArgsProvidedThenCreated() {
+		OAuth2AuthorizationRequest authorizationRequest = mock(OAuth2AuthorizationRequest.class);
+		OAuth2AuthorizationResponse authorizationResponse = mock(OAuth2AuthorizationResponse.class);
+		OAuth2AuthorizationExchange authorizationExchange =
+			new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse);
+		assertThat(authorizationExchange.getAuthorizationRequest()).isEqualTo(authorizationRequest);
+		assertThat(authorizationExchange.getAuthorizationResponse()).isEqualTo(authorizationResponse);
+	}
+}

+ 78 - 58
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java

@@ -16,24 +16,34 @@
 package org.springframework.security.oauth2.core.endpoint;
 
 import org.junit.Test;
-
-import java.util.Collections;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Set;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 
 /**
- * Tests {@link OAuth2AuthorizationRequest}
+ * Tests for {@link OAuth2AuthorizationRequest}.
  *
  * @author Luander Ribeiro
+ * @author Joe Grandja
  */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(OAuth2AuthorizationRequest.class)
 public class OAuth2AuthorizationRequestTests {
-	private static final String AUTHORIZE_URI = "http://authorize.uri/";
-	private static final String CLIENT_ID = "client id";
-	private static final String REDIRECT_URI = "http://redirect.uri/";
-	private static final Set<String> SCOPE = Collections.singleton("scope");
-	private static final String STATE = "xyz";
+	private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/authorize";
+	private static final String CLIENT_ID = "client-id";
+	private static final String REDIRECT_URI = "http://example.com";
+	private static final Set<String> SCOPES = new LinkedHashSet<>(Arrays.asList("scope1", "scope2"));
+	private static final String STATE = "state";
 
 	@Test(expected = IllegalArgumentException.class)
 	public void buildWhenAuthorizationUriIsNullThenThrowIllegalArgumentException() {
@@ -41,17 +51,7 @@ public class OAuth2AuthorizationRequestTests {
 			.authorizationUri(null)
 			.clientId(CLIENT_ID)
 			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
-			.state(STATE)
-			.build();
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void buildWhenAuthorizeUriNotSetThenThrowIllegalArgumentException() {
-		OAuth2AuthorizationRequest.authorizationCode()
-			.clientId(CLIENT_ID)
-			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
+			.scopes(SCOPES)
 			.state(STATE)
 			.build();
 	}
@@ -59,76 +59,94 @@ public class OAuth2AuthorizationRequestTests {
 	@Test(expected = IllegalArgumentException.class)
 	public void buildWhenClientIdIsNullThenThrowIllegalArgumentException() {
 		OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(null)
 			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
+			.scopes(SCOPES)
 			.state(STATE)
 			.build();
 	}
 
 	@Test(expected = IllegalArgumentException.class)
-	public void buildWhenClientIdNotSetThenThrowIllegalArgumentException() {
-		OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
-			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
+	public void buildWhenRedirectUriIsNullForImplicitThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationRequest.implicit()
+			.authorizationUri(AUTHORIZATION_URI)
+			.clientId(CLIENT_ID)
+			.redirectUri(null)
+			.scopes(SCOPES)
 			.state(STATE)
 			.build();
 	}
 
 	@Test
-	public void buildWhenGetResponseTypeIsCalledThenReturnCode() {
-		OAuth2AuthorizationRequest authorizationRequest;
-		authorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+	public void buildWhenRedirectUriIsNullForAuthorizationCodeThenDoesNotThrowAnyException() {
+		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
-			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
+			.redirectUri(null)
+			.scopes(SCOPES)
 			.state(STATE)
-			.build();
-
-		assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE);
+			.build()).doesNotThrowAnyException();
 	}
 
 	@Test
-	public void buildWhenRedirectUriIsNullThenDoesNotThrowAnyException() {
-		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+	public void buildWhenImplicitThenGrantTypeResponseTypeIsSet() {
+		OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.implicit()
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
-			.redirectUri(null)
-			.scopes(SCOPE)
+			.redirectUri(REDIRECT_URI)
+			.scopes(SCOPES)
 			.state(STATE)
-			.build()).doesNotThrowAnyException();
+			.build();
+		assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.IMPLICIT);
+		assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.TOKEN);
 	}
 
 	@Test
-	public void buildWhenRedirectUriNotSetThenDoesNotThrowAnyException() {
-		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+	public void buildWhenAuthorizationCodeThenGrantTypeResponseTypeIsSet() {
+		OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
-			.scopes(SCOPE)
+			.redirectUri(null)
+			.scopes(SCOPES)
 			.state(STATE)
-			.build()).doesNotThrowAnyException();
+			.build();
+		assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
+		assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE);
 	}
 
 	@Test
-	public void buildWhenScopesIsNullThenDoesNotThrowAnyException() {
-		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+	public void buildWhenAllAttributesProvidedThenAllAttributesAreSet() {
+		Map<String, Object> additionalParameters = new HashMap<>();
+		additionalParameters.put("param1", "value1");
+		additionalParameters.put("param2", "value2");
+
+		OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
 			.redirectUri(REDIRECT_URI)
-			.scopes(null)
+			.scopes(SCOPES)
 			.state(STATE)
-			.build()).doesNotThrowAnyException();
+			.additionalParameters(additionalParameters)
+			.build();
+
+		assertThat(authorizationRequest.getAuthorizationUri()).isEqualTo(AUTHORIZATION_URI);
+		assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
+		assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE);
+		assertThat(authorizationRequest.getClientId()).isEqualTo(CLIENT_ID);
+		assertThat(authorizationRequest.getRedirectUri()).isEqualTo(REDIRECT_URI);
+		assertThat(authorizationRequest.getScopes()).isEqualTo(SCOPES);
+		assertThat(authorizationRequest.getState()).isEqualTo(STATE);
+		assertThat(authorizationRequest.getAdditionalParameters()).isEqualTo(additionalParameters);
 	}
 
 	@Test
-	public void buildWhenScopesNotSetThenDoesNotThrowAnyException() {
+	public void buildWhenScopesIsNullThenDoesNotThrowAnyException() {
 		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
 			.redirectUri(REDIRECT_URI)
+			.scopes(null)
 			.state(STATE)
 			.build()).doesNotThrowAnyException();
 	}
@@ -136,21 +154,23 @@ public class OAuth2AuthorizationRequestTests {
 	@Test
 	public void buildWhenStateIsNullThenDoesNotThrowAnyException() {
 		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
 			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
+			.scopes(SCOPES)
 			.state(null)
 			.build()).doesNotThrowAnyException();
 	}
 
 	@Test
-	public void buildWhenStateNotSetThenDoesNotThrowAnyException() {
+	public void buildWhenAdditionalParametersIsNullThenDoesNotThrowAnyException() {
 		assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode()
-			.authorizationUri(AUTHORIZE_URI)
+			.authorizationUri(AUTHORIZATION_URI)
 			.clientId(CLIENT_ID)
 			.redirectUri(REDIRECT_URI)
-			.scopes(SCOPE)
+			.scopes(SCOPES)
+			.state(STATE)
+			.additionalParameters(null)
 			.build()).doesNotThrowAnyException();
 	}
 }

+ 127 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTests.java

@@ -0,0 +1,127 @@
+/*
+ * Copyright 2002-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.core.endpoint;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+
+/**
+ * Tests for {@link OAuth2AuthorizationResponse}.
+ *
+ * @author Joe Grandja
+ */
+public class OAuth2AuthorizationResponseTests {
+	private static final String AUTH_CODE = "auth-code";
+	private static final String REDIRECT_URI = "http://example.com";
+	private static final String STATE = "state";
+	private static final String ERROR_CODE = "error-code";
+	private static final String ERROR_DESCRIPTION = "error-description";
+	private static final String ERROR_URI = "error-uri";
+
+	@Test(expected = IllegalArgumentException.class)
+	public void buildSuccessResponseWhenAuthCodeIsNullThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationResponse.success(null)
+			.redirectUri(REDIRECT_URI)
+			.state(STATE)
+			.build();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void buildSuccessResponseWhenRedirectUriIsNullThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationResponse.success(AUTH_CODE)
+			.redirectUri(null)
+			.state(STATE)
+			.build();
+	}
+
+	@Test
+	public void buildSuccessResponseWhenStateIsNullThenDoesNotThrowAnyException() {
+		assertThatCode(() -> OAuth2AuthorizationResponse.success(AUTH_CODE)
+			.redirectUri(REDIRECT_URI)
+			.state(null)
+			.build()).doesNotThrowAnyException();
+	}
+
+	@Test
+	public void buildSuccessResponseWhenAllAttributesProvidedThenAllAttributesAreSet() {
+		OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success(AUTH_CODE)
+			.redirectUri(REDIRECT_URI)
+			.state(STATE)
+			.build();
+		assertThat(authorizationResponse.getCode()).isEqualTo(AUTH_CODE);
+		assertThat(authorizationResponse.getRedirectUri()).isEqualTo(REDIRECT_URI);
+		assertThat(authorizationResponse.getState()).isEqualTo(STATE);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void buildSuccessResponseWhenErrorCodeIsSetThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationResponse.success(AUTH_CODE)
+			.redirectUri(REDIRECT_URI)
+			.state(STATE)
+			.errorCode(ERROR_CODE)
+			.build();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void buildErrorResponseWhenErrorCodeIsNullThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationResponse.error(null)
+			.redirectUri(REDIRECT_URI)
+			.state(STATE)
+			.build();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void buildErrorResponseWhenRedirectUriIsNullThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationResponse.error(ERROR_CODE)
+			.redirectUri(null)
+			.state(STATE)
+			.build();
+	}
+
+	@Test
+	public void buildErrorResponseWhenStateIsNullThenDoesNotThrowAnyException() {
+		assertThatCode(() -> OAuth2AuthorizationResponse.error(ERROR_CODE)
+			.redirectUri(REDIRECT_URI)
+			.state(null)
+			.build()).doesNotThrowAnyException();
+	}
+
+	@Test
+	public void buildErrorResponseWhenAllAttributesProvidedThenAllAttributesAreSet() {
+		OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.error(ERROR_CODE)
+			.errorDescription(ERROR_DESCRIPTION)
+			.errorUri(ERROR_URI)
+			.redirectUri(REDIRECT_URI)
+			.state(STATE)
+			.build();
+		assertThat(authorizationResponse.getError().getErrorCode()).isEqualTo(ERROR_CODE);
+		assertThat(authorizationResponse.getError().getDescription()).isEqualTo(ERROR_DESCRIPTION);
+		assertThat(authorizationResponse.getError().getUri()).isEqualTo(ERROR_URI);
+		assertThat(authorizationResponse.getRedirectUri()).isEqualTo(REDIRECT_URI);
+		assertThat(authorizationResponse.getState()).isEqualTo(STATE);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void buildErrorResponseWhenAuthCodeIsSetThenThrowIllegalArgumentException() {
+		OAuth2AuthorizationResponse.error(ERROR_CODE)
+			.redirectUri(REDIRECT_URI)
+			.state(STATE)
+			.code(AUTH_CODE)
+			.build();
+	}
+}

+ 38 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTypeTests.java

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-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.core.endpoint;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link OAuth2AuthorizationResponseType}.
+ *
+ * @author Joe Grandja
+ */
+public class OAuth2AuthorizationResponseTypeTests {
+
+	@Test
+	public void getValueWhenResponseTypeCodeThenReturnCode() {
+		assertThat(OAuth2AuthorizationResponseType.CODE.getValue()).isEqualTo("code");
+	}
+
+	@Test
+	public void getValueWhenResponseTypeTokenThenReturnToken() {
+		assertThat(OAuth2AuthorizationResponseType.TOKEN.getValue()).isEqualTo("token");
+	}
+}

+ 85 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaimTests.java

@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002-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.core.oidc;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link DefaultAddressStandardClaim}.
+ *
+ * @author Joe Grandja
+ */
+public class DefaultAddressStandardClaimTests {
+	static final String FORMATTED_FIELD_NAME = "formatted";
+	static final String STREET_ADDRESS_FIELD_NAME = "street_address";
+	static final String LOCALITY_FIELD_NAME = "locality";
+	static final String REGION_FIELD_NAME = "region";
+	static final String POSTAL_CODE_FIELD_NAME = "postal_code";
+	static final String COUNTRY_FIELD_NAME = "country";
+	static final String FORMATTED = "formatted";
+	static final String STREET_ADDRESS = "street_address";
+	static final String LOCALITY = "locality";
+	static final String REGION = "region";
+	static final String POSTAL_CODE = "postal_code";
+	static final String COUNTRY = "country";
+
+	@Test
+	public void buildWhenAllAttributesProvidedThenAllAttributesAreSet() {
+		AddressStandardClaim addressStandardClaim =
+			new DefaultAddressStandardClaim.Builder()
+			.formatted(FORMATTED)
+			.streetAddress(STREET_ADDRESS)
+			.locality(LOCALITY)
+			.region(REGION)
+			.postalCode(POSTAL_CODE)
+			.country(COUNTRY)
+			.build();
+
+		assertThat(addressStandardClaim.getFormatted()).isEqualTo(FORMATTED);
+		assertThat(addressStandardClaim.getStreetAddress()).isEqualTo(STREET_ADDRESS);
+		assertThat(addressStandardClaim.getLocality()).isEqualTo(LOCALITY);
+		assertThat(addressStandardClaim.getRegion()).isEqualTo(REGION);
+		assertThat(addressStandardClaim.getPostalCode()).isEqualTo(POSTAL_CODE);
+		assertThat(addressStandardClaim.getCountry()).isEqualTo(COUNTRY);
+	}
+
+	@Test
+	public void buildWhenAllAttributesProvidedToConstructorThenAllAttributesAreSet() {
+		Map<String, Object> addressFields = new HashMap<>();
+		addressFields.put(FORMATTED_FIELD_NAME, FORMATTED);
+		addressFields.put(STREET_ADDRESS_FIELD_NAME, STREET_ADDRESS);
+		addressFields.put(LOCALITY_FIELD_NAME, LOCALITY);
+		addressFields.put(REGION_FIELD_NAME, REGION);
+		addressFields.put(POSTAL_CODE_FIELD_NAME, POSTAL_CODE);
+		addressFields.put(COUNTRY_FIELD_NAME, COUNTRY);
+
+		AddressStandardClaim addressStandardClaim =
+			new DefaultAddressStandardClaim.Builder(addressFields)
+			.build();
+
+		assertThat(addressStandardClaim.getFormatted()).isEqualTo(FORMATTED);
+		assertThat(addressStandardClaim.getStreetAddress()).isEqualTo(STREET_ADDRESS);
+		assertThat(addressStandardClaim.getLocality()).isEqualTo(LOCALITY);
+		assertThat(addressStandardClaim.getRegion()).isEqualTo(REGION);
+		assertThat(addressStandardClaim.getPostalCode()).isEqualTo(POSTAL_CODE);
+		assertThat(addressStandardClaim.getCountry()).isEqualTo(COUNTRY);
+	}
+}

+ 121 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java

@@ -0,0 +1,121 @@
+/*
+ * Copyright 2002-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.core.oidc;
+
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link OidcIdToken}.
+ *
+ * @author Joe Grandja
+ */
+public class OidcIdTokenTests {
+	private static final String ISS_CLAIM = "iss";
+	private static final String SUB_CLAIM = "sub";
+	private static final String AUD_CLAIM = "aud";
+	private static final String IAT_CLAIM = "iat";
+	private static final String EXP_CLAIM = "exp";
+	private static final String AUTH_TIME_CLAIM = "auth_time";
+	private static final String NONCE_CLAIM = "nonce";
+	private static final String ACR_CLAIM = "acr";
+	private static final String AMR_CLAIM = "amr";
+	private static final String AZP_CLAIM = "azp";
+	private static final String AT_HASH_CLAIM = "at_hash";
+	private static final String C_HASH_CLAIM = "c_hash";
+
+	private static final String ISS_VALUE = "https://provider.com";
+	private static final String SUB_VALUE = "subject1";
+	private static final List<String> AUD_VALUE = Arrays.asList("aud1", "aud2");
+	private static final long IAT_VALUE = Instant.now().toEpochMilli();
+	private static final long EXP_VALUE = Instant.now().plusSeconds(60).toEpochMilli();
+	private static final long AUTH_TIME_VALUE = Instant.now().minusSeconds(5).toEpochMilli();
+	private static final String NONCE_VALUE = "nonce";
+	private static final String ACR_VALUE = "acr";
+	private static final List<String> AMR_VALUE = Arrays.asList("amr1", "amr2");
+	private static final String AZP_VALUE = "azp";
+	private static final String AT_HASH_VALUE = "at_hash";
+	private static final String C_HASH_VALUE = "c_hash";
+
+	private static final Map<String, Object> CLAIMS;
+	private static final String ID_TOKEN_VALUE = "id-token-value";
+
+	static {
+		CLAIMS = new HashMap<>();
+		CLAIMS.put(ISS_CLAIM, ISS_VALUE);
+		CLAIMS.put(SUB_CLAIM, SUB_VALUE);
+		CLAIMS.put(AUD_CLAIM, AUD_VALUE);
+		CLAIMS.put(IAT_CLAIM, IAT_VALUE);
+		CLAIMS.put(EXP_CLAIM, EXP_VALUE);
+		CLAIMS.put(AUTH_TIME_CLAIM, AUTH_TIME_VALUE);
+		CLAIMS.put(NONCE_CLAIM, NONCE_VALUE);
+		CLAIMS.put(ACR_CLAIM, ACR_VALUE);
+		CLAIMS.put(AMR_CLAIM, AMR_VALUE);
+		CLAIMS.put(AZP_CLAIM, AZP_VALUE);
+		CLAIMS.put(AT_HASH_CLAIM, AT_HASH_VALUE);
+		CLAIMS.put(C_HASH_CLAIM, C_HASH_VALUE);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenTokenValueIsNullThenThrowIllegalArgumentException() {
+		new OidcIdToken(null, Instant.ofEpochMilli(IAT_VALUE), Instant.ofEpochMilli(EXP_VALUE), CLAIMS);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenIssuedAtIsNullThenThrowIllegalArgumentException() {
+		new OidcIdToken(ID_TOKEN_VALUE, null, Instant.ofEpochMilli(EXP_VALUE), CLAIMS);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenExpiresAtIsNullThenThrowIllegalArgumentException() {
+		new OidcIdToken(ID_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), null, CLAIMS);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenClaimsIsEmptyThenThrowIllegalArgumentException() {
+		new OidcIdToken(ID_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE),
+			Instant.ofEpochMilli(EXP_VALUE), Collections.emptyMap());
+	}
+
+	@Test
+	public void constructorWhenParametersProvidedAndValidThenCreated() {
+		OidcIdToken idToken = new OidcIdToken(ID_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE),
+			Instant.ofEpochMilli(EXP_VALUE), CLAIMS);
+
+		assertThat(idToken.getClaims()).isEqualTo(CLAIMS);
+		assertThat(idToken.getTokenValue()).isEqualTo(ID_TOKEN_VALUE);
+		assertThat(idToken.getIssuer().toString()).isEqualTo(ISS_VALUE);
+		assertThat(idToken.getSubject()).isEqualTo(SUB_VALUE);
+		assertThat(idToken.getAudience()).isEqualTo(AUD_VALUE);
+		assertThat(idToken.getIssuedAt().toEpochMilli()).isEqualTo(IAT_VALUE);
+		assertThat(idToken.getExpiresAt().toEpochMilli()).isEqualTo(EXP_VALUE);
+		assertThat(idToken.getAuthenticatedAt().toEpochMilli()).isEqualTo(AUTH_TIME_VALUE);
+		assertThat(idToken.getNonce()).isEqualTo(NONCE_VALUE);
+		assertThat(idToken.getAuthenticationContextClass()).isEqualTo(ACR_VALUE);
+		assertThat(idToken.getAuthenticationMethods()).isEqualTo(AMR_VALUE);
+		assertThat(idToken.getAuthorizedParty()).isEqualTo(AZP_VALUE);
+		assertThat(idToken.getAccessTokenHash()).isEqualTo(AT_HASH_VALUE);
+		assertThat(idToken.getAuthorizationCodeHash()).isEqualTo(C_HASH_VALUE);
+	}
+}

+ 142 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java

@@ -0,0 +1,142 @@
+/*
+ * Copyright 2002-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.core.oidc;
+
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.security.oauth2.core.oidc.DefaultAddressStandardClaimTests.*;
+
+/**
+ * Tests for {@link OidcUserInfo}.
+ *
+ * @author Joe Grandja
+ */
+public class OidcUserInfoTests {
+	private static final String SUB_CLAIM = "sub";
+	private static final String NAME_CLAIM = "name";
+	private static final String GIVEN_NAME_CLAIM = "given_name";
+	private static final String FAMILY_NAME_CLAIM = "family_name";
+	private static final String MIDDLE_NAME_CLAIM = "middle_name";
+	private static final String NICKNAME_CLAIM = "nickname";
+	private static final String PREFERRED_USERNAME_CLAIM = "preferred_username";
+	private static final String PROFILE_CLAIM = "profile";
+	private static final String PICTURE_CLAIM = "picture";
+	private static final String WEBSITE_CLAIM = "website";
+	private static final String EMAIL_CLAIM = "email";
+	private static final String EMAIL_VERIFIED_CLAIM = "email_verified";
+	private static final String GENDER_CLAIM = "gender";
+	private static final String BIRTHDATE_CLAIM = "birthdate";
+	private static final String ZONEINFO_CLAIM = "zoneinfo";
+	private static final String LOCALE_CLAIM = "locale";
+	private static final String PHONE_NUMBER_CLAIM = "phone_number";
+	private static final String PHONE_NUMBER_VERIFIED_CLAIM = "phone_number_verified";
+	private static final String ADDRESS_CLAIM = "address";
+	private static final String UPDATED_AT_CLAIM = "updated_at";
+
+	private static final String SUB_VALUE = "subject1";
+	private static final String NAME_VALUE = "full_name";
+	private static final String GIVEN_NAME_VALUE = "given_name";
+	private static final String FAMILY_NAME_VALUE = "family_name";
+	private static final String MIDDLE_NAME_VALUE = "middle_name";
+	private static final String NICKNAME_VALUE = "nickname";
+	private static final String PREFERRED_USERNAME_VALUE = "preferred_username";
+	private static final String PROFILE_VALUE = "profile";
+	private static final String PICTURE_VALUE = "picture";
+	private static final String WEBSITE_VALUE = "website";
+	private static final String EMAIL_VALUE = "email";
+	private static final Boolean EMAIL_VERIFIED_VALUE = true;
+	private static final String GENDER_VALUE = "gender";
+	private static final String BIRTHDATE_VALUE = "birthdate";
+	private static final String ZONEINFO_VALUE = "zoneinfo";
+	private static final String LOCALE_VALUE = "locale";
+	private static final String PHONE_NUMBER_VALUE = "phone_number";
+	private static final Boolean PHONE_NUMBER_VERIFIED_VALUE = true;
+	private static final Map<String, Object> ADDRESS_VALUE;
+	private static final long UPDATED_AT_VALUE = Instant.now().minusSeconds(60).toEpochMilli();
+
+	private static final Map<String, Object> CLAIMS;
+
+	static {
+		CLAIMS = new HashMap<>();
+		CLAIMS.put(SUB_CLAIM, SUB_VALUE);
+		CLAIMS.put(NAME_CLAIM, NAME_VALUE);
+		CLAIMS.put(GIVEN_NAME_CLAIM, GIVEN_NAME_VALUE);
+		CLAIMS.put(FAMILY_NAME_CLAIM, FAMILY_NAME_VALUE);
+		CLAIMS.put(MIDDLE_NAME_CLAIM, MIDDLE_NAME_VALUE);
+		CLAIMS.put(NICKNAME_CLAIM, NICKNAME_VALUE);
+		CLAIMS.put(PREFERRED_USERNAME_CLAIM, PREFERRED_USERNAME_VALUE);
+		CLAIMS.put(PROFILE_CLAIM, PROFILE_VALUE);
+		CLAIMS.put(PICTURE_CLAIM, PICTURE_VALUE);
+		CLAIMS.put(WEBSITE_CLAIM, WEBSITE_VALUE);
+		CLAIMS.put(EMAIL_CLAIM, EMAIL_VALUE);
+		CLAIMS.put(EMAIL_VERIFIED_CLAIM, EMAIL_VERIFIED_VALUE);
+		CLAIMS.put(GENDER_CLAIM, GENDER_VALUE);
+		CLAIMS.put(BIRTHDATE_CLAIM, BIRTHDATE_VALUE);
+		CLAIMS.put(ZONEINFO_CLAIM, ZONEINFO_VALUE);
+		CLAIMS.put(LOCALE_CLAIM, LOCALE_VALUE);
+		CLAIMS.put(PHONE_NUMBER_CLAIM, PHONE_NUMBER_VALUE);
+		CLAIMS.put(PHONE_NUMBER_VERIFIED_CLAIM, PHONE_NUMBER_VERIFIED_VALUE);
+
+		ADDRESS_VALUE = new HashMap<>();
+		ADDRESS_VALUE.put(FORMATTED_FIELD_NAME, FORMATTED);
+		ADDRESS_VALUE.put(STREET_ADDRESS_FIELD_NAME, STREET_ADDRESS);
+		ADDRESS_VALUE.put(LOCALITY_FIELD_NAME, LOCALITY);
+		ADDRESS_VALUE.put(REGION_FIELD_NAME, REGION);
+		ADDRESS_VALUE.put(POSTAL_CODE_FIELD_NAME, POSTAL_CODE);
+		ADDRESS_VALUE.put(COUNTRY_FIELD_NAME, COUNTRY);
+		CLAIMS.put(ADDRESS_CLAIM, ADDRESS_VALUE);
+
+		CLAIMS.put(UPDATED_AT_CLAIM, UPDATED_AT_VALUE);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenClaimsIsEmptyThenThrowIllegalArgumentException() {
+		new OidcUserInfo(Collections.emptyMap());
+	}
+
+	@Test
+	public void constructorWhenParametersProvidedAndValidThenCreated() {
+		OidcUserInfo userInfo = new OidcUserInfo(CLAIMS);
+
+		assertThat(userInfo.getClaims()).isEqualTo(CLAIMS);
+		assertThat(userInfo.getSubject()).isEqualTo(SUB_VALUE);
+		assertThat(userInfo.getFullName()).isEqualTo(NAME_VALUE);
+		assertThat(userInfo.getGivenName()).isEqualTo(GIVEN_NAME_VALUE);
+		assertThat(userInfo.getFamilyName()).isEqualTo(FAMILY_NAME_VALUE);
+		assertThat(userInfo.getMiddleName()).isEqualTo(MIDDLE_NAME_VALUE);
+		assertThat(userInfo.getNickName()).isEqualTo(NICKNAME_VALUE);
+		assertThat(userInfo.getPreferredUsername()).isEqualTo(PREFERRED_USERNAME_VALUE);
+		assertThat(userInfo.getProfile()).isEqualTo(PROFILE_VALUE);
+		assertThat(userInfo.getPicture()).isEqualTo(PICTURE_VALUE);
+		assertThat(userInfo.getWebsite()).isEqualTo(WEBSITE_VALUE);
+		assertThat(userInfo.getEmail()).isEqualTo(EMAIL_VALUE);
+		assertThat(userInfo.getEmailVerified()).isEqualTo(EMAIL_VERIFIED_VALUE);
+		assertThat(userInfo.getGender()).isEqualTo(GENDER_VALUE);
+		assertThat(userInfo.getBirthdate()).isEqualTo(BIRTHDATE_VALUE);
+		assertThat(userInfo.getZoneInfo()).isEqualTo(ZONEINFO_VALUE);
+		assertThat(userInfo.getLocale()).isEqualTo(LOCALE_VALUE);
+		assertThat(userInfo.getPhoneNumber()).isEqualTo(PHONE_NUMBER_VALUE);
+		assertThat(userInfo.getPhoneNumberVerified()).isEqualTo(PHONE_NUMBER_VERIFIED_VALUE);
+		assertThat(userInfo.getAddress()).isEqualTo(new DefaultAddressStandardClaim.Builder(ADDRESS_VALUE).build());
+		assertThat(userInfo.getUpdatedAt().toEpochMilli()).isEqualTo(UPDATED_AT_VALUE);
+	}
+}

+ 68 - 62
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java

@@ -16,107 +16,113 @@
 
 package org.springframework.security.oauth2.core.oidc.user;
 
-import java.time.Instant;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.oauth2.core.oidc.OidcIdToken;
 import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
 import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
 import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
 
+import java.time.Instant;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * Tests for {@link DefaultOidcUser}.
  *
  * @author Vedran Pavic
+ * @author Joe Grandja
  */
 public class DefaultOidcUserTests {
-
-	private static final SimpleGrantedAuthority TEST_AUTHORITY = new SimpleGrantedAuthority("ROLE_USER");
-
-	private static final Set<GrantedAuthority> TEST_AUTHORITIES = Collections.singleton(TEST_AUTHORITY);
-
-	private static final String TEST_SUBJECT = "test";
-
-	private static final String TEST_EMAIL = "test@example.com";
-
-	private static final Map<String, Object> TEST_ID_TOKEN_CLAIMS = new HashMap<>();
+	private static final SimpleGrantedAuthority AUTHORITY = new SimpleGrantedAuthority("ROLE_USER");
+	private static final Set<GrantedAuthority> AUTHORITIES = Collections.singleton(AUTHORITY);
+	private static final String SUBJECT = "test-subject";
+	private static final String EMAIL = "test-subject@example.com";
+	private static final String NAME = "test-name";
+	private static final Map<String, Object> ID_TOKEN_CLAIMS = new HashMap<>();
+	private static final Map<String, Object> USER_INFO_CLAIMS = new HashMap<>();
 
 	static {
-		TEST_ID_TOKEN_CLAIMS.put(IdTokenClaimNames.ISS, "https://example.com");
-		TEST_ID_TOKEN_CLAIMS.put(IdTokenClaimNames.SUB, TEST_SUBJECT);
+		ID_TOKEN_CLAIMS.put(IdTokenClaimNames.ISS, "https://example.com");
+		ID_TOKEN_CLAIMS.put(IdTokenClaimNames.SUB, SUBJECT);
+		USER_INFO_CLAIMS.put(StandardClaimNames.NAME, NAME);
+		USER_INFO_CLAIMS.put(StandardClaimNames.EMAIL, EMAIL);
 	}
 
-	private static final OidcIdToken TEST_ID_TOKEN = new OidcIdToken("value", Instant.EPOCH, Instant.MAX, TEST_ID_TOKEN_CLAIMS);
-
-	private static final OidcUserInfo TEST_USER_INFO = new OidcUserInfo(Collections.singletonMap(StandardClaimNames.EMAIL, TEST_EMAIL));
+	private static final OidcIdToken ID_TOKEN = new OidcIdToken("id-token-value", Instant.EPOCH, Instant.MAX, ID_TOKEN_CLAIMS);
+	private static final OidcUserInfo USER_INFO = new OidcUserInfo(USER_INFO_CLAIMS);
 
-	@Rule
-	public ExpectedException thrown = ExpectedException.none();
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthoritiesIsNullThenThrowIllegalArgumentException() {
+		new DefaultOidcUser(null, ID_TOKEN);
+	}
 
-	@Test
-	public void constructorWhenAuthoritiesAndIdTokenThenIsCreated() {
-		DefaultOidcUser user = new DefaultOidcUser(TEST_AUTHORITIES, TEST_ID_TOKEN);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenIdTokenIsNullThenThrowIllegalArgumentException() {
+		new DefaultOidcUser(AUTHORITIES, null);
+	}
 
-		assertThat(user.getName()).isEqualTo(TEST_SUBJECT);
-		assertThat(user.getAuthorities()).hasSize(1);
-		assertThat(user.getAuthorities().iterator().next()).isEqualTo(TEST_AUTHORITY);
-		assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenNameAttributeKeyInvalidThenThrowIllegalArgumentException() {
+		new DefaultOidcUser(AUTHORITIES, ID_TOKEN, "invalid");
 	}
 
 	@Test
-	public void constructorWhenAuthoritiesAndIdTokenAndNameAttributeKeyThenIsCreated() {
-		DefaultOidcUser user = new DefaultOidcUser(TEST_AUTHORITIES, TEST_ID_TOKEN, IdTokenClaimNames.SUB);
+	public void constructorWhenAuthoritiesIdTokenProvidedThenCreated() {
+		DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN);
 
-		assertThat(user.getName()).isEqualTo(TEST_SUBJECT);
+		assertThat(user.getClaims()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB);
+		assertThat(user.getIdToken()).isEqualTo(ID_TOKEN);
+		assertThat(user.getName()).isEqualTo(SUBJECT);
 		assertThat(user.getAuthorities()).hasSize(1);
-		assertThat(user.getAuthorities().iterator().next()).isEqualTo(TEST_AUTHORITY);
+		assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY);
 		assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB);
 	}
 
 	@Test
-	public void constructorWhenAuthoritiesAndIdTokenAndUserInfoThenIsCreated() {
-		DefaultOidcUser user = new DefaultOidcUser(TEST_AUTHORITIES, TEST_ID_TOKEN, TEST_USER_INFO);
+	public void constructorWhenAuthoritiesIdTokenNameAttributeKeyProvidedThenCreated() {
+		DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN, IdTokenClaimNames.SUB);
 
-		assertThat(user.getName()).isEqualTo(TEST_SUBJECT);
+		assertThat(user.getClaims()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB);
+		assertThat(user.getIdToken()).isEqualTo(ID_TOKEN);
+		assertThat(user.getName()).isEqualTo(SUBJECT);
 		assertThat(user.getAuthorities()).hasSize(1);
-		assertThat(user.getAuthorities().iterator().next()).isEqualTo(TEST_AUTHORITY);
-		assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.EMAIL);
+		assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY);
+		assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB);
 	}
 
 	@Test
-	public void constructorWhenAuthoritiesAndIdTokenAndUserInfoAndNameAttributeKeyThenIsCreated() {
-		DefaultOidcUser user = new DefaultOidcUser(TEST_AUTHORITIES, TEST_ID_TOKEN, TEST_USER_INFO, StandardClaimNames.EMAIL);
-
-		assertThat(user.getName()).isEqualTo(TEST_EMAIL);
+	public void constructorWhenAuthoritiesIdTokenUserInfoProvidedThenCreated() {
+		DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN, USER_INFO);
+
+		assertThat(user.getClaims()).containsOnlyKeys(
+			IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL);
+		assertThat(user.getIdToken()).isEqualTo(ID_TOKEN);
+		assertThat(user.getUserInfo()).isEqualTo(USER_INFO);
+		assertThat(user.getName()).isEqualTo(SUBJECT);
 		assertThat(user.getAuthorities()).hasSize(1);
-		assertThat(user.getAuthorities().iterator().next()).isEqualTo(TEST_AUTHORITY);
-		assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.EMAIL);
-	}
-
-	@Test
-	public void constructorWhenIdTokenIsNullThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("idToken cannot be null");
-
-		new DefaultOidcUser(TEST_AUTHORITIES, null);
+		assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY);
+		assertThat(user.getAttributes()).containsOnlyKeys(
+			IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL);
 	}
 
 	@Test
-	public void constructorWhenNameAttributeKeyClaimIsNotPresentThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("Missing attribute '" + StandardClaimNames.NAME + "' in attributes");
-
-		new DefaultOidcUser(TEST_AUTHORITIES, TEST_ID_TOKEN, TEST_USER_INFO, StandardClaimNames.NAME);
+	public void constructorWhenAllParametersProvidedAndValidThenCreated() {
+		DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN, USER_INFO, StandardClaimNames.EMAIL);
+
+		assertThat(user.getClaims()).containsOnlyKeys(
+			IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL);
+		assertThat(user.getIdToken()).isEqualTo(ID_TOKEN);
+		assertThat(user.getUserInfo()).isEqualTo(USER_INFO);
+		assertThat(user.getName()).isEqualTo(EMAIL);
+		assertThat(user.getAuthorities()).hasSize(1);
+		assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY);
+		assertThat(user.getAttributes()).containsOnlyKeys(
+			IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL);
 	}
-
 }

+ 79 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthorityTests.java

@@ -0,0 +1,79 @@
+/*
+ * Copyright 2002-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.core.oidc.user;
+
+import org.junit.Test;
+import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
+import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
+import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+
+/**
+ * Tests for {@link OidcUserAuthority}.
+ *
+ * @author Joe Grandja
+ */
+public class OidcUserAuthorityTests {
+	private static final String AUTHORITY = "ROLE_USER";
+	private static final String SUBJECT = "test-subject";
+	private static final String EMAIL = "test-subject@example.com";
+	private static final String NAME = "test-name";
+	private static final Map<String, Object> ID_TOKEN_CLAIMS = new HashMap<>();
+	private static final Map<String, Object> USER_INFO_CLAIMS = new HashMap<>();
+
+	static {
+		ID_TOKEN_CLAIMS.put(IdTokenClaimNames.ISS, "https://example.com");
+		ID_TOKEN_CLAIMS.put(IdTokenClaimNames.SUB, SUBJECT);
+		USER_INFO_CLAIMS.put(StandardClaimNames.NAME, NAME);
+		USER_INFO_CLAIMS.put(StandardClaimNames.EMAIL, EMAIL);
+	}
+
+	private static final OidcIdToken ID_TOKEN = new OidcIdToken("id-token-value", Instant.EPOCH, Instant.MAX, ID_TOKEN_CLAIMS);
+	private static final OidcUserInfo USER_INFO = new OidcUserInfo(USER_INFO_CLAIMS);
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenIdTokenIsNullThenThrowIllegalArgumentException() {
+		new OidcUserAuthority(null);
+	}
+
+	@Test
+	public void constructorWhenUserInfoIsNullThenDoesNotThrowAnyException() {
+		assertThatCode(() -> new OidcUserAuthority(ID_TOKEN, null)).doesNotThrowAnyException();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthorityIsNullThenThrowIllegalArgumentException() {
+		new OidcUserAuthority(null, ID_TOKEN, USER_INFO);
+	}
+
+	@Test
+	public void constructorWhenAllParametersProvidedAndValidThenCreated() {
+		OidcUserAuthority userAuthority = new OidcUserAuthority(AUTHORITY, ID_TOKEN, USER_INFO);
+
+		assertThat(userAuthority.getIdToken()).isEqualTo(ID_TOKEN);
+		assertThat(userAuthority.getUserInfo()).isEqualTo(USER_INFO);
+		assertThat(userAuthority.getAuthority()).isEqualTo(AUTHORITY);
+		assertThat(userAuthority.getAttributes()).containsOnlyKeys(
+			IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL);
+	}
+}

+ 36 - 64
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java

@@ -16,95 +16,67 @@
 
 package org.springframework.security.oauth2.core.user;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
 import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * Tests for {@link DefaultOAuth2User}.
  *
  * @author Vedran Pavic
+ * @author Joe Grandja
  */
 public class DefaultOAuth2UserTests {
-
-	private static final SimpleGrantedAuthority TEST_AUTHORITY = new SimpleGrantedAuthority("ROLE_USER");
-
-	private static final Set<GrantedAuthority> TEST_AUTHORITIES = Collections.singleton(TEST_AUTHORITY);
-
-	private static final String TEST_ATTRIBUTE_NAME_KEY = "username";
-
-	private static final String TEST_USERNAME = "test";
-
-	private static final Map<String, Object> TEST_ATTRIBUTES = Collections.singletonMap(
-			TEST_ATTRIBUTE_NAME_KEY, TEST_USERNAME);
-
-	@Rule
-	public ExpectedException thrown = ExpectedException.none();
-
-	@Test
-	public void constructorWhenParametersAreValidThenIsCreated() {
-		DefaultOAuth2User user = new DefaultOAuth2User(TEST_AUTHORITIES, TEST_ATTRIBUTES, TEST_ATTRIBUTE_NAME_KEY);
-
-		assertThat(user.getName()).isEqualTo(TEST_USERNAME);
-		assertThat(user.getAuthorities()).hasSize(1);
-		assertThat(user.getAuthorities().iterator().next()).isEqualTo(TEST_AUTHORITY);
-		assertThat(user.getAttributes()).containsOnlyKeys(TEST_ATTRIBUTE_NAME_KEY);
+	private static final SimpleGrantedAuthority AUTHORITY = new SimpleGrantedAuthority("ROLE_USER");
+	private static final Set<GrantedAuthority> AUTHORITIES = Collections.singleton(AUTHORITY);
+	private static final String ATTRIBUTE_NAME_KEY = "username";
+	private static final String USERNAME = "test";
+	private static final Map<String, Object> ATTRIBUTES = Collections.singletonMap(
+		ATTRIBUTE_NAME_KEY, USERNAME);
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthoritiesIsNullThenThrowIllegalArgumentException() {
+		new DefaultOAuth2User(null, ATTRIBUTES, ATTRIBUTE_NAME_KEY);
 	}
 
-	@Test
-	public void constructorWhenAuthoritiesAreNullThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("authorities cannot be empty");
-
-		new DefaultOAuth2User(null, TEST_ATTRIBUTES, TEST_ATTRIBUTE_NAME_KEY);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthoritiesIsEmptyThenThrowIllegalArgumentException() {
+		new DefaultOAuth2User(Collections.emptySet(), ATTRIBUTES, ATTRIBUTE_NAME_KEY);
 	}
 
-	@Test
-	public void constructorWhenAuthoritiesAreEmptyThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("authorities cannot be empty");
-
-		new DefaultOAuth2User(Collections.emptySet(), TEST_ATTRIBUTES, TEST_ATTRIBUTE_NAME_KEY);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAttributesIsNullThenThrowIllegalArgumentException() {
+		new DefaultOAuth2User(AUTHORITIES, null, ATTRIBUTE_NAME_KEY);
 	}
 
-	@Test
-	public void constructorWhenAttributesAreNullThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("attributes cannot be empty");
-
-		new DefaultOAuth2User(TEST_AUTHORITIES, null, TEST_ATTRIBUTE_NAME_KEY);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAttributesIsEmptyThenThrowIllegalArgumentException() {
+		new DefaultOAuth2User(AUTHORITIES, Collections.emptyMap(), ATTRIBUTE_NAME_KEY);
 	}
 
-	@Test
-	public void constructorWhenAttributesAreEmptyThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("attributes cannot be empty");
-
-		new DefaultOAuth2User(TEST_AUTHORITIES, Collections.emptyMap(), TEST_ATTRIBUTE_NAME_KEY);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenNameAttributeKeyIsNullThenThrowIllegalArgumentException() {
+		new DefaultOAuth2User(AUTHORITIES, ATTRIBUTES, null);
 	}
 
-	@Test
-	public void constructorWhenNameAttributeKeyIsNullThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("nameAttributeKey cannot be empty");
-
-		new DefaultOAuth2User(TEST_AUTHORITIES, TEST_ATTRIBUTES, null);
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenNameAttributeKeyIsInvalidThenThrowIllegalArgumentException() {
+		new DefaultOAuth2User(AUTHORITIES, ATTRIBUTES, "invalid");
 	}
 
 	@Test
-	public void constructorWhenNameAttributeKeyIsInvalidThenThrowsException() {
-		this.thrown.expect(IllegalArgumentException.class);
-		this.thrown.expectMessage("Missing attribute 'invalid' in attributes");
+	public void constructorWhenAllParametersProvidedAndValidThenCreated() {
+		DefaultOAuth2User user = new DefaultOAuth2User(AUTHORITIES, ATTRIBUTES, ATTRIBUTE_NAME_KEY);
 
-		new DefaultOAuth2User(TEST_AUTHORITIES, TEST_ATTRIBUTES, "invalid");
+		assertThat(user.getName()).isEqualTo(USERNAME);
+		assertThat(user.getAuthorities()).hasSize(1);
+		assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY);
+		assertThat(user.getAttributes()).containsOnlyKeys(ATTRIBUTE_NAME_KEY);
 	}
-
 }

+ 56 - 0
oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthorityTests.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-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.core.user;
+
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link OAuth2UserAuthority}.
+ *
+ * @author Joe Grandja
+ */
+public class OAuth2UserAuthorityTests {
+	private static final String AUTHORITY = "ROLE_USER";
+	private static final Map<String, Object> ATTRIBUTES = Collections.singletonMap("username", "test");
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAuthorityIsNullThenThrowIllegalArgumentException() {
+		new OAuth2UserAuthority(null, ATTRIBUTES);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAttributesIsNullThenThrowIllegalArgumentException() {
+		new OAuth2UserAuthority(AUTHORITY, null);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorWhenAttributesIsEmptyThenThrowIllegalArgumentException() {
+		new OAuth2UserAuthority(AUTHORITY, Collections.emptyMap());
+	}
+
+	@Test
+	public void constructorWhenAllParametersProvidedAndValidThenCreated() {
+		OAuth2UserAuthority userAuthority = new OAuth2UserAuthority(AUTHORITY, ATTRIBUTES);
+
+		assertThat(userAuthority.getAuthority()).isEqualTo(AUTHORITY);
+		assertThat(userAuthority.getAttributes()).isEqualTo(ATTRIBUTES);
+	}
+}