mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-04-01 12:58:25 +00:00
Polish spring-security-oauth2-resource-server main code
Manually polish `spring-security-oauth-resource-server` following the formatting and checkstyle fixes. Issue gh-8945
This commit is contained in:
parent
20aa8bef25
commit
ba19a9e4b6
@ -40,7 +40,7 @@ public class BearerTokenAuthenticationToken extends AbstractAuthenticationToken
|
|||||||
|
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
private String token;
|
private final String token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@code BearerTokenAuthenticationToken} using the provided parameter(s)
|
* Create a {@code BearerTokenAuthenticationToken} using the provided parameter(s)
|
||||||
@ -48,9 +48,7 @@ public class BearerTokenAuthenticationToken extends AbstractAuthenticationToken
|
|||||||
*/
|
*/
|
||||||
public BearerTokenAuthenticationToken(String token) {
|
public BearerTokenAuthenticationToken(String token) {
|
||||||
super(Collections.emptyList());
|
super(Collections.emptyList());
|
||||||
|
|
||||||
Assert.hasText(token, "token cannot be empty");
|
Assert.hasText(token, "token cannot be empty");
|
||||||
|
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,17 +63,11 @@ public class BearerTokenAuthenticationToken extends AbstractAuthenticationToken
|
|||||||
return this.token;
|
return this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return this.getToken();
|
return this.getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Object getPrincipal() {
|
public Object getPrincipal() {
|
||||||
return this.getToken();
|
return this.getToken();
|
||||||
|
@ -59,7 +59,6 @@ public final class BearerTokenError extends OAuth2Error {
|
|||||||
String scope) {
|
String scope) {
|
||||||
super(errorCode, description, errorUri);
|
super(errorCode, description, errorUri);
|
||||||
Assert.notNull(httpStatus, "httpStatus cannot be null");
|
Assert.notNull(httpStatus, "httpStatus cannot be null");
|
||||||
|
|
||||||
Assert.isTrue(isDescriptionValid(description),
|
Assert.isTrue(isDescriptionValid(description),
|
||||||
"description contains invalid ASCII characters, it must conform to RFC 6750");
|
"description contains invalid ASCII characters, it must conform to RFC 6750");
|
||||||
Assert.isTrue(isErrorCodeValid(errorCode),
|
Assert.isTrue(isErrorCodeValid(errorCode),
|
||||||
@ -67,7 +66,6 @@ public final class BearerTokenError extends OAuth2Error {
|
|||||||
Assert.isTrue(isErrorUriValid(errorUri),
|
Assert.isTrue(isErrorUriValid(errorUri),
|
||||||
"errorUri contains invalid ASCII characters, it must conform to RFC 6750");
|
"errorUri contains invalid ASCII characters, it must conform to RFC 6750");
|
||||||
Assert.isTrue(isScopeValid(scope), "scope contains invalid ASCII characters, it must conform to RFC 6750");
|
Assert.isTrue(isScopeValid(scope), "scope contains invalid ASCII characters, it must conform to RFC 6750");
|
||||||
|
|
||||||
this.httpStatus = httpStatus;
|
this.httpStatus = httpStatus;
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@ public final class BearerTokenErrors {
|
|||||||
|
|
||||||
private static final String DEFAULT_URI = "https://tools.ietf.org/html/rfc6750#section-3.1";
|
private static final String DEFAULT_URI = "https://tools.ietf.org/html/rfc6750#section-3.1";
|
||||||
|
|
||||||
|
private BearerTokenErrors() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link BearerTokenError} caused by an invalid request
|
* Create a {@link BearerTokenError} caused by an invalid request
|
||||||
* @param message a description of the error
|
* @param message a description of the error
|
||||||
@ -46,7 +49,7 @@ public final class BearerTokenErrors {
|
|||||||
return new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, message,
|
return new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, message,
|
||||||
DEFAULT_URI);
|
DEFAULT_URI);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException malformed) {
|
catch (IllegalArgumentException ex) {
|
||||||
// some third-party library error messages are not suitable for RFC 6750's
|
// some third-party library error messages are not suitable for RFC 6750's
|
||||||
// error message charset
|
// error message charset
|
||||||
return DEFAULT_INVALID_REQUEST;
|
return DEFAULT_INVALID_REQUEST;
|
||||||
@ -63,7 +66,7 @@ public final class BearerTokenErrors {
|
|||||||
return new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED, message,
|
return new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED, message,
|
||||||
DEFAULT_URI);
|
DEFAULT_URI);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException malformed) {
|
catch (IllegalArgumentException ex) {
|
||||||
// some third-party library error messages are not suitable for RFC 6750's
|
// some third-party library error messages are not suitable for RFC 6750's
|
||||||
// error message charset
|
// error message charset
|
||||||
return DEFAULT_INVALID_TOKEN;
|
return DEFAULT_INVALID_TOKEN;
|
||||||
@ -80,14 +83,11 @@ public final class BearerTokenErrors {
|
|||||||
return new BearerTokenError(BearerTokenErrorCodes.INSUFFICIENT_SCOPE, HttpStatus.FORBIDDEN, message,
|
return new BearerTokenError(BearerTokenErrorCodes.INSUFFICIENT_SCOPE, HttpStatus.FORBIDDEN, message,
|
||||||
DEFAULT_URI, scope);
|
DEFAULT_URI, scope);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException malformed) {
|
catch (IllegalArgumentException ex) {
|
||||||
// some third-party library error messages are not suitable for RFC 6750's
|
// some third-party library error messages are not suitable for RFC 6750's
|
||||||
// error message charset
|
// error message charset
|
||||||
return DEFAULT_INSUFFICIENT_SCOPE;
|
return DEFAULT_INSUFFICIENT_SCOPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BearerTokenErrors() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,17 +84,11 @@ public abstract class AbstractOAuth2TokenAuthenticationToken<T extends AbstractO
|
|||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Object getPrincipal() {
|
public Object getPrincipal() {
|
||||||
return this.principal;
|
return this.principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return this.credentials;
|
return this.credentials;
|
||||||
|
@ -40,7 +40,7 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication
|
|||||||
|
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
private Map<String, Object> attributes;
|
private final Map<String, Object> attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@link BearerTokenAuthentication} with the provided arguments
|
* Constructs a {@link BearerTokenAuthentication} with the provided arguments
|
||||||
@ -50,7 +50,6 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication
|
|||||||
*/
|
*/
|
||||||
public BearerTokenAuthentication(OAuth2AuthenticatedPrincipal principal, OAuth2AccessToken credentials,
|
public BearerTokenAuthentication(OAuth2AuthenticatedPrincipal principal, OAuth2AccessToken credentials,
|
||||||
Collection<? extends GrantedAuthority> authorities) {
|
Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
|
||||||
super(credentials, principal, credentials, authorities);
|
super(credentials, principal, credentials, authorities);
|
||||||
Assert.isTrue(credentials.getTokenType() == OAuth2AccessToken.TokenType.BEARER,
|
Assert.isTrue(credentials.getTokenType() == OAuth2AccessToken.TokenType.BEARER,
|
||||||
"credentials must be a bearer token");
|
"credentials must be a bearer token");
|
||||||
@ -58,9 +57,6 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication
|
|||||||
setAuthenticated(true);
|
setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getTokenAttributes() {
|
public Map<String, Object> getTokenAttributes() {
|
||||||
return this.attributes;
|
return this.attributes;
|
||||||
|
@ -43,7 +43,6 @@ public class JwtAuthenticationConverter implements Converter<Jwt, AbstractAuthen
|
|||||||
if (this.principalClaimName == null) {
|
if (this.principalClaimName == null) {
|
||||||
return new JwtAuthenticationToken(jwt, authorities);
|
return new JwtAuthenticationToken(jwt, authorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = jwt.getClaim(this.principalClaimName);
|
String name = jwt.getClaim(this.principalClaimName);
|
||||||
return new JwtAuthenticationToken(jwt, authorities, name);
|
return new JwtAuthenticationToken(jwt, authorities, name);
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,15 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider {
|
|||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;
|
BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;
|
||||||
|
Jwt jwt = getJwt(bearer);
|
||||||
|
AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt);
|
||||||
|
token.setDetails(bearer.getDetails());
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
Jwt jwt;
|
private Jwt getJwt(BearerTokenAuthenticationToken bearer) {
|
||||||
try {
|
try {
|
||||||
jwt = this.jwtDecoder.decode(bearer.getToken());
|
return this.jwtDecoder.decode(bearer.getToken());
|
||||||
}
|
}
|
||||||
catch (BadJwtException failed) {
|
catch (BadJwtException failed) {
|
||||||
throw new InvalidBearerTokenException(failed.getMessage(), failed);
|
throw new InvalidBearerTokenException(failed.getMessage(), failed);
|
||||||
@ -91,16 +96,8 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider {
|
|||||||
catch (JwtException failed) {
|
catch (JwtException failed) {
|
||||||
throw new AuthenticationServiceException(failed.getMessage(), failed);
|
throw new AuthenticationServiceException(failed.getMessage(), failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt);
|
|
||||||
token.setDetails(bearer.getDetails());
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> authentication) {
|
public boolean supports(Class<?> authentication) {
|
||||||
return BearerTokenAuthenticationToken.class.isAssignableFrom(authentication);
|
return BearerTokenAuthenticationToken.class.isAssignableFrom(authentication);
|
||||||
@ -108,7 +105,6 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider {
|
|||||||
|
|
||||||
public void setJwtAuthenticationConverter(
|
public void setJwtAuthenticationConverter(
|
||||||
Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter) {
|
Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter) {
|
||||||
|
|
||||||
Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null");
|
Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null");
|
||||||
this.jwtAuthenticationConverter = jwtAuthenticationConverter;
|
this.jwtAuthenticationConverter = jwtAuthenticationConverter;
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,6 @@ public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationTok
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getTokenAttributes() {
|
public Map<String, Object> getTokenAttributes() {
|
||||||
return this.getToken().getClaims();
|
return this.getToken().getClaims();
|
||||||
|
@ -52,10 +52,8 @@ public final class JwtBearerTokenAuthenticationConverter implements Converter<Jw
|
|||||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, jwt.getTokenValue(),
|
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, jwt.getTokenValue(),
|
||||||
jwt.getIssuedAt(), jwt.getExpiresAt());
|
jwt.getIssuedAt(), jwt.getExpiresAt());
|
||||||
Map<String, Object> attributes = jwt.getClaims();
|
Map<String, Object> attributes = jwt.getClaims();
|
||||||
|
|
||||||
AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt);
|
AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt);
|
||||||
Collection<GrantedAuthority> authorities = token.getAuthorities();
|
Collection<GrantedAuthority> authorities = token.getAuthorities();
|
||||||
|
|
||||||
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(attributes, authorities);
|
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(attributes, authorities);
|
||||||
return new BearerTokenAuthentication(principal, accessToken, authorities);
|
return new BearerTokenAuthentication(principal, accessToken, authorities);
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,9 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getAuthoritiesClaimName(Jwt jwt) {
|
private String getAuthoritiesClaimName(Jwt jwt) {
|
||||||
|
|
||||||
if (this.authoritiesClaimName != null) {
|
if (this.authoritiesClaimName != null) {
|
||||||
return this.authoritiesClaimName;
|
return this.authoritiesClaimName;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String claimName : WELL_KNOWN_AUTHORITIES_CLAIM_NAMES) {
|
for (String claimName : WELL_KNOWN_AUTHORITIES_CLAIM_NAMES) {
|
||||||
if (jwt.containsClaim(claimName)) {
|
if (jwt.containsClaim(claimName)) {
|
||||||
return claimName;
|
return claimName;
|
||||||
@ -99,24 +97,19 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
|
|||||||
|
|
||||||
private Collection<String> getAuthorities(Jwt jwt) {
|
private Collection<String> getAuthorities(Jwt jwt) {
|
||||||
String claimName = getAuthoritiesClaimName(jwt);
|
String claimName = getAuthoritiesClaimName(jwt);
|
||||||
|
|
||||||
if (claimName == null) {
|
if (claimName == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object authorities = jwt.getClaim(claimName);
|
Object authorities = jwt.getClaim(claimName);
|
||||||
if (authorities instanceof String) {
|
if (authorities instanceof String) {
|
||||||
if (StringUtils.hasText((String) authorities)) {
|
if (StringUtils.hasText((String) authorities)) {
|
||||||
return Arrays.asList(((String) authorities).split(" "));
|
return Arrays.asList(((String) authorities).split(" "));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
if (authorities instanceof Collection) {
|
||||||
else if (authorities instanceof Collection) {
|
|
||||||
return (Collection<String>) authorities;
|
return (Collection<String>) authorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,6 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
|||||||
*/
|
*/
|
||||||
public JwtIssuerReactiveAuthenticationManagerResolver(
|
public JwtIssuerReactiveAuthenticationManagerResolver(
|
||||||
ReactiveAuthenticationManagerResolver<String> issuerAuthenticationManagerResolver) {
|
ReactiveAuthenticationManagerResolver<String> issuerAuthenticationManagerResolver) {
|
||||||
|
|
||||||
Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null");
|
Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null");
|
||||||
this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver;
|
this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver;
|
||||||
}
|
}
|
||||||
@ -141,10 +140,8 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
|||||||
if (issuer == null) {
|
if (issuer == null) {
|
||||||
throw new InvalidBearerTokenException("Missing issuer");
|
throw new InvalidBearerTokenException("Missing issuer");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return issuer;
|
return issuer;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new InvalidBearerTokenException(ex.getMessage(), ex);
|
throw new InvalidBearerTokenException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,6 @@ public final class JwtReactiveAuthenticationManager implements ReactiveAuthentic
|
|||||||
*/
|
*/
|
||||||
public void setJwtAuthenticationConverter(
|
public void setJwtAuthenticationConverter(
|
||||||
Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter) {
|
Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter) {
|
||||||
|
|
||||||
Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null");
|
Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null");
|
||||||
this.jwtAuthenticationConverter = jwtAuthenticationConverter;
|
this.jwtAuthenticationConverter = jwtAuthenticationConverter;
|
||||||
}
|
}
|
||||||
@ -74,9 +73,7 @@ public final class JwtReactiveAuthenticationManager implements ReactiveAuthentic
|
|||||||
if (ex instanceof BadJwtException) {
|
if (ex instanceof BadJwtException) {
|
||||||
return new InvalidBearerTokenException(ex.getMessage(), ex);
|
return new InvalidBearerTokenException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return new AuthenticationServiceException(ex.getMessage(), ex);
|
return new AuthenticationServiceException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,10 +86,15 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;
|
BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;
|
||||||
|
OAuth2AuthenticatedPrincipal principal = getOAuth2AuthenticatedPrincipal(bearer);
|
||||||
|
AbstractAuthenticationToken result = convert(principal, bearer.getToken());
|
||||||
|
result.setDetails(bearer.getDetails());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
OAuth2AuthenticatedPrincipal principal;
|
private OAuth2AuthenticatedPrincipal getOAuth2AuthenticatedPrincipal(BearerTokenAuthenticationToken bearer) {
|
||||||
try {
|
try {
|
||||||
principal = this.introspector.introspect(bearer.getToken());
|
return this.introspector.introspect(bearer.getToken());
|
||||||
}
|
}
|
||||||
catch (BadOpaqueTokenException failed) {
|
catch (BadOpaqueTokenException failed) {
|
||||||
throw new InvalidBearerTokenException(failed.getMessage());
|
throw new InvalidBearerTokenException(failed.getMessage());
|
||||||
@ -97,15 +102,8 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr
|
|||||||
catch (OAuth2IntrospectionException failed) {
|
catch (OAuth2IntrospectionException failed) {
|
||||||
throw new AuthenticationServiceException(failed.getMessage());
|
throw new AuthenticationServiceException(failed.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractAuthenticationToken result = convert(principal, bearer.getToken());
|
|
||||||
result.setDetails(bearer.getDetails());
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> authentication) {
|
public boolean supports(Class<?> authentication) {
|
||||||
return BearerTokenAuthenticationToken.class.isAssignableFrom(authentication);
|
return BearerTokenAuthenticationToken.class.isAssignableFrom(authentication);
|
||||||
|
@ -84,7 +84,6 @@ public class OpaqueTokenReactiveAuthenticationManager implements ReactiveAuthent
|
|||||||
return this.introspector.introspect(token).map((principal) -> {
|
return this.introspector.introspect(token).map((principal) -> {
|
||||||
Instant iat = principal.getAttribute(OAuth2IntrospectionClaimNames.ISSUED_AT);
|
Instant iat = principal.getAttribute(OAuth2IntrospectionClaimNames.ISSUED_AT);
|
||||||
Instant exp = principal.getAttribute(OAuth2IntrospectionClaimNames.EXPIRES_AT);
|
Instant exp = principal.getAttribute(OAuth2IntrospectionClaimNames.EXPIRES_AT);
|
||||||
|
|
||||||
// construct token
|
// construct token
|
||||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp);
|
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp);
|
||||||
return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities());
|
return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities());
|
||||||
@ -95,9 +94,7 @@ public class OpaqueTokenReactiveAuthenticationManager implements ReactiveAuthent
|
|||||||
if (ex instanceof BadOpaqueTokenException) {
|
if (ex instanceof BadOpaqueTokenException) {
|
||||||
return new InvalidBearerTokenException(ex.getMessage(), ex);
|
return new InvalidBearerTokenException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return new AuthenticationServiceException(ex.getMessage(), ex);
|
return new AuthenticationServiceException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,6 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
|||||||
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
||||||
Assert.notNull(clientId, "clientId cannot be null");
|
Assert.notNull(clientId, "clientId cannot be null");
|
||||||
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
||||||
|
|
||||||
this.requestEntityConverter = this.defaultRequestEntityConverter(URI.create(introspectionUri));
|
this.requestEntityConverter = this.defaultRequestEntityConverter(URI.create(introspectionUri));
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(clientId, clientSecret));
|
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(clientId, clientSecret));
|
||||||
@ -92,7 +91,6 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
|||||||
public NimbusOpaqueTokenIntrospector(String introspectionUri, RestOperations restOperations) {
|
public NimbusOpaqueTokenIntrospector(String introspectionUri, RestOperations restOperations) {
|
||||||
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
||||||
Assert.notNull(restOperations, "restOperations cannot be null");
|
Assert.notNull(restOperations, "restOperations cannot be null");
|
||||||
|
|
||||||
this.requestEntityConverter = this.defaultRequestEntityConverter(URI.create(introspectionUri));
|
this.requestEntityConverter = this.defaultRequestEntityConverter(URI.create(introspectionUri));
|
||||||
this.restOperations = restOperations;
|
this.restOperations = restOperations;
|
||||||
}
|
}
|
||||||
@ -117,27 +115,21 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2AuthenticatedPrincipal introspect(String token) {
|
public OAuth2AuthenticatedPrincipal introspect(String token) {
|
||||||
RequestEntity<?> requestEntity = this.requestEntityConverter.convert(token);
|
RequestEntity<?> requestEntity = this.requestEntityConverter.convert(token);
|
||||||
if (requestEntity == null) {
|
if (requestEntity == null) {
|
||||||
throw new OAuth2IntrospectionException("requestEntityConverter returned a null entity");
|
throw new OAuth2IntrospectionException("requestEntityConverter returned a null entity");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponseEntity<String> responseEntity = makeRequest(requestEntity);
|
ResponseEntity<String> responseEntity = makeRequest(requestEntity);
|
||||||
HTTPResponse httpResponse = adaptToNimbusResponse(responseEntity);
|
HTTPResponse httpResponse = adaptToNimbusResponse(responseEntity);
|
||||||
TokenIntrospectionResponse introspectionResponse = parseNimbusResponse(httpResponse);
|
TokenIntrospectionResponse introspectionResponse = parseNimbusResponse(httpResponse);
|
||||||
TokenIntrospectionSuccessResponse introspectionSuccessResponse = castToNimbusSuccess(introspectionResponse);
|
TokenIntrospectionSuccessResponse introspectionSuccessResponse = castToNimbusSuccess(introspectionResponse);
|
||||||
|
|
||||||
// relying solely on the authorization server to validate this token (not checking
|
// relying solely on the authorization server to validate this token (not checking
|
||||||
// 'exp', for example)
|
// 'exp', for example)
|
||||||
if (!introspectionSuccessResponse.isActive()) {
|
if (!introspectionSuccessResponse.isActive()) {
|
||||||
throw new BadOpaqueTokenException("Provided token isn't active");
|
throw new BadOpaqueTokenException("Provided token isn't active");
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertClaimsSet(introspectionSuccessResponse);
|
return convertClaimsSet(introspectionSuccessResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +141,6 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
|||||||
*/
|
*/
|
||||||
public void setRequestEntityConverter(Converter<String, RequestEntity<?>> requestEntityConverter) {
|
public void setRequestEntityConverter(Converter<String, RequestEntity<?>> requestEntityConverter) {
|
||||||
Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null");
|
Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null");
|
||||||
|
|
||||||
this.requestEntityConverter = requestEntityConverter;
|
this.requestEntityConverter = requestEntityConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +157,6 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
|||||||
HTTPResponse response = new HTTPResponse(responseEntity.getStatusCodeValue());
|
HTTPResponse response = new HTTPResponse(responseEntity.getStatusCodeValue());
|
||||||
response.setHeader(HttpHeaders.CONTENT_TYPE, responseEntity.getHeaders().getContentType().toString());
|
response.setHeader(HttpHeaders.CONTENT_TYPE, responseEntity.getHeaders().getContentType().toString());
|
||||||
response.setContent(responseEntity.getBody());
|
response.setContent(responseEntity.getBody());
|
||||||
|
|
||||||
if (response.getStatusCode() != HTTPResponse.SC_OK) {
|
if (response.getStatusCode() != HTTPResponse.SC_OK) {
|
||||||
throw new OAuth2IntrospectionException("Introspection endpoint responded with " + response.getStatusCode());
|
throw new OAuth2IntrospectionException("Introspection endpoint responded with " + response.getStatusCode());
|
||||||
}
|
}
|
||||||
@ -219,12 +209,10 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
|||||||
if (response.getScope() != null) {
|
if (response.getScope() != null) {
|
||||||
List<String> scopes = Collections.unmodifiableList(response.getScope().toStringList());
|
List<String> scopes = Collections.unmodifiableList(response.getScope().toStringList());
|
||||||
claims.put(OAuth2IntrospectionClaimNames.SCOPE, scopes);
|
claims.put(OAuth2IntrospectionClaimNames.SCOPE, scopes);
|
||||||
|
|
||||||
for (String scope : scopes) {
|
for (String scope : scopes) {
|
||||||
authorities.add(new SimpleGrantedAuthority(this.authorityPrefix + scope));
|
authorities.add(new SimpleGrantedAuthority(this.authorityPrefix + scope));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OAuth2IntrospectionAuthenticatedPrincipal(claims, authorities);
|
return new OAuth2IntrospectionAuthenticatedPrincipal(claims, authorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,9 @@ import org.springframework.web.reactive.function.client.WebClient;
|
|||||||
*/
|
*/
|
||||||
public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueTokenIntrospector {
|
public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueTokenIntrospector {
|
||||||
|
|
||||||
private URI introspectionUri;
|
private final URI introspectionUri;
|
||||||
|
|
||||||
private WebClient webClient;
|
private final WebClient webClient;
|
||||||
|
|
||||||
private String authorityPrefix = "SCOPE_";
|
private String authorityPrefix = "SCOPE_";
|
||||||
|
|
||||||
@ -71,7 +71,6 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
|
|||||||
Assert.hasText(introspectionUri, "introspectionUri cannot be empty");
|
Assert.hasText(introspectionUri, "introspectionUri cannot be empty");
|
||||||
Assert.hasText(clientId, "clientId cannot be empty");
|
Assert.hasText(clientId, "clientId cannot be empty");
|
||||||
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
||||||
|
|
||||||
this.introspectionUri = URI.create(introspectionUri);
|
this.introspectionUri = URI.create(introspectionUri);
|
||||||
this.webClient = WebClient.builder().defaultHeaders((h) -> h.setBasicAuth(clientId, clientSecret)).build();
|
this.webClient = WebClient.builder().defaultHeaders((h) -> h.setBasicAuth(clientId, clientSecret)).build();
|
||||||
}
|
}
|
||||||
@ -85,14 +84,10 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
|
|||||||
public NimbusReactiveOpaqueTokenIntrospector(String introspectionUri, WebClient webClient) {
|
public NimbusReactiveOpaqueTokenIntrospector(String introspectionUri, WebClient webClient) {
|
||||||
Assert.hasText(introspectionUri, "introspectionUri cannot be null");
|
Assert.hasText(introspectionUri, "introspectionUri cannot be null");
|
||||||
Assert.notNull(webClient, "webClient cannot be null");
|
Assert.notNull(webClient, "webClient cannot be null");
|
||||||
|
|
||||||
this.introspectionUri = URI.create(introspectionUri);
|
this.introspectionUri = URI.create(introspectionUri);
|
||||||
this.webClient = webClient;
|
this.webClient = webClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<OAuth2AuthenticatedPrincipal> introspect(String token) {
|
public Mono<OAuth2AuthenticatedPrincipal> introspect(String token) {
|
||||||
return Mono.just(token).flatMap(this::makeRequest).flatMap(this::adaptToNimbusResponse)
|
return Mono.just(token).flatMap(this::makeRequest).flatMap(this::adaptToNimbusResponse)
|
||||||
@ -177,7 +172,6 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
|
|||||||
authorities.add(new SimpleGrantedAuthority(this.authorityPrefix + scope));
|
authorities.add(new SimpleGrantedAuthority(this.authorityPrefix + scope));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OAuth2IntrospectionAuthenticatedPrincipal(claims, authorities);
|
return new OAuth2IntrospectionAuthenticatedPrincipal(claims, authorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal
|
|||||||
*/
|
*/
|
||||||
public OAuth2IntrospectionAuthenticatedPrincipal(Map<String, Object> attributes,
|
public OAuth2IntrospectionAuthenticatedPrincipal(Map<String, Object> attributes,
|
||||||
Collection<GrantedAuthority> authorities) {
|
Collection<GrantedAuthority> authorities) {
|
||||||
|
|
||||||
this.delegate = new DefaultOAuth2AuthenticatedPrincipal(attributes, authorities);
|
this.delegate = new DefaultOAuth2AuthenticatedPrincipal(attributes, authorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +57,6 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal
|
|||||||
*/
|
*/
|
||||||
public OAuth2IntrospectionAuthenticatedPrincipal(String name, Map<String, Object> attributes,
|
public OAuth2IntrospectionAuthenticatedPrincipal(String name, Map<String, Object> attributes,
|
||||||
Collection<GrantedAuthority> authorities) {
|
Collection<GrantedAuthority> authorities) {
|
||||||
|
|
||||||
this.delegate = new DefaultOAuth2AuthenticatedPrincipal(name, attributes, authorities);
|
this.delegate = new DefaultOAuth2AuthenticatedPrincipal(name, attributes, authorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,17 +79,11 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal
|
|||||||
return this.delegate.getAuthorities();
|
return this.delegate.getAuthorities();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.delegate.getName();
|
return this.delegate.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getClaims() {
|
public Map<String, Object> getClaims() {
|
||||||
return getAttributes();
|
return getAttributes();
|
||||||
|
@ -59,41 +59,29 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication
|
|||||||
@Override
|
@Override
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||||
AuthenticationException authException) {
|
AuthenticationException authException) {
|
||||||
|
|
||||||
HttpStatus status = HttpStatus.UNAUTHORIZED;
|
HttpStatus status = HttpStatus.UNAUTHORIZED;
|
||||||
|
|
||||||
Map<String, String> parameters = new LinkedHashMap<>();
|
Map<String, String> parameters = new LinkedHashMap<>();
|
||||||
|
|
||||||
if (this.realmName != null) {
|
if (this.realmName != null) {
|
||||||
parameters.put("realm", this.realmName);
|
parameters.put("realm", this.realmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authException instanceof OAuth2AuthenticationException) {
|
if (authException instanceof OAuth2AuthenticationException) {
|
||||||
OAuth2Error error = ((OAuth2AuthenticationException) authException).getError();
|
OAuth2Error error = ((OAuth2AuthenticationException) authException).getError();
|
||||||
|
|
||||||
parameters.put("error", error.getErrorCode());
|
parameters.put("error", error.getErrorCode());
|
||||||
|
|
||||||
if (StringUtils.hasText(error.getDescription())) {
|
if (StringUtils.hasText(error.getDescription())) {
|
||||||
parameters.put("error_description", error.getDescription());
|
parameters.put("error_description", error.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.hasText(error.getUri())) {
|
if (StringUtils.hasText(error.getUri())) {
|
||||||
parameters.put("error_uri", error.getUri());
|
parameters.put("error_uri", error.getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof BearerTokenError) {
|
if (error instanceof BearerTokenError) {
|
||||||
BearerTokenError bearerTokenError = (BearerTokenError) error;
|
BearerTokenError bearerTokenError = (BearerTokenError) error;
|
||||||
|
|
||||||
if (StringUtils.hasText(bearerTokenError.getScope())) {
|
if (StringUtils.hasText(bearerTokenError.getScope())) {
|
||||||
parameters.put("scope", bearerTokenError.getScope());
|
parameters.put("scope", bearerTokenError.getScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
status = ((BearerTokenError) error).getHttpStatus();
|
status = ((BearerTokenError) error).getHttpStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
|
String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
|
||||||
|
|
||||||
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
|
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
|
||||||
response.setStatus(status.value());
|
response.setStatus(status.value());
|
||||||
}
|
}
|
||||||
@ -109,20 +97,17 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication
|
|||||||
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
|
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
|
||||||
StringBuilder wwwAuthenticate = new StringBuilder();
|
StringBuilder wwwAuthenticate = new StringBuilder();
|
||||||
wwwAuthenticate.append("Bearer");
|
wwwAuthenticate.append("Bearer");
|
||||||
|
|
||||||
if (!parameters.isEmpty()) {
|
if (!parameters.isEmpty()) {
|
||||||
wwwAuthenticate.append(" ");
|
wwwAuthenticate.append(" ");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||||
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
||||||
|
|
||||||
if (i != parameters.size() - 1) {
|
if (i != parameters.size() - 1) {
|
||||||
wwwAuthenticate.append(", ");
|
wwwAuthenticate.append(", ");
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wwwAuthenticate.toString();
|
return wwwAuthenticate.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter
|
|||||||
*/
|
*/
|
||||||
public BearerTokenAuthenticationFilter(
|
public BearerTokenAuthenticationFilter(
|
||||||
AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver) {
|
AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver) {
|
||||||
|
|
||||||
Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null");
|
Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null");
|
||||||
this.authenticationManagerResolver = authenticationManagerResolver;
|
this.authenticationManagerResolver = authenticationManagerResolver;
|
||||||
}
|
}
|
||||||
@ -101,11 +100,7 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter
|
|||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
final boolean debug = this.logger.isDebugEnabled();
|
|
||||||
|
|
||||||
String token;
|
String token;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
token = this.bearerTokenResolver.resolve(request);
|
token = this.bearerTokenResolver.resolve(request);
|
||||||
}
|
}
|
||||||
@ -113,33 +108,23 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter
|
|||||||
this.authenticationEntryPoint.commence(request, response, invalid);
|
this.authenticationEntryPoint.commence(request, response, invalid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BearerTokenAuthenticationToken authenticationRequest = new BearerTokenAuthenticationToken(token);
|
BearerTokenAuthenticationToken authenticationRequest = new BearerTokenAuthenticationToken(token);
|
||||||
|
|
||||||
authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AuthenticationManager authenticationManager = this.authenticationManagerResolver.resolve(request);
|
AuthenticationManager authenticationManager = this.authenticationManagerResolver.resolve(request);
|
||||||
Authentication authenticationResult = authenticationManager.authenticate(authenticationRequest);
|
Authentication authenticationResult = authenticationManager.authenticate(authenticationRequest);
|
||||||
|
|
||||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
context.setAuthentication(authenticationResult);
|
context.setAuthentication(authenticationResult);
|
||||||
SecurityContextHolder.setContext(context);
|
SecurityContextHolder.setContext(context);
|
||||||
|
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
catch (AuthenticationException failed) {
|
catch (AuthenticationException failed) {
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
this.logger.debug("Authentication request for failed!", failed);
|
this.logger.debug("Authentication request for failed!", failed);
|
||||||
}
|
|
||||||
|
|
||||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, failed);
|
this.authenticationFailureHandler.onAuthenticationFailure(request, response, failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,6 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
|||||||
|
|
||||||
private String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION;
|
private String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION;
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String resolve(HttpServletRequest request) {
|
public String resolve(HttpServletRequest request) {
|
||||||
String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
|
String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
|
||||||
@ -61,7 +58,7 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
|||||||
}
|
}
|
||||||
return authorizationHeaderToken;
|
return authorizationHeaderToken;
|
||||||
}
|
}
|
||||||
else if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
|
if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
|
||||||
return parameterToken;
|
return parameterToken;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -104,29 +101,25 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
|||||||
|
|
||||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||||
if (StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||||
|
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||||
throw new OAuth2AuthenticationException(error);
|
throw new OAuth2AuthenticationException(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matcher.group("token");
|
return matcher.group("token");
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String resolveFromRequestParameters(HttpServletRequest request) {
|
private static String resolveFromRequestParameters(HttpServletRequest request) {
|
||||||
String[] values = request.getParameterValues("access_token");
|
String[] values = request.getParameterValues("access_token");
|
||||||
if (values == null || values.length == 0) {
|
if (values == null || values.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.length == 1) {
|
if (values.length == 1) {
|
||||||
return values[0];
|
return values[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
|
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
|
||||||
throw new OAuth2AuthenticationException(error);
|
throw new OAuth2AuthenticationException(error);
|
||||||
}
|
}
|
||||||
|
@ -59,22 +59,17 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler
|
|||||||
@Override
|
@Override
|
||||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||||
AccessDeniedException accessDeniedException) {
|
AccessDeniedException accessDeniedException) {
|
||||||
|
|
||||||
Map<String, String> parameters = new LinkedHashMap<>();
|
Map<String, String> parameters = new LinkedHashMap<>();
|
||||||
|
|
||||||
if (this.realmName != null) {
|
if (this.realmName != null) {
|
||||||
parameters.put("realm", this.realmName);
|
parameters.put("realm", this.realmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.getUserPrincipal() instanceof AbstractOAuth2TokenAuthenticationToken) {
|
if (request.getUserPrincipal() instanceof AbstractOAuth2TokenAuthenticationToken) {
|
||||||
parameters.put("error", BearerTokenErrorCodes.INSUFFICIENT_SCOPE);
|
parameters.put("error", BearerTokenErrorCodes.INSUFFICIENT_SCOPE);
|
||||||
parameters.put("error_description",
|
parameters.put("error_description",
|
||||||
"The request requires higher privileges than provided by the access token.");
|
"The request requires higher privileges than provided by the access token.");
|
||||||
parameters.put("error_uri", "https://tools.ietf.org/html/rfc6750#section-3.1");
|
parameters.put("error_uri", "https://tools.ietf.org/html/rfc6750#section-3.1");
|
||||||
}
|
}
|
||||||
|
|
||||||
String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
|
String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
|
||||||
|
|
||||||
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
|
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
|
||||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||||
}
|
}
|
||||||
@ -90,20 +85,17 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler
|
|||||||
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
|
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
|
||||||
StringBuilder wwwAuthenticate = new StringBuilder();
|
StringBuilder wwwAuthenticate = new StringBuilder();
|
||||||
wwwAuthenticate.append("Bearer");
|
wwwAuthenticate.append("Bearer");
|
||||||
|
|
||||||
if (!parameters.isEmpty()) {
|
if (!parameters.isEmpty()) {
|
||||||
wwwAuthenticate.append(" ");
|
wwwAuthenticate.append(" ");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||||
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
||||||
|
|
||||||
if (i != parameters.size() - 1) {
|
if (i != parameters.size() - 1) {
|
||||||
wwwAuthenticate.append(", ");
|
wwwAuthenticate.append(", ");
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wwwAuthenticate.toString();
|
return wwwAuthenticate.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,13 +55,10 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
|
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
|
||||||
|
|
||||||
Map<String, String> parameters = new LinkedHashMap<>();
|
Map<String, String> parameters = new LinkedHashMap<>();
|
||||||
|
|
||||||
if (this.realmName != null) {
|
if (this.realmName != null) {
|
||||||
parameters.put("realm", this.realmName);
|
parameters.put("realm", this.realmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return exchange.getPrincipal().filter(AbstractOAuth2TokenAuthenticationToken.class::isInstance)
|
return exchange.getPrincipal().filter(AbstractOAuth2TokenAuthenticationToken.class::isInstance)
|
||||||
.map((token) -> errorMessageParameters(parameters)).switchIfEmpty(Mono.just(parameters))
|
.map((token) -> errorMessageParameters(parameters)).switchIfEmpty(Mono.just(parameters))
|
||||||
.flatMap((params) -> respond(exchange, params));
|
.flatMap((params) -> respond(exchange, params));
|
||||||
@ -80,7 +77,6 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH
|
|||||||
parameters.put("error_description",
|
parameters.put("error_description",
|
||||||
"The request requires higher privileges than provided by the access token.");
|
"The request requires higher privileges than provided by the access token.");
|
||||||
parameters.put("error_uri", "https://tools.ietf.org/html/rfc6750#section-3.1");
|
parameters.put("error_uri", "https://tools.ietf.org/html/rfc6750#section-3.1");
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +101,6 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wwwAuthenticate.toString();
|
return wwwAuthenticate.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +51,6 @@ import org.springframework.web.reactive.function.client.ExchangeFunction;
|
|||||||
*/
|
*/
|
||||||
public final class ServerBearerExchangeFilterFunction implements ExchangeFilterFunction {
|
public final class ServerBearerExchangeFilterFunction implements ExchangeFilterFunction {
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
||||||
return oauth2Token().map((token) -> bearer(request, token)).defaultIfEmpty(request).flatMap(next::exchange);
|
return oauth2Token().map((token) -> bearer(request, token)).defaultIfEmpty(request).flatMap(next::exchange);
|
||||||
|
@ -62,9 +62,6 @@ public final class ServletBearerExchangeFilterFunction implements ExchangeFilter
|
|||||||
|
|
||||||
static final String SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES";
|
static final String SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES";
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
||||||
return oauth2Token().map((token) -> bearer(request, token)).defaultIfEmpty(request).flatMap(next::exchange);
|
return oauth2Token().map((token) -> bearer(request, token)).defaultIfEmpty(request).flatMap(next::exchange);
|
||||||
|
@ -59,7 +59,6 @@ public final class BearerTokenServerAuthenticationEntryPoint implements ServerAu
|
|||||||
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException authException) {
|
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException authException) {
|
||||||
return Mono.defer(() -> {
|
return Mono.defer(() -> {
|
||||||
HttpStatus status = getStatus(authException);
|
HttpStatus status = getStatus(authException);
|
||||||
|
|
||||||
Map<String, String> parameters = createParameters(authException);
|
Map<String, String> parameters = createParameters(authException);
|
||||||
String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
|
String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters);
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
@ -74,23 +73,17 @@ public final class BearerTokenServerAuthenticationEntryPoint implements ServerAu
|
|||||||
if (this.realmName != null) {
|
if (this.realmName != null) {
|
||||||
parameters.put("realm", this.realmName);
|
parameters.put("realm", this.realmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authException instanceof OAuth2AuthenticationException) {
|
if (authException instanceof OAuth2AuthenticationException) {
|
||||||
OAuth2Error error = ((OAuth2AuthenticationException) authException).getError();
|
OAuth2Error error = ((OAuth2AuthenticationException) authException).getError();
|
||||||
|
|
||||||
parameters.put("error", error.getErrorCode());
|
parameters.put("error", error.getErrorCode());
|
||||||
|
|
||||||
if (StringUtils.hasText(error.getDescription())) {
|
if (StringUtils.hasText(error.getDescription())) {
|
||||||
parameters.put("error_description", error.getDescription());
|
parameters.put("error_description", error.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.hasText(error.getUri())) {
|
if (StringUtils.hasText(error.getUri())) {
|
||||||
parameters.put("error_uri", error.getUri());
|
parameters.put("error_uri", error.getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof BearerTokenError) {
|
if (error instanceof BearerTokenError) {
|
||||||
BearerTokenError bearerTokenError = (BearerTokenError) error;
|
BearerTokenError bearerTokenError = (BearerTokenError) error;
|
||||||
|
|
||||||
if (StringUtils.hasText(bearerTokenError.getScope())) {
|
if (StringUtils.hasText(bearerTokenError.getScope())) {
|
||||||
parameters.put("scope", bearerTokenError.getScope());
|
parameters.put("scope", bearerTokenError.getScope());
|
||||||
}
|
}
|
||||||
@ -112,7 +105,6 @@ public final class BearerTokenServerAuthenticationEntryPoint implements ServerAu
|
|||||||
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
|
private static String computeWWWAuthenticateHeaderValue(Map<String, String> parameters) {
|
||||||
StringBuilder wwwAuthenticate = new StringBuilder();
|
StringBuilder wwwAuthenticate = new StringBuilder();
|
||||||
wwwAuthenticate.append("Bearer");
|
wwwAuthenticate.append("Bearer");
|
||||||
|
|
||||||
if (!parameters.isEmpty()) {
|
if (!parameters.isEmpty()) {
|
||||||
wwwAuthenticate.append(" ");
|
wwwAuthenticate.append(" ");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -124,7 +116,6 @@ public final class BearerTokenServerAuthenticationEntryPoint implements ServerAu
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wwwAuthenticate.toString();
|
return wwwAuthenticate.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
|
|||||||
}
|
}
|
||||||
return authorizationHeaderToken;
|
return authorizationHeaderToken;
|
||||||
}
|
}
|
||||||
else if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
|
if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
|
||||||
return parameterToken;
|
return parameterToken;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -107,18 +107,16 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
|
|||||||
|
|
||||||
private String resolveFromAuthorizationHeader(HttpHeaders headers) {
|
private String resolveFromAuthorizationHeader(HttpHeaders headers) {
|
||||||
String authorization = headers.getFirst(this.bearerTokenHeaderName);
|
String authorization = headers.getFirst(this.bearerTokenHeaderName);
|
||||||
if (StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||||
|
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
BearerTokenError error = invalidTokenError();
|
BearerTokenError error = invalidTokenError();
|
||||||
throw new OAuth2AuthenticationException(error);
|
throw new OAuth2AuthenticationException(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matcher.group("token");
|
return matcher.group("token");
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BearerTokenError invalidTokenError() {
|
private static BearerTokenError invalidTokenError() {
|
||||||
return BearerTokenErrors.invalidToken("Bearer token is malformed");
|
return BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user