Skip to content

Commit ef859a3

Browse files
committed
Add tests for Token Exchange
Issue gh-60
1 parent 2f1f45b commit ef859a3

9 files changed

+1871
-4
lines changed

Diff for: oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/TestOAuth2Authorizations.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
3131
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
3232
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
33+
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
3334
import org.springframework.util.CollectionUtils;
3435

3536
/**
@@ -92,15 +93,17 @@ private static OAuth2Authorization.Builder authorization(RegisteredClient regist
9293
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken(
9394
"refresh-token", Instant.now(), Instant.now().plus(1, ChronoUnit.HOURS));
9495
builder
95-
.token(accessToken, (metadata) -> metadata.putAll(tokenMetadata(accessTokenClaims)))
96+
.token(accessToken, (metadata) -> metadata.putAll(tokenMetadata(registeredClient, accessTokenClaims)))
9697
.refreshToken(refreshToken);
9798
}
9899

99100
return builder;
100101
}
101102

102-
private static Map<String, Object> tokenMetadata(Map<String, Object> tokenClaims) {
103+
private static Map<String, Object> tokenMetadata(RegisteredClient registeredClient, Map<String, Object> tokenClaims) {
103104
Map<String, Object> tokenMetadata = new HashMap<>();
105+
OAuth2TokenFormat accessTokenFormat = registeredClient.getTokenSettings().getAccessTokenFormat();
106+
tokenMetadata.put(OAuth2TokenFormat.class.getName(), accessTokenFormat.getValue());
104107
tokenMetadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, false);
105108
if (CollectionUtils.isEmpty(tokenClaims)) {
106109
tokenClaims = defaultTokenClaims();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2020-2024 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.server.authorization.authentication;
17+
18+
import java.util.Map;
19+
20+
import org.junit.jupiter.api.Test;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
24+
25+
/**
26+
* Tests for {@link OAuth2TokenExchangeActor}.
27+
*
28+
* @author Steve Riesenberg
29+
*/
30+
public class OAuth2TokenExchangeActorTests {
31+
32+
@Test
33+
public void constructorWhenClaimsNullThenThrowIllegalArgumentException() {
34+
// @formatter:off
35+
assertThatIllegalArgumentException()
36+
.isThrownBy(() -> new OAuth2TokenExchangeActor(null))
37+
.withMessage("claims cannot be null");
38+
// @formatter:on
39+
}
40+
41+
@Test
42+
public void constructorWhenRequiredParametersThenCreated() {
43+
Map<String, Object> claims = Map.of("claim1", "value1");
44+
OAuth2TokenExchangeActor actor = new OAuth2TokenExchangeActor(claims);
45+
assertThat(actor.getClaims()).isEqualTo(claims);
46+
}
47+
48+
}

Diff for: oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProviderTests.java

+702
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright 2020-2024 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.server.authorization.authentication;
17+
18+
import java.util.Collections;
19+
import java.util.Map;
20+
import java.util.Set;
21+
22+
import org.junit.jupiter.api.Test;
23+
24+
import org.springframework.security.oauth2.core.AuthorizationGrantType;
25+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
26+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
27+
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
31+
32+
/**
33+
* Tests for {@link OAuth2TokenExchangeAuthenticationToken}.
34+
*
35+
* @author Steve Riesenberg
36+
*/
37+
public class OAuth2TokenExchangeAuthenticationTokenTests {
38+
private static final Set<String> RESOURCES = Set.of("https://mydomain.com/resource1", "https://mydomain.com/resource2");
39+
private static final Set<String> AUDIENCES = Set.of("audience1", "audience2");
40+
private static final String SUBJECT_TOKEN = "EfYu_0jEL";
41+
private static final String ACTOR_TOKEN = "JlNE_xR1f";
42+
private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token";
43+
private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt";
44+
45+
private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
46+
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
47+
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
48+
private Set<String> scopes = Collections.singleton("scope1");
49+
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
50+
51+
@Test
52+
public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() {
53+
// @formatter:off
54+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken(null, null, null, null, null, null, null, null, null, this.additionalParameters))
55+
.isInstanceOf(IllegalArgumentException.class)
56+
.hasMessage("clientPrincipal cannot be null");
57+
// @formatter:on
58+
}
59+
60+
@Test
61+
public void constructorWhenRequestedTokenTypeNullOrEmptyThenThrowIllegalArgumentException() {
62+
// @formatter:off
63+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken(null, null, null, this.clientPrincipal, null, null, null, null, null, this.additionalParameters))
64+
.isInstanceOf(IllegalArgumentException.class)
65+
.hasMessage("requestedTokenType cannot be empty");
66+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken("", null, null, this.clientPrincipal, null, null, null, null, null, this.additionalParameters))
67+
.isInstanceOf(IllegalArgumentException.class)
68+
.hasMessage("requestedTokenType cannot be empty");
69+
// @formatter:on
70+
}
71+
72+
@Test
73+
public void constructorWhenSubjectTokenNullOrEmptyThenThrowIllegalArgumentException() {
74+
// @formatter:off
75+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken(JWT_TOKEN_TYPE_VALUE, null, null, this.clientPrincipal, null, null, null, null, this.scopes, this.additionalParameters))
76+
.isInstanceOf(IllegalArgumentException.class)
77+
.hasMessage("subjectToken cannot be empty");
78+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken(JWT_TOKEN_TYPE_VALUE, "", null, this.clientPrincipal, null, null, null, null, this.scopes, this.additionalParameters))
79+
.isInstanceOf(IllegalArgumentException.class)
80+
.hasMessage("subjectToken cannot be empty");
81+
// @formatter:on
82+
}
83+
84+
@Test
85+
public void constructorWhenSubjectTokenTypeNullOrEmptyThenThrowIllegalArgumentException() {
86+
// @formatter:off
87+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken(JWT_TOKEN_TYPE_VALUE, SUBJECT_TOKEN, null, this.clientPrincipal, null, null, null, null, this.scopes, this.additionalParameters))
88+
.isInstanceOf(IllegalArgumentException.class)
89+
.hasMessage("subjectTokenType cannot be empty");
90+
assertThatThrownBy(() -> new OAuth2TokenExchangeAuthenticationToken(JWT_TOKEN_TYPE_VALUE, SUBJECT_TOKEN, "", this.clientPrincipal, null, null, null, null, this.scopes, this.additionalParameters))
91+
.isInstanceOf(IllegalArgumentException.class)
92+
.hasMessage("subjectTokenType cannot be empty");
93+
// @formatter:on
94+
}
95+
96+
@Test
97+
public void constructorWhenRequiredParametersProvidedThenCreated() {
98+
OAuth2TokenExchangeAuthenticationToken authentication = new OAuth2TokenExchangeAuthenticationToken(
99+
JWT_TOKEN_TYPE_VALUE, SUBJECT_TOKEN, ACCESS_TOKEN_TYPE_VALUE, this.clientPrincipal, null, null, null,
100+
null, null, this.additionalParameters);
101+
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
102+
assertThat(authentication.getCredentials().toString()).isEmpty();
103+
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.TOKEN_EXCHANGE);
104+
assertThat(authentication.getRequestedTokenType()).isEqualTo(JWT_TOKEN_TYPE_VALUE);
105+
assertThat(authentication.getSubjectToken()).isEqualTo(SUBJECT_TOKEN);
106+
assertThat(authentication.getSubjectTokenType()).isEqualTo(ACCESS_TOKEN_TYPE_VALUE);
107+
assertThat(authentication.getActorToken()).isNull();
108+
assertThat(authentication.getActorTokenType()).isNull();
109+
assertThat(authentication.getResources()).isEmpty();
110+
assertThat(authentication.getAudiences()).isEmpty();
111+
assertThat(authentication.getScopes()).isEmpty();
112+
assertThat(authentication.getAdditionalParameters()).isEqualTo(this.additionalParameters);
113+
}
114+
115+
@Test
116+
public void constructorWhenAllParametersProvidedThenCreated() {
117+
OAuth2TokenExchangeAuthenticationToken authentication = new OAuth2TokenExchangeAuthenticationToken(
118+
JWT_TOKEN_TYPE_VALUE, SUBJECT_TOKEN, ACCESS_TOKEN_TYPE_VALUE, this.clientPrincipal, ACTOR_TOKEN,
119+
ACCESS_TOKEN_TYPE_VALUE, RESOURCES, AUDIENCES, this.scopes, this.additionalParameters);
120+
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
121+
assertThat(authentication.getCredentials().toString()).isEmpty();
122+
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.TOKEN_EXCHANGE);
123+
assertThat(authentication.getRequestedTokenType()).isEqualTo(JWT_TOKEN_TYPE_VALUE);
124+
assertThat(authentication.getSubjectToken()).isEqualTo(SUBJECT_TOKEN);
125+
assertThat(authentication.getSubjectTokenType()).isEqualTo(ACCESS_TOKEN_TYPE_VALUE);
126+
assertThat(authentication.getActorToken()).isEqualTo(ACTOR_TOKEN);
127+
assertThat(authentication.getActorTokenType()).isEqualTo(ACCESS_TOKEN_TYPE_VALUE);
128+
assertThat(authentication.getResources()).isEqualTo(RESOURCES);
129+
assertThat(authentication.getAudiences()).isEqualTo(AUDIENCES);
130+
assertThat(authentication.getScopes()).isEqualTo(this.scopes);
131+
assertThat(authentication.getAdditionalParameters()).isEqualTo(this.additionalParameters);
132+
}
133+
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2020-2024 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.server.authorization.authentication;
17+
18+
import java.util.List;
19+
import java.util.Map;
20+
21+
import org.junit.jupiter.api.Test;
22+
23+
import org.springframework.security.authentication.TestingAuthenticationToken;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
27+
28+
/**
29+
* Tests for {@link OAuth2TokenExchangeCompositeAuthenticationToken}.
30+
*
31+
* @author Steve Riesenberg
32+
*/
33+
public class OAuth2TokenExchangeCompositeAuthenticationTokenTests {
34+
35+
@Test
36+
public void constructorWhenSubjectNullThenThrowIllegalArgumentException() {
37+
// @formatter:off
38+
assertThatIllegalArgumentException()
39+
.isThrownBy(() -> new OAuth2TokenExchangeCompositeAuthenticationToken(null, null))
40+
.withMessage("subject cannot be null");
41+
// @formatter:on
42+
}
43+
44+
@Test
45+
public void constructorWhenActorsNullThenThrowIllegalArgumentException() {
46+
TestingAuthenticationToken subject = new TestingAuthenticationToken("subject", null);
47+
// @formatter:off
48+
assertThatIllegalArgumentException()
49+
.isThrownBy(() -> new OAuth2TokenExchangeCompositeAuthenticationToken(subject, null))
50+
.withMessage("actors cannot be null");
51+
// @formatter:on
52+
}
53+
54+
@Test
55+
public void constructorWhenRequiredParametersProvidedThenCreated() {
56+
TestingAuthenticationToken subject = new TestingAuthenticationToken("subject", null);
57+
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of("claim1", "value1"));
58+
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of("claim2", "value2"));
59+
List<OAuth2TokenExchangeActor> actors = List.of(actor1, actor2);
60+
OAuth2TokenExchangeCompositeAuthenticationToken authentication =
61+
new OAuth2TokenExchangeCompositeAuthenticationToken(subject, actors);
62+
assertThat(authentication.getSubject()).isEqualTo(subject);
63+
assertThat(authentication.getActors()).isEqualTo(actors);
64+
}
65+
66+
}

0 commit comments

Comments
 (0)