Skip to content

Commit 64b20ae

Browse files
committed
Fix package tangle
Closes gh-1615
1 parent af52849 commit 64b20ae

File tree

8 files changed

+286
-202
lines changed

8 files changed

+286
-202
lines changed
Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.security.oauth2.server.authorization.token;
16+
package org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers;
1717

1818
import java.security.MessageDigest;
1919
import java.security.cert.X509Certificate;
@@ -22,7 +22,6 @@
2222
import java.util.HashMap;
2323
import java.util.LinkedHashMap;
2424
import java.util.Map;
25-
import java.util.function.Consumer;
2625

2726
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
2827
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
@@ -32,28 +31,36 @@
3231
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
3332
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeActor;
3433
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeCompositeAuthenticationToken;
34+
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
35+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimNames;
36+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
37+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
38+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
3539

3640
/**
3741
* @author Joe Grandja
42+
* @author Steve Riesenberg
3843
* @since 1.3
3944
*/
40-
final class DefaultOAuth2TokenClaimsConsumer implements Consumer<Map<String, Object>> {
41-
private final OAuth2TokenContext context;
45+
final class DefaultOAuth2TokenCustomizers {
4246

43-
DefaultOAuth2TokenClaimsConsumer(OAuth2TokenContext context) {
44-
this.context = context;
47+
static OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
48+
return (context) -> context.getClaims().claims((claims) -> customize(context, claims));
4549
}
4650

47-
@Override
48-
public void accept(Map<String, Object> claims) {
51+
static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer() {
52+
return (context) -> context.getClaims().claims((claims) -> customize(context, claims));
53+
}
54+
55+
private static void customize(OAuth2TokenContext tokenContext, Map<String, Object> claims) {
4956
// Add 'cnf' claim for Mutual-TLS Client Certificate-Bound Access Tokens
50-
if (OAuth2TokenType.ACCESS_TOKEN.equals(this.context.getTokenType()) &&
51-
this.context.getAuthorizationGrant() != null &&
52-
this.context.getAuthorizationGrant().getPrincipal() instanceof OAuth2ClientAuthenticationToken clientAuthentication) {
57+
if (OAuth2TokenType.ACCESS_TOKEN.equals(tokenContext.getTokenType()) &&
58+
tokenContext.getAuthorizationGrant() != null &&
59+
tokenContext.getAuthorizationGrant().getPrincipal() instanceof OAuth2ClientAuthenticationToken clientAuthentication) {
5360

5461
if ((ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod()) ||
5562
ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod())) &&
56-
this.context.getRegisteredClient().getTokenSettings().isX509CertificateBoundAccessTokens()) {
63+
tokenContext.getRegisteredClient().getTokenSettings().isX509CertificateBoundAccessTokens()) {
5764

5865
X509Certificate[] clientCertificateChain = (X509Certificate[]) clientAuthentication.getCredentials();
5966
try {
@@ -71,7 +78,7 @@ public void accept(Map<String, Object> claims) {
7178

7279
// Add 'act' claim for delegation use case of Token Exchange Grant.
7380
// If more than one actor is present, we create a chain of delegation by nesting "act" claims.
74-
if (this.context.getPrincipal() instanceof OAuth2TokenExchangeCompositeAuthenticationToken compositeAuthenticationToken) {
81+
if (tokenContext.getPrincipal() instanceof OAuth2TokenExchangeCompositeAuthenticationToken compositeAuthenticationToken) {
7582
Map<String, Object> currentClaims = claims;
7683
for (OAuth2TokenExchangeActor actor : compositeAuthenticationToken.getActors()) {
7784
Map<String, Object> actorClaims = actor.getClaims();

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ConfigurerUtils.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,7 @@ static OAuth2TokenGenerator<? extends OAuth2Token> getTokenGenerator(HttpSecurit
105105
if (tokenGenerator == null) {
106106
JwtGenerator jwtGenerator = getJwtGenerator(httpSecurity);
107107
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
108-
OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer = getAccessTokenCustomizer(httpSecurity);
109-
if (accessTokenCustomizer != null) {
110-
accessTokenGenerator.setAccessTokenCustomizer(accessTokenCustomizer);
111-
}
108+
accessTokenGenerator.setAccessTokenCustomizer(getAccessTokenCustomizer(httpSecurity));
112109
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
113110
if (jwtGenerator != null) {
114111
tokenGenerator = new DelegatingOAuth2TokenGenerator(
@@ -129,10 +126,7 @@ private static JwtGenerator getJwtGenerator(HttpSecurity httpSecurity) {
129126
JwtEncoder jwtEncoder = getJwtEncoder(httpSecurity);
130127
if (jwtEncoder != null) {
131128
jwtGenerator = new JwtGenerator(jwtEncoder);
132-
OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = getJwtCustomizer(httpSecurity);
133-
if (jwtCustomizer != null) {
134-
jwtGenerator.setJwtCustomizer(jwtCustomizer);
135-
}
129+
jwtGenerator.setJwtCustomizer(getJwtCustomizer(httpSecurity));
136130
httpSecurity.setSharedObject(JwtGenerator.class, jwtGenerator);
137131
}
138132
}
@@ -170,13 +164,29 @@ static JWKSource<SecurityContext> getJwkSource(HttpSecurity httpSecurity) {
170164
}
171165

172166
private static OAuth2TokenCustomizer<JwtEncodingContext> getJwtCustomizer(HttpSecurity httpSecurity) {
167+
final OAuth2TokenCustomizer<JwtEncodingContext> defaultJwtCustomizer = DefaultOAuth2TokenCustomizers.jwtCustomizer();
173168
ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, JwtEncodingContext.class);
174-
return getOptionalBean(httpSecurity, type);
169+
final OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = getOptionalBean(httpSecurity, type);
170+
if (jwtCustomizer == null) {
171+
return defaultJwtCustomizer;
172+
}
173+
return (context) -> {
174+
defaultJwtCustomizer.customize(context);
175+
jwtCustomizer.customize(context);
176+
};
175177
}
176178

177179
private static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> getAccessTokenCustomizer(HttpSecurity httpSecurity) {
180+
final OAuth2TokenCustomizer<OAuth2TokenClaimsContext> defaultAccessTokenCustomizer = DefaultOAuth2TokenCustomizers.accessTokenCustomizer();
178181
ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, OAuth2TokenClaimsContext.class);
179-
return getOptionalBean(httpSecurity, type);
182+
OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer = getOptionalBean(httpSecurity, type);
183+
if (accessTokenCustomizer == null) {
184+
return defaultAccessTokenCustomizer;
185+
}
186+
return (context) -> {
187+
defaultAccessTokenCustomizer.customize(context);
188+
accessTokenCustomizer.customize(context);
189+
};
180190
}
181191

182192
static AuthorizationServerSettings getAuthorizationServerSettings(HttpSecurity httpSecurity) {

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/JwtGenerator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 the original author or authors.
2+
* Copyright 2020-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -144,7 +144,6 @@ public Jwt generate(OAuth2TokenContext context) {
144144
}
145145
}
146146
}
147-
claimsBuilder.claims(new DefaultOAuth2TokenClaimsConsumer(context));
148147
// @formatter:on
149148

150149
JwsHeader.Builder jwsHeaderBuilder = JwsHeader.with(jwsAlgorithm);

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2AccessTokenGenerator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 the original author or authors.
2+
* Copyright 2020-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -84,7 +84,6 @@ public OAuth2AccessToken generate(OAuth2TokenContext context) {
8484
if (!CollectionUtils.isEmpty(context.getAuthorizedScopes())) {
8585
claimsBuilder.claim(OAuth2ParameterNames.SCOPE, context.getAuthorizedScopes());
8686
}
87-
claimsBuilder.claims(new DefaultOAuth2TokenClaimsConsumer(context));
8887
// @formatter:on
8988

9089
if (this.accessTokenCustomizer != null) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
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.config.annotation.web.configurers;
17+
18+
import java.util.Collections;
19+
import java.util.List;
20+
import java.util.Map;
21+
import java.util.Set;
22+
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Test;
25+
26+
import org.springframework.security.authentication.TestingAuthenticationToken;
27+
import org.springframework.security.core.Authentication;
28+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
29+
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
30+
import org.springframework.security.oauth2.jwt.JwsHeader;
31+
import org.springframework.security.oauth2.jwt.JwtClaimNames;
32+
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
33+
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
34+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
35+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
36+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeActor;
37+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeAuthenticationToken;
38+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeCompositeAuthenticationToken;
39+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
40+
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
41+
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
42+
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
43+
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
44+
import org.springframework.security.oauth2.server.authorization.util.TestX509Certificates;
45+
46+
import static org.assertj.core.api.Assertions.assertThat;
47+
import static org.assertj.core.api.Assertions.entry;
48+
import static org.mockito.Mockito.mock;
49+
import static org.mockito.Mockito.when;
50+
51+
/**
52+
* Tests for {@link DefaultOAuth2TokenCustomizers}.
53+
*
54+
* @author Steve Riesenberg
55+
* @author Joe Grandja
56+
*/
57+
class DefaultOAuth2TokenCustomizersTests {
58+
private static final String ISSUER_1 = "issuer-1";
59+
private static final String ISSUER_2 = "issuer-2";
60+
private JwsHeader.Builder jwsHeaderBuilder;
61+
private JwtClaimsSet.Builder jwtClaimsBuilder;
62+
63+
@BeforeEach
64+
void setUp() {
65+
this.jwsHeaderBuilder = JwsHeader.with(SignatureAlgorithm.RS256);
66+
this.jwtClaimsBuilder = JwtClaimsSet.builder().issuer(ISSUER_1);
67+
}
68+
69+
@Test
70+
void customizeWhenTokenTypeIsRefreshTokenThenNoClaimsAdded() {
71+
// @formatter:off
72+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
73+
.tokenType(OAuth2TokenType.REFRESH_TOKEN)
74+
.build();
75+
// @formatter:on
76+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
77+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
78+
assertThat(jwtClaimsSet.getClaims()).containsOnly(entry(JwtClaimNames.ISS, ISSUER_1));
79+
}
80+
81+
@Test
82+
void customizeWhenAuthorizationGrantIsNullThenNoClaimsAdded() {
83+
// @formatter:off
84+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
85+
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
86+
.build();
87+
// @formatter:on
88+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
89+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
90+
assertThat(jwtClaimsSet.getClaims()).containsOnly(entry(JwtClaimNames.ISS, ISSUER_1));
91+
}
92+
93+
@Test
94+
void customizeWhenTokenExchangeGrantAndResourcesThenNoClaimsAdded() {
95+
OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthentication = mock(
96+
OAuth2TokenExchangeAuthenticationToken.class);
97+
when(tokenExchangeAuthentication.getResources()).thenReturn(Set.of("resource1", "resource2"));
98+
// @formatter:off
99+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
100+
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
101+
.authorizationGrant(tokenExchangeAuthentication)
102+
.build();
103+
// @formatter:on
104+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
105+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
106+
// We do not populate claims (e.g. `aud`) based on the resource parameter
107+
assertThat(jwtClaimsSet.getClaims()).containsOnly(entry(JwtClaimNames.ISS, ISSUER_1));
108+
}
109+
110+
@Test
111+
void customizeWhenTokenExchangeGrantAndAudiencesThenNoClaimsAdded() {
112+
OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthentication = mock(
113+
OAuth2TokenExchangeAuthenticationToken.class);
114+
when(tokenExchangeAuthentication.getAudiences()).thenReturn(Set.of("audience1", "audience2"));
115+
// @formatter:off
116+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
117+
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
118+
.authorizationGrant(tokenExchangeAuthentication)
119+
.build();
120+
// @formatter:on
121+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
122+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
123+
// NOTE: We do not populate claims (e.g. `aud`) based on the audience parameter
124+
assertThat(jwtClaimsSet.getClaims()).containsOnly(entry(JwtClaimNames.ISS, ISSUER_1));
125+
}
126+
127+
@Test
128+
void customizeWhenTokenExchangeGrantAndDelegationThenActClaimAdded() {
129+
OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthentication = mock(
130+
OAuth2TokenExchangeAuthenticationToken.class);
131+
when(tokenExchangeAuthentication.getAudiences()).thenReturn(Collections.emptySet());
132+
133+
Authentication subject = new TestingAuthenticationToken("subject", null);
134+
OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of(JwtClaimNames.ISS, ISSUER_1,
135+
JwtClaimNames.SUB, "actor1"));
136+
OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of(JwtClaimNames.ISS, ISSUER_2,
137+
JwtClaimNames.SUB, "actor2"));
138+
OAuth2TokenExchangeCompositeAuthenticationToken principal = new OAuth2TokenExchangeCompositeAuthenticationToken(
139+
subject, List.of(actor1, actor2));
140+
141+
// @formatter:off
142+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
143+
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
144+
.principal(principal)
145+
.authorizationGrant(tokenExchangeAuthentication)
146+
.build();
147+
// @formatter:on
148+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
149+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
150+
assertThat(jwtClaimsSet.getClaims()).isNotEmpty();
151+
assertThat(jwtClaimsSet.getClaims()).hasSize(2);
152+
assertThat(jwtClaimsSet.getClaims().get("act")).isNotNull();
153+
@SuppressWarnings("unchecked")
154+
Map<String, Object> actClaim1 = (Map<String, Object>) jwtClaimsSet.getClaims().get("act");
155+
assertThat(actClaim1.get(JwtClaimNames.ISS)).isEqualTo(ISSUER_1);
156+
assertThat(actClaim1.get(JwtClaimNames.SUB)).isEqualTo("actor1");
157+
@SuppressWarnings("unchecked")
158+
Map<String, Object> actClaim2 = (Map<String, Object>) actClaim1.get("act");
159+
assertThat(actClaim2.get(JwtClaimNames.ISS)).isEqualTo(ISSUER_2);
160+
assertThat(actClaim2.get(JwtClaimNames.SUB)).isEqualTo("actor2");
161+
}
162+
163+
@Test
164+
void customizeWhenPKIX509ClientCertificateAndCertificateBoundAccessTokensThenX5tClaimAdded() {
165+
// @formatter:off
166+
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
167+
.clientAuthenticationMethod(ClientAuthenticationMethod.TLS_CLIENT_AUTH)
168+
.clientSettings(
169+
ClientSettings.builder()
170+
.x509CertificateSubjectDN(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE[0].getSubjectX500Principal().getName())
171+
.build()
172+
)
173+
.tokenSettings(
174+
TokenSettings.builder()
175+
.x509CertificateBoundAccessTokens(true)
176+
.build()
177+
)
178+
.build();
179+
// @formatter:on
180+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
181+
registeredClient, ClientAuthenticationMethod.TLS_CLIENT_AUTH,
182+
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
183+
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
184+
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
185+
// @formatter:off
186+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
187+
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
188+
.registeredClient(registeredClient)
189+
.authorizationGrant(clientCredentialsAuthentication)
190+
.build();
191+
// @formatter:on
192+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
193+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
194+
assertThat(jwtClaimsSet.getClaims()).isNotEmpty();
195+
assertThat(jwtClaimsSet.getClaims()).hasSize(2);
196+
Map<String, Object> cnfClaim = jwtClaimsSet.getClaim("cnf");
197+
assertThat(cnfClaim).isNotEmpty();
198+
assertThat(cnfClaim.get("x5t#S256")).isNotNull();
199+
}
200+
201+
@Test
202+
void customizeWhenSelfSignedX509ClientCertificateAndCertificateBoundAccessTokensThenX5tClaimAdded() {
203+
// @formatter:off
204+
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
205+
.clientAuthenticationMethod(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH)
206+
.clientSettings(
207+
ClientSettings.builder()
208+
.jwkSetUrl("https://client.example.com/jwks")
209+
.build()
210+
)
211+
.tokenSettings(
212+
TokenSettings.builder()
213+
.x509CertificateBoundAccessTokens(true)
214+
.build()
215+
)
216+
.build();
217+
// @formatter:on
218+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
219+
registeredClient, ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH,
220+
TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE);
221+
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
222+
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
223+
// @formatter:off
224+
JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder)
225+
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
226+
.registeredClient(registeredClient)
227+
.authorizationGrant(clientCredentialsAuthentication)
228+
.build();
229+
// @formatter:on
230+
DefaultOAuth2TokenCustomizers.jwtCustomizer().customize(tokenContext);
231+
JwtClaimsSet jwtClaimsSet = this.jwtClaimsBuilder.build();
232+
assertThat(jwtClaimsSet.getClaims()).isNotEmpty();
233+
assertThat(jwtClaimsSet.getClaims()).hasSize(2);
234+
Map<String, Object> cnfClaim = jwtClaimsSet.getClaim("cnf");
235+
assertThat(cnfClaim).isNotEmpty();
236+
assertThat(cnfClaim.get("x5t#S256")).isNotNull();
237+
}
238+
239+
}

0 commit comments

Comments
 (0)