Skip to content

Commit

Permalink
Improve Bearer Token Error Handling
Browse files Browse the repository at this point in the history
Expired tokens now report as invalid_token errors. Also, when a token
is specified in more than one way, then the code reports an
invalid_request error. Finally, when the token contains invalid
characters, an invalid_token error is returned.

Issue: gh-3
Issue: gh-4
  • Loading branch information
jzheaux committed Jun 25, 2018
1 parent 1ab74af commit 6e0b6e7
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public final class BearerTokenError extends OAuth2Error {
* @param errorCode the error code
* @param httpStatus the HTTP status
*/
public BearerTokenError(String errorCode, HttpStatus httpStatus) {
this(errorCode, httpStatus, null, null, null);
public BearerTokenError(String errorCode, HttpStatus httpStatus, String description, String errorUri) {
this(errorCode, httpStatus, description, errorUri, null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@
*/
package org.springframework.security.oauth2.server.resource.authentication;

import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthoritiesPopulator;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtException;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import org.springframework.security.oauth2.server.resource.BearerTokenError;
import org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes;
import org.springframework.util.Assert;

/**
Expand Down Expand Up @@ -61,7 +63,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
try {
jwt = this.jwtDecoder.decode(bearer.getToken());
} catch (JwtException failed) {
OAuth2Error invalidRequest = invalidRequest(failed.getMessage());
OAuth2Error invalidRequest = invalidToken(failed.getMessage());
throw new OAuth2AuthenticationException(invalidRequest, failed);
}

Expand All @@ -85,11 +87,11 @@ public void setAuthoritiesPopulator(OAuth2AuthoritiesPopulator authoritiesPopula
this.authoritiesPopulator = authoritiesPopulator;
}

private static OAuth2Error invalidRequest(String message) {
return new OAuth2Error(
OAuth2ErrorCodes.INVALID_REQUEST,
private static OAuth2Error invalidToken(String message) {
return new BearerTokenError(
BearerTokenErrorCodes.INVALID_TOKEN,
HttpStatus.UNAUTHORIZED,
message,
"https://tools.ietf.org/html/rfc6750#section-3.1"
);
"https://tools.ietf.org/html/rfc6750#section-3.1");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ public String resolve(HttpServletRequest request) {
if (authorizationHeaderToken != null) {
if (parameterToken != null) {
BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST,
HttpStatus.BAD_REQUEST);
HttpStatus.BAD_REQUEST,
"Found multiple bearer tokens in the request",
"https://tools.ietf.org/html/rfc6750#section-3.1");
throw new OAuth2AuthenticationException(error);
}
return authorizationHeaderToken;
Expand Down Expand Up @@ -86,8 +88,10 @@ private static String resolveFromAuthorizationHeader(HttpServletRequest request)
Matcher matcher = authorizationPattern.matcher(authorization);

if ( !matcher.matches() ) {
BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST,
HttpStatus.BAD_REQUEST);
BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN,
HttpStatus.BAD_REQUEST,
"Bearer token is malformed",
"https://tools.ietf.org/html/rfc6750#section-3.1");
throw new OAuth2AuthenticationException(error);
}

Expand All @@ -100,5 +104,4 @@ private boolean isParameterTokenSupportedForRequest(HttpServletRequest request)
return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod()))
|| (this.allowUriQueryParameter && "GET".equals(request.getMethod())));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public void performWhenMalformedBearerTokenThenUnauthorized()
this.mvc.perform(get("/").with(bearerToken("malformed")))
.andExpect(status().isUnauthorized())
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE,
containsString("Bearer error=\"invalid_request\", " +
containsString("Bearer error=\"invalid_token\", " +
"error_description=\"An error occurred while attempting to decode the Jwt: " +
"Invalid JWT serialization: Missing dot delimiter(s)\"")));
}
Expand Down

0 comments on commit 6e0b6e7

Please sign in to comment.