Skip to content

Commit 7b2fcd1

Browse files
committed
Add BearerTokenErrors
Fixes gh-7823
1 parent 187c76e commit 7b2fcd1

File tree

2 files changed

+187
-0
lines changed

2 files changed

+187
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright 2002-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.oauth2.server.resource;
18+
19+
import org.springframework.http.HttpStatus;
20+
21+
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INSUFFICIENT_SCOPE;
22+
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_REQUEST;
23+
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_TOKEN;
24+
25+
/**
26+
* A factory for creating {@link BearerTokenError} instances that correspond to the registered
27+
* <a href="https://tools.ietf.org/html/rfc6750#section-3.1">Bearer Token Error Codes</a>.
28+
*
29+
* @author Josh Cummings
30+
* @since 5.3
31+
*/
32+
public final class BearerTokenErrors {
33+
private static final BearerTokenError DEFAULT_INVALID_REQUEST = invalidRequest("Invalid request");
34+
private static final BearerTokenError DEFAULT_INVALID_TOKEN = invalidToken("Invalid token");
35+
private static final BearerTokenError DEFAULT_INSUFFICIENT_SCOPE = insufficientScope("Insufficient scope", null);
36+
37+
private static final String DEFAULT_URI = "https://tools.ietf.org/html/rfc6750#section-3.1";
38+
39+
/**
40+
* Create a {@link BearerTokenError} caused by an invalid request
41+
*
42+
* @param message a description of the error
43+
* @return a {@link BearerTokenError}
44+
*/
45+
public static BearerTokenError invalidRequest(String message) {
46+
try {
47+
return new BearerTokenError(INVALID_REQUEST,
48+
HttpStatus.BAD_REQUEST,
49+
message,
50+
DEFAULT_URI);
51+
} catch (IllegalArgumentException malformed) {
52+
// some third-party library error messages are not suitable for RFC 6750's error message charset
53+
return DEFAULT_INVALID_REQUEST;
54+
}
55+
}
56+
57+
/**
58+
* Create a {@link BearerTokenError} caused by an invalid token
59+
*
60+
* @param message a description of the error
61+
* @return a {@link BearerTokenError}
62+
*/
63+
public static BearerTokenError invalidToken(String message) {
64+
try {
65+
return new BearerTokenError(INVALID_TOKEN,
66+
HttpStatus.UNAUTHORIZED,
67+
message,
68+
DEFAULT_URI);
69+
} catch (IllegalArgumentException malformed) {
70+
// some third-party library error messages are not suitable for RFC 6750's error message charset
71+
return DEFAULT_INVALID_TOKEN;
72+
}
73+
}
74+
75+
/**
76+
* Create a {@link BearerTokenError} caused by an invalid token
77+
*
78+
* @param scope the scope attribute to use in the error
79+
* @return a {@link BearerTokenError}
80+
*/
81+
public static BearerTokenError insufficientScope(String message, String scope) {
82+
try {
83+
return new BearerTokenError(INSUFFICIENT_SCOPE,
84+
HttpStatus.FORBIDDEN,
85+
message,
86+
DEFAULT_URI,
87+
scope);
88+
} catch (IllegalArgumentException malformed) {
89+
// some third-party library error messages are not suitable for RFC 6750's error message charset
90+
return DEFAULT_INSUFFICIENT_SCOPE;
91+
}
92+
}
93+
94+
private BearerTokenErrors() {}
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2002-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.oauth2.server.resource;
18+
19+
import org.junit.Test;
20+
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
import static org.springframework.http.HttpStatus.BAD_REQUEST;
23+
import static org.springframework.http.HttpStatus.FORBIDDEN;
24+
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
25+
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INSUFFICIENT_SCOPE;
26+
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_REQUEST;
27+
import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_TOKEN;
28+
29+
public class BearerTokenErrorsTests {
30+
@Test
31+
public void invalidRequestWhenMessageGivenThenBearerTokenErrorReturned() {
32+
String message = "message";
33+
BearerTokenError error = BearerTokenErrors.invalidRequest(message);
34+
assertThat(error.getErrorCode()).isSameAs(INVALID_REQUEST);
35+
assertThat(error.getDescription()).isSameAs(message);
36+
assertThat(error.getHttpStatus()).isSameAs(BAD_REQUEST);
37+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
38+
}
39+
40+
@Test
41+
public void invalidRequestWhenInvalidMessageGivenThenDefaultBearerTokenErrorReturned() {
42+
String message = "has \"invalid\" chars";
43+
BearerTokenError error = BearerTokenErrors.invalidRequest(message);
44+
assertThat(error.getErrorCode()).isSameAs(INVALID_REQUEST);
45+
assertThat(error.getDescription()).isEqualTo("Invalid request");
46+
assertThat(error.getHttpStatus()).isSameAs(BAD_REQUEST);
47+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
48+
}
49+
50+
@Test
51+
public void invalidTokenWhenMessageGivenThenBearerTokenErrorReturned() {
52+
String message = "message";
53+
BearerTokenError error = BearerTokenErrors.invalidToken(message);
54+
assertThat(error.getErrorCode()).isSameAs(INVALID_TOKEN);
55+
assertThat(error.getDescription()).isSameAs(message);
56+
assertThat(error.getHttpStatus()).isSameAs(UNAUTHORIZED);
57+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
58+
}
59+
60+
@Test
61+
public void invalidTokenWhenInvalidMessageGivenThenDefaultBearerTokenErrorReturned() {
62+
String message = "has \"invalid\" chars";
63+
BearerTokenError error = BearerTokenErrors.invalidToken(message);
64+
assertThat(error.getErrorCode()).isSameAs(INVALID_TOKEN);
65+
assertThat(error.getDescription()).isEqualTo("Invalid token");
66+
assertThat(error.getHttpStatus()).isSameAs(UNAUTHORIZED);
67+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
68+
}
69+
70+
@Test
71+
public void insufficientScopeWhenMessageGivenThenBearerTokenErrorReturned() {
72+
String message = "message";
73+
String scope = "scope";
74+
BearerTokenError error = BearerTokenErrors.insufficientScope(message, scope);
75+
assertThat(error.getErrorCode()).isSameAs(INSUFFICIENT_SCOPE);
76+
assertThat(error.getDescription()).isSameAs(message);
77+
assertThat(error.getHttpStatus()).isSameAs(FORBIDDEN);
78+
assertThat(error.getScope()).isSameAs(scope);
79+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
80+
}
81+
82+
@Test
83+
public void insufficientScopeWhenInvalidMessageGivenThenDefaultBearerTokenErrorReturned() {
84+
String message = "has \"invalid\" chars";
85+
BearerTokenError error = BearerTokenErrors.insufficientScope(message, "scope");
86+
assertThat(error.getErrorCode()).isSameAs(INSUFFICIENT_SCOPE);
87+
assertThat(error.getDescription()).isSameAs("Insufficient scope");
88+
assertThat(error.getHttpStatus()).isSameAs(FORBIDDEN);
89+
assertThat(error.getScope()).isNull();
90+
assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1");
91+
}
92+
}

0 commit comments

Comments
 (0)