Add BearerTokenErrors

Fixes gh-7823
This commit is contained in:
Josh Cummings 2020-01-13 16:01:31 -07:00
parent 187c76e610
commit 7b2fcd17f5
No known key found for this signature in database
GPG Key ID: 49EF60DD7FF83443
2 changed files with 187 additions and 0 deletions

View File

@ -0,0 +1,95 @@
/*
* Copyright 2002-2020 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
*
* https://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;
import org.springframework.http.HttpStatus;
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INSUFFICIENT_SCOPE;
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_REQUEST;
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_TOKEN;
/**
* A factory for creating {@link BearerTokenError} instances that correspond to the registered
* <a href="https://tools.ietf.org/html/rfc6750#section-3.1">Bearer Token Error Codes</a>.
*
* @author Josh Cummings
* @since 5.3
*/
public final class BearerTokenErrors {
private static final BearerTokenError DEFAULT_INVALID_REQUEST = invalidRequest("Invalid request");
private static final BearerTokenError DEFAULT_INVALID_TOKEN = invalidToken("Invalid token");
private static final BearerTokenError DEFAULT_INSUFFICIENT_SCOPE = insufficientScope("Insufficient scope", null);
private static final String DEFAULT_URI = "https://tools.ietf.org/html/rfc6750#section-3.1";
/**
* Create a {@link BearerTokenError} caused by an invalid request
*
* @param message a description of the error
* @return a {@link BearerTokenError}
*/
public static BearerTokenError invalidRequest(String message) {
try {
return new BearerTokenError(INVALID_REQUEST,
HttpStatus.BAD_REQUEST,
message,
DEFAULT_URI);
} catch (IllegalArgumentException malformed) {
// some third-party library error messages are not suitable for RFC 6750's error message charset
return DEFAULT_INVALID_REQUEST;
}
}
/**
* Create a {@link BearerTokenError} caused by an invalid token
*
* @param message a description of the error
* @return a {@link BearerTokenError}
*/
public static BearerTokenError invalidToken(String message) {
try {
return new BearerTokenError(INVALID_TOKEN,
HttpStatus.UNAUTHORIZED,
message,
DEFAULT_URI);
} catch (IllegalArgumentException malformed) {
// some third-party library error messages are not suitable for RFC 6750's error message charset
return DEFAULT_INVALID_TOKEN;
}
}
/**
* Create a {@link BearerTokenError} caused by an invalid token
*
* @param scope the scope attribute to use in the error
* @return a {@link BearerTokenError}
*/
public static BearerTokenError insufficientScope(String message, String scope) {
try {
return new BearerTokenError(INSUFFICIENT_SCOPE,
HttpStatus.FORBIDDEN,
message,
DEFAULT_URI,
scope);
} catch (IllegalArgumentException malformed) {
// some third-party library error messages are not suitable for RFC 6750's error message charset
return DEFAULT_INSUFFICIENT_SCOPE;
}
}
private BearerTokenErrors() {}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2002-2020 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
*
* https://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;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INSUFFICIENT_SCOPE;
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_REQUEST;
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_TOKEN;
public class BearerTokenErrorsTests {
@Test
public void invalidRequestWhenMessageGivenThenBearerTokenErrorReturned() {
String message = "message";
BearerTokenError error = BearerTokenErrors.invalidRequest(message);
assertThat(error.getErrorCode()).isSameAs(INVALID_REQUEST);
assertThat(error.getDescription()).isSameAs(message);
assertThat(error.getHttpStatus()).isSameAs(BAD_REQUEST);
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
}
@Test
public void invalidRequestWhenInvalidMessageGivenThenDefaultBearerTokenErrorReturned() {
String message = "has \"invalid\" chars";
BearerTokenError error = BearerTokenErrors.invalidRequest(message);
assertThat(error.getErrorCode()).isSameAs(INVALID_REQUEST);
assertThat(error.getDescription()).isEqualTo("Invalid request");
assertThat(error.getHttpStatus()).isSameAs(BAD_REQUEST);
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
}
@Test
public void invalidTokenWhenMessageGivenThenBearerTokenErrorReturned() {
String message = "message";
BearerTokenError error = BearerTokenErrors.invalidToken(message);
assertThat(error.getErrorCode()).isSameAs(INVALID_TOKEN);
assertThat(error.getDescription()).isSameAs(message);
assertThat(error.getHttpStatus()).isSameAs(UNAUTHORIZED);
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
}
@Test
public void invalidTokenWhenInvalidMessageGivenThenDefaultBearerTokenErrorReturned() {
String message = "has \"invalid\" chars";
BearerTokenError error = BearerTokenErrors.invalidToken(message);
assertThat(error.getErrorCode()).isSameAs(INVALID_TOKEN);
assertThat(error.getDescription()).isEqualTo("Invalid token");
assertThat(error.getHttpStatus()).isSameAs(UNAUTHORIZED);
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
}
@Test
public void insufficientScopeWhenMessageGivenThenBearerTokenErrorReturned() {
String message = "message";
String scope = "scope";
BearerTokenError error = BearerTokenErrors.insufficientScope(message, scope);
assertThat(error.getErrorCode()).isSameAs(INSUFFICIENT_SCOPE);
assertThat(error.getDescription()).isSameAs(message);
assertThat(error.getHttpStatus()).isSameAs(FORBIDDEN);
assertThat(error.getScope()).isSameAs(scope);
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
}
@Test
public void insufficientScopeWhenInvalidMessageGivenThenDefaultBearerTokenErrorReturned() {
String message = "has \"invalid\" chars";
BearerTokenError error = BearerTokenErrors.insufficientScope(message, "scope");
assertThat(error.getErrorCode()).isSameAs(INSUFFICIENT_SCOPE);
assertThat(error.getDescription()).isSameAs("Insufficient scope");
assertThat(error.getHttpStatus()).isSameAs(FORBIDDEN);
assertThat(error.getScope()).isNull();
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
}
}