Skip to content

Commit 57db8e5

Browse files
schnapsterjgrandja
authored andcommitted
Add OAuth2AuthenticationException to allowlist
Add mixins for - OAuth2AuthenticationException - OAuth2Error Closes gh-8797
1 parent 5d8bac1 commit 57db8e5

File tree

4 files changed

+241
-0
lines changed

4 files changed

+241
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
package org.springframework.security.oauth2.client.jackson2;
17+
18+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
19+
import com.fasterxml.jackson.annotation.JsonCreator;
20+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
21+
import com.fasterxml.jackson.annotation.JsonProperty;
22+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
23+
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
24+
import org.springframework.security.oauth2.core.OAuth2Error;
25+
26+
/**
27+
* This mixin class is used to serialize/deserialize
28+
* {@link OAuth2AuthenticationException}.
29+
*
30+
* @author Dennis Neufeld
31+
* @since 5.3.4
32+
* @see OAuth2AuthenticationException
33+
* @see OAuth2ClientJackson2Module
34+
*/
35+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
36+
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
37+
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
38+
@JsonIgnoreProperties(ignoreUnknown = true, value = {"cause", "stackTrace", "suppressedExceptions"})
39+
abstract class OAuth2AuthenticationExceptionMixin {
40+
41+
@JsonCreator
42+
OAuth2AuthenticationExceptionMixin(
43+
@JsonProperty("error") OAuth2Error error,
44+
@JsonProperty("detailMessage") String message) {
45+
}
46+
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ClientJackson2Module.java

+8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
2323
import org.springframework.security.oauth2.client.registration.ClientRegistration;
2424
import org.springframework.security.oauth2.core.OAuth2AccessToken;
25+
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
26+
import org.springframework.security.oauth2.core.OAuth2Error;
2527
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
2628
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
2729
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
@@ -50,6 +52,8 @@
5052
* <li>{@link OidcUserAuthorityMixin}</li>
5153
* <li>{@link DefaultOidcUserMixin}</li>
5254
* <li>{@link OAuth2AuthenticationTokenMixin}</li>
55+
* <li>{@link OAuth2AuthenticationExceptionMixin}</li>
56+
* <li>{@link OAuth2ErrorMixin}</li>
5357
* </ul>
5458
*
5559
* If not already enabled, default typing will be automatically enabled
@@ -78,6 +82,8 @@
7882
* @see OidcUserAuthorityMixin
7983
* @see DefaultOidcUserMixin
8084
* @see OAuth2AuthenticationTokenMixin
85+
* @see OAuth2AuthenticationExceptionMixin
86+
* @see OAuth2ErrorMixin
8187
*/
8288
public class OAuth2ClientJackson2Module extends SimpleModule {
8389

@@ -101,5 +107,7 @@ public void setupModule(SetupContext context) {
101107
context.setMixInAnnotations(OidcUserAuthority.class, OidcUserAuthorityMixin.class);
102108
context.setMixInAnnotations(DefaultOidcUser.class, DefaultOidcUserMixin.class);
103109
context.setMixInAnnotations(OAuth2AuthenticationToken.class, OAuth2AuthenticationTokenMixin.class);
110+
context.setMixInAnnotations(OAuth2AuthenticationException.class, OAuth2AuthenticationExceptionMixin.class);
111+
context.setMixInAnnotations(OAuth2Error.class, OAuth2ErrorMixin.class);
104112
}
105113
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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+
package org.springframework.security.oauth2.client.jackson2;
17+
18+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
19+
import com.fasterxml.jackson.annotation.JsonCreator;
20+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
21+
import com.fasterxml.jackson.annotation.JsonProperty;
22+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
23+
import org.springframework.security.oauth2.core.OAuth2Error;
24+
25+
/**
26+
* This mixin class is used to serialize/deserialize {@link OAuth2Error} as part of
27+
* {@link org.springframework.security.oauth2.core.OAuth2AuthenticationException}.
28+
*
29+
* @author Dennis Neufeld
30+
* @since 5.3.4
31+
* @see OAuth2Error
32+
* @see OAuth2AuthenticationExceptionMixin
33+
* @see OAuth2ClientJackson2Module
34+
*/
35+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
36+
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
37+
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
38+
@JsonIgnoreProperties(ignoreUnknown = true)
39+
abstract class OAuth2ErrorMixin {
40+
41+
@JsonCreator
42+
OAuth2ErrorMixin(
43+
@JsonProperty("errorCode") String errorCode,
44+
@JsonProperty("description") String description,
45+
@JsonProperty("uri") String uri) {
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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+
package org.springframework.security.oauth2.client.jackson2;
17+
18+
import com.fasterxml.jackson.core.JsonProcessingException;
19+
import com.fasterxml.jackson.databind.ObjectMapper;
20+
import org.junit.Before;
21+
import org.junit.Test;
22+
import org.skyscreamer.jsonassert.JSONAssert;
23+
import org.springframework.security.jackson2.SecurityJackson2Modules;
24+
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
25+
import org.springframework.security.oauth2.core.OAuth2Error;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
29+
30+
/**
31+
* Tests for {@link OAuth2AuthenticationExceptionMixin}.
32+
*
33+
* @author Dennis Neufeld
34+
* @since 5.3.4
35+
*/
36+
public class OAuth2AuthenticationExceptionMixinTests {
37+
38+
private ObjectMapper mapper;
39+
40+
@Before
41+
public void setup() {
42+
ClassLoader loader = getClass().getClassLoader();
43+
this.mapper = new ObjectMapper();
44+
this.mapper.registerModules(SecurityJackson2Modules.getModules(loader));
45+
}
46+
47+
@Test
48+
public void serializeWhenMixinRegisteredThenSerializes() throws Exception {
49+
OAuth2AuthenticationException exception = new OAuth2AuthenticationException(new OAuth2Error(
50+
"[authorization_request_not_found]",
51+
"Authorization Request Not Found",
52+
"/foo/bar"
53+
), "Authorization Request Not Found");
54+
55+
String serializedJson = this.mapper.writeValueAsString(exception);
56+
String expected = asJson(exception);
57+
JSONAssert.assertEquals(expected, serializedJson, true);
58+
}
59+
60+
@Test
61+
public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception {
62+
OAuth2AuthenticationException exception = new OAuth2AuthenticationException(
63+
new OAuth2Error("[authorization_request_not_found]")
64+
);
65+
66+
String serializedJson = this.mapper.writeValueAsString(exception);
67+
String expected = asJson(exception);
68+
JSONAssert.assertEquals(expected, serializedJson, true);
69+
}
70+
71+
@Test
72+
public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() {
73+
String json = asJson(new OAuth2AuthenticationException(
74+
new OAuth2Error("[authorization_request_not_found]")
75+
));
76+
assertThatThrownBy(() -> new ObjectMapper().readValue(json, OAuth2AuthenticationException.class))
77+
.isInstanceOf(JsonProcessingException.class);
78+
}
79+
80+
@Test
81+
public void deserializeWhenMixinRegisteredThenDeserializes() throws Exception {
82+
OAuth2AuthenticationException expected = new OAuth2AuthenticationException(new OAuth2Error(
83+
"[authorization_request_not_found]",
84+
"Authorization Request Not Found",
85+
"/foo/bar"
86+
), "Authorization Request Not Found");
87+
88+
OAuth2AuthenticationException exception = this.mapper.readValue(asJson(expected), OAuth2AuthenticationException.class);
89+
assertThat(exception).isNotNull();
90+
assertThat(exception.getCause()).isNull();
91+
assertThat(exception.getMessage()).isEqualTo(expected.getMessage());
92+
93+
OAuth2Error oauth2Error = exception.getError();
94+
assertThat(oauth2Error).isNotNull();
95+
assertThat(oauth2Error.getErrorCode()).isEqualTo(expected.getError().getErrorCode());
96+
assertThat(oauth2Error.getDescription()).isEqualTo(expected.getError().getDescription());
97+
assertThat(oauth2Error.getUri()).isEqualTo(expected.getError().getUri());
98+
}
99+
100+
@Test
101+
public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception {
102+
OAuth2AuthenticationException expected = new OAuth2AuthenticationException(
103+
new OAuth2Error("[authorization_request_not_found]")
104+
);
105+
106+
OAuth2AuthenticationException exception = this.mapper.readValue(asJson(expected), OAuth2AuthenticationException.class);
107+
assertThat(exception).isNotNull();
108+
assertThat(exception.getCause()).isNull();
109+
assertThat(exception.getMessage()).isNull();
110+
111+
OAuth2Error oauth2Error = exception.getError();
112+
assertThat(oauth2Error).isNotNull();
113+
assertThat(oauth2Error.getErrorCode()).isEqualTo(expected.getError().getErrorCode());
114+
assertThat(oauth2Error.getDescription()).isNull();
115+
assertThat(oauth2Error.getUri()).isNull();
116+
}
117+
118+
private String asJson(OAuth2AuthenticationException exception) {
119+
OAuth2Error error = exception.getError();
120+
// @formatter:off
121+
return "\n{"
122+
+ "\n \"@class\": \"org.springframework.security.oauth2.core.OAuth2AuthenticationException\","
123+
+ "\n \"error\":"
124+
+ "\n {"
125+
+ "\n \"@class\":\"org.springframework.security.oauth2.core.OAuth2Error\","
126+
+ "\n \"errorCode\":\"" + error.getErrorCode() + "\","
127+
+ "\n \"description\":" + jsonStringOrNull(error.getDescription()) + ","
128+
+ "\n \"uri\":" + jsonStringOrNull(error.getUri())
129+
+ "\n },"
130+
+ "\n \"detailMessage\":" + jsonStringOrNull(exception.getMessage())
131+
+ "\n}";
132+
// @formatter:on
133+
}
134+
135+
private String jsonStringOrNull(String input) {
136+
return input != null
137+
? "\"" + input + "\""
138+
: "null";
139+
}
140+
}

0 commit comments

Comments
 (0)