Skip to content

Commit 9e3b559

Browse files
committed
Add support for OAuth 2.0 Token Exchange Grant
Issue spring-projectsgh-60
1 parent 2004ba1 commit 9e3b559

16 files changed

+1129
-12
lines changed

Diff for: docs/modules/ROOT/pages/protocol-endpoints.adoc

+2-2
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ The supported https://datatracker.ietf.org/doc/html/rfc6749#section-1.3[authoriz
261261

262262
`OAuth2TokenEndpointFilter` is configured with the following defaults:
263263

264-
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeAuthenticationConverter`, `OAuth2RefreshTokenAuthenticationConverter`, `OAuth2ClientCredentialsAuthenticationConverter`, and `OAuth2DeviceCodeAuthenticationConverter`.
265-
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeAuthenticationProvider`, `OAuth2RefreshTokenAuthenticationProvider`, `OAuth2ClientCredentialsAuthenticationProvider`, and `OAuth2DeviceCodeAuthenticationProvider`.
264+
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeAuthenticationConverter`, `OAuth2RefreshTokenAuthenticationConverter`, `OAuth2ClientCredentialsAuthenticationConverter`, `OAuth2DeviceCodeAuthenticationConverter`, and `OAuth2TokenExchangeAuthenticationConverter`.
265+
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeAuthenticationProvider`, `OAuth2RefreshTokenAuthenticationProvider`, `OAuth2ClientCredentialsAuthenticationProvider`, `OAuth2DeviceCodeAuthenticationProvider`, and `OAuth2TokenExchangeAuthenticationProvider`.
266266
* `*AuthenticationSuccessHandler*` -- An `OAuth2AccessTokenResponseAuthenticationSuccessHandler`.
267267
* `*AuthenticationFailureHandler*` -- An `OAuth2ErrorAuthenticationFailureHandler`.
268268

Diff for: oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/aot/hint/OAuth2AuthorizationServerBeanRegistrationAotProcessor.java

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
4444
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
4545
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
46+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ActorAuthenticationToken;
47+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2CompositeAuthenticationToken;
4648
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
4749
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
4850
import org.springframework.security.web.authentication.WebAuthenticationDetails;
@@ -109,7 +111,9 @@ private void registerHints(RuntimeHints hints) {
109111
TypeReference.of(OidcIdToken.class),
110112
TypeReference.of(AbstractOAuth2Token.class),
111113
TypeReference.of(OidcUserInfo.class),
114+
TypeReference.of(OAuth2ActorAuthenticationToken.class),
112115
TypeReference.of(OAuth2AuthorizationRequest.class),
116+
TypeReference.of(OAuth2CompositeAuthenticationToken.class),
113117
TypeReference.of(AuthorizationGrantType.class),
114118
TypeReference.of(OAuth2AuthorizationResponseType.class),
115119
TypeReference.of(OAuth2TokenFormat.class)
@@ -150,8 +154,12 @@ private void registerHints(RuntimeHints hints) {
150154
loadClass("org.springframework.security.jackson2.UserMixin"));
151155
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
152156
loadClass("org.springframework.security.jackson2.SimpleGrantedAuthorityMixin"));
157+
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
158+
loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2ActorAuthenticationTokenMixin"));
153159
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
154160
loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationRequestMixin"));
161+
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
162+
loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2CompositeAuthenticationTokenMixin"));
155163
this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(),
156164
loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2TokenFormatMixin"));
157165

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
17+
package org.springframework.security.oauth2.server.authorization.authentication;
18+
19+
import java.io.Serializable;
20+
import java.util.Collections;
21+
22+
import org.springframework.security.authentication.AbstractAuthenticationToken;
23+
import org.springframework.security.core.Authentication;
24+
import org.springframework.util.Assert;
25+
26+
/**
27+
* An {@link Authentication} implementation used for the OAuth 2.0 Token Exchange Grant
28+
* to represent an actor in a composite token (e.g. the "delegation" use case).
29+
*
30+
* @author Steve Riesenberg
31+
* @since 1.3
32+
* @see OAuth2CompositeAuthenticationToken
33+
*/
34+
public class OAuth2ActorAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
35+
36+
private final String name;
37+
38+
public OAuth2ActorAuthenticationToken(String name) {
39+
super(Collections.emptyList());
40+
Assert.hasText(name, "name cannot be empty");
41+
this.name = name;
42+
}
43+
44+
@Override
45+
public Object getPrincipal() {
46+
return this.name;
47+
}
48+
49+
@Override
50+
public Object getCredentials() {
51+
return null;
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
17+
package org.springframework.security.oauth2.server.authorization.authentication;
18+
19+
import java.io.Serializable;
20+
import java.util.ArrayList;
21+
import java.util.Collections;
22+
import java.util.List;
23+
24+
import org.springframework.security.authentication.AbstractAuthenticationToken;
25+
import org.springframework.security.core.Authentication;
26+
import org.springframework.util.Assert;
27+
28+
/**
29+
* An {@link Authentication} implementation used for the OAuth 2.0 Token Exchange Grant
30+
* to represent the principal in a composite token (e.g. the "delegation" use case).
31+
*
32+
* @author Steve Riesenberg
33+
* @since 1.3
34+
* @see OAuth2TokenExchangeAuthenticationToken
35+
*/
36+
public class OAuth2CompositeAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
37+
38+
private final Authentication subject;
39+
40+
private final List<Authentication> actors;
41+
42+
public OAuth2CompositeAuthenticationToken(Authentication subject, List<Authentication> actors) {
43+
super(subject != null ? subject.getAuthorities() : null);
44+
Assert.notNull(subject, "subject cannot be null");
45+
Assert.notNull(actors, "actors cannot be null");
46+
this.subject = subject;
47+
this.actors = Collections.unmodifiableList(new ArrayList<>(actors));
48+
setDetails(subject.getDetails());
49+
setAuthenticated(subject.isAuthenticated());
50+
}
51+
52+
@Override
53+
public Object getPrincipal() {
54+
return this.subject.getPrincipal();
55+
}
56+
57+
@Override
58+
public Object getCredentials() {
59+
return null;
60+
}
61+
62+
public Authentication getSubject() {
63+
return this.subject;
64+
}
65+
66+
public List<Authentication> getActors() {
67+
return this.actors;
68+
}
69+
}

0 commit comments

Comments
 (0)