diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java index 68c022ff7d..b70bd2accd 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java @@ -15,17 +15,13 @@ */ package org.springframework.security.oauth2.server.resource.authentication; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.stream.Collectors; import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.jwt.Jwt; @@ -35,7 +31,6 @@ import org.springframework.security.oauth2.server.resource.BearerTokenAuthentica import org.springframework.security.oauth2.server.resource.BearerTokenError; import org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** * An {@link AuthenticationProvider} implementation of the {@link Jwt}-encoded @@ -64,10 +59,7 @@ import org.springframework.util.StringUtils; public final class JwtAuthenticationProvider implements AuthenticationProvider { private final JwtDecoder jwtDecoder; - private static final Collection WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES = - Arrays.asList("scope", "scp"); - - private static final String SCOPE_AUTHORITY_PREFIX = "SCOPE_"; + private final JwtConverter jwtConverter = new JwtConverter(); public JwtAuthenticationProvider(JwtDecoder jwtDecoder) { Assert.notNull(jwtDecoder, "jwtDecoder cannot be null"); @@ -101,16 +93,7 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider { } throw new OAuth2AuthenticationException(invalidToken, failed); } - - Collection authorities = - this.getScopes(jwt) - .stream() - .map(authority -> SCOPE_AUTHORITY_PREFIX + authority) - .map(SimpleGrantedAuthority::new) - .collect(Collectors.toList()); - - JwtAuthenticationToken token = new JwtAuthenticationToken(jwt, authorities); - + JwtAuthenticationToken token = this.jwtConverter.convert(jwt); token.setDetails(bearer.getDetails()); return token; @@ -131,21 +114,4 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider { message, "https://tools.ietf.org/html/rfc6750#section-3.1"); } - - private static Collection getScopes(Jwt jwt) { - for ( String attributeName : WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES ) { - Object scopes = jwt.getClaims().get(attributeName); - if (scopes instanceof String) { - if (StringUtils.hasText((String) scopes)) { - return Arrays.asList(((String) scopes).split(" ")); - } else { - return Collections.emptyList(); - } - } else if (scopes instanceof Collection) { - return (Collection) scopes; - } - } - - return Collections.emptyList(); - } } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtConverter.java new file mode 100644 index 0000000000..0ade72982f --- /dev/null +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtConverter.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2018 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.server.resource.authentication; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.util.StringUtils; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + +/** + * @author Rob Winch + * @since 5.1 + */ +class JwtConverter { + private static final String SCOPE_AUTHORITY_PREFIX = "SCOPE_"; + + private static final Collection WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES = + Arrays.asList("scope", "scp"); + + + JwtAuthenticationToken convert(Jwt jwt) { + Collection authorities = + this.getScopes(jwt) + .stream() + .map(authority -> SCOPE_AUTHORITY_PREFIX + authority) + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + + return new JwtAuthenticationToken(jwt, authorities); + } + + private Collection getScopes(Jwt jwt) { + for ( String attributeName : WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES ) { + Object scopes = jwt.getClaims().get(attributeName); + if (scopes instanceof String) { + if (StringUtils.hasText((String) scopes)) { + return Arrays.asList(((String) scopes).split(" ")); + } else { + return Collections.emptyList(); + } + } else if (scopes instanceof Collection) { + return (Collection) scopes; + } + } + + return Collections.emptyList(); + } +}