From 75706f118cb44afd89db5ec47e0909ba0b22cf8b Mon Sep 17 00:00:00 2001 From: Mayur Patel Date: Wed, 27 Jan 2021 11:34:00 +0530 Subject: [PATCH] Allow null or empty authorities for DefaultOAuth2User Make DefaultOAuth2User more inline with other part of spring-security. For example, - DefaultOAuth2AuthenticatedPrincipal - AbstractAuthenticationToken Closes gh-9366 --- .../oauth2/core/user/DefaultOAuth2User.java | 8 +++-- .../core/oidc/user/DefaultOidcUserTests.java | 28 +++++++++++++---- .../core/user/DefaultOAuth2UserTests.java | 30 +++++++++++-------- 3 files changed, 44 insertions(+), 22 deletions(-) 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 31fb080f50..a8ad76cd00 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -29,6 +29,7 @@ import java.util.TreeSet; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityCoreVersion; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.util.Assert; /** @@ -65,13 +66,14 @@ public class DefaultOAuth2User implements OAuth2User, Serializable { */ public DefaultOAuth2User(Collection authorities, Map attributes, String nameAttributeKey) { - Assert.notEmpty(authorities, "authorities cannot be empty"); Assert.notEmpty(attributes, "attributes cannot be empty"); Assert.hasText(nameAttributeKey, "nameAttributeKey cannot be empty"); if (!attributes.containsKey(nameAttributeKey)) { throw new IllegalArgumentException("Missing attribute '" + nameAttributeKey + "' in attributes"); } - this.authorities = Collections.unmodifiableSet(new LinkedHashSet<>(this.sortAuthorities(authorities))); + this.authorities = (authorities != null) + ? Collections.unmodifiableSet(new LinkedHashSet<>(this.sortAuthorities(authorities))) + : Collections.unmodifiableSet(new LinkedHashSet<>(AuthorityUtils.NO_AUTHORITIES)); this.attributes = Collections.unmodifiableMap(new LinkedHashMap<>(attributes)); this.nameAttributeKey = nameAttributeKey; } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java index a7f21a5098..a928dc0fbc 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -25,6 +25,7 @@ import java.util.Set; import org.junit.Test; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; import org.springframework.security.oauth2.core.oidc.OidcIdToken; @@ -66,11 +67,6 @@ public class DefaultOidcUserTests { private static final OidcUserInfo USER_INFO = new OidcUserInfo(USER_INFO_CLAIMS); - @Test - public void constructorWhenAuthoritiesIsNullThenThrowIllegalArgumentException() { - assertThatIllegalArgumentException().isThrownBy(() -> new DefaultOidcUser(null, ID_TOKEN)); - } - @Test public void constructorWhenIdTokenIsNullThenThrowIllegalArgumentException() { assertThatIllegalArgumentException().isThrownBy(() -> new DefaultOidcUser(AUTHORITIES, null)); @@ -81,6 +77,26 @@ public class DefaultOidcUserTests { assertThatIllegalArgumentException().isThrownBy(() -> new DefaultOidcUser(AUTHORITIES, ID_TOKEN, "invalid")); } + @Test + public void constructorWhenAuthoritiesIsNullThenCreatedWithEmptyAuthorities() { + DefaultOidcUser user = new DefaultOidcUser(null, ID_TOKEN); + assertThat(user.getClaims()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB); + assertThat(user.getIdToken()).isEqualTo(ID_TOKEN); + assertThat(user.getName()).isEqualTo(SUBJECT); + assertThat(user.getAuthorities()).isEmpty(); + assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB); + } + + @Test + public void constructorWhenAuthoritiesIsEmptyThenCreated() { + DefaultOidcUser user = new DefaultOidcUser(AuthorityUtils.NO_AUTHORITIES, ID_TOKEN); + assertThat(user.getClaims()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB); + assertThat(user.getIdToken()).isEqualTo(ID_TOKEN); + assertThat(user.getName()).isEqualTo(SUBJECT); + assertThat(user.getAuthorities()).isEmpty(); + assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB); + } + @Test public void constructorWhenAuthoritiesIdTokenProvidedThenCreated() { DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN); diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java index 9d0e5abce1..5ba71e4fb7 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -47,18 +47,6 @@ public class DefaultOAuth2UserTests { private static final Map ATTRIBUTES = Collections.singletonMap(ATTRIBUTE_NAME_KEY, USERNAME); - @Test - public void constructorWhenAuthoritiesIsNullThenThrowIllegalArgumentException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new DefaultOAuth2User(null, ATTRIBUTES, ATTRIBUTE_NAME_KEY)); - } - - @Test - public void constructorWhenAuthoritiesIsEmptyThenThrowIllegalArgumentException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new DefaultOAuth2User(Collections.emptySet(), ATTRIBUTES, ATTRIBUTE_NAME_KEY)); - } - @Test public void constructorWhenAttributesIsNullThenThrowIllegalArgumentException() { assertThatIllegalArgumentException() @@ -82,6 +70,22 @@ public class DefaultOAuth2UserTests { .isThrownBy(() -> new DefaultOAuth2User(AUTHORITIES, ATTRIBUTES, "invalid")); } + @Test + public void constructorWhenAuthoritiesIsNullThenCreatedWithEmptyAuthorities() { + DefaultOAuth2User user = new DefaultOAuth2User(null, ATTRIBUTES, ATTRIBUTE_NAME_KEY); + assertThat(user.getName()).isEqualTo(USERNAME); + assertThat(user.getAuthorities()).isEmpty(); + assertThat(user.getAttributes()).containsOnlyKeys(ATTRIBUTE_NAME_KEY); + } + + @Test + public void constructorWhenAuthoritiesIsEmptyThenCreated() { + DefaultOAuth2User user = new DefaultOAuth2User(Collections.emptySet(), ATTRIBUTES, ATTRIBUTE_NAME_KEY); + assertThat(user.getName()).isEqualTo(USERNAME); + assertThat(user.getAuthorities()).isEmpty(); + assertThat(user.getAttributes()).containsOnlyKeys(ATTRIBUTE_NAME_KEY); + } + @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { DefaultOAuth2User user = new DefaultOAuth2User(AUTHORITIES, ATTRIBUTES, ATTRIBUTE_NAME_KEY);