Skip to content

Commit e556d23

Browse files
committed
Adds how-to guide on adding authorities to access tokens
Closes issue #542
1 parent 9c1ec34 commit e556d23

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package sample.customClaims;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
6+
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
7+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
8+
9+
@Configuration
10+
public class CustomClaimsConfiguration {
11+
@Bean
12+
public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() {
13+
return (context) -> {
14+
if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
15+
context.getClaims().claims((claims) -> {
16+
claims.put("claim-1", "value-1");
17+
claims.put("claim-2", "value-2");
18+
});
19+
}
20+
};
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package sample.customClaims.authorities;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.security.core.authority.AuthorityUtils;
6+
import org.springframework.security.core.userdetails.User;
7+
import org.springframework.security.core.userdetails.UserDetails;
8+
import org.springframework.security.core.userdetails.UserDetailsService;
9+
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
10+
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
11+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
12+
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
13+
14+
import java.util.Collections;
15+
import java.util.stream.Collectors;
16+
17+
@Configuration
18+
public class CustomClaimsWithAuthoritiesConfiguration {
19+
@Bean
20+
public UserDetailsService users() {
21+
UserDetails user = User.withDefaultPasswordEncoder()
22+
.username("user1") // <1>
23+
.password("password")
24+
.roles(new String[] { "messenger", "courier" }) // <2>
25+
.build();
26+
return new InMemoryUserDetailsManager(user);
27+
}
28+
29+
@Bean
30+
public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() { // <3>
31+
return (context) -> {
32+
if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { // <4>
33+
context.getClaims().claims((claims) -> { // <5>
34+
var roles = AuthorityUtils.authorityListToSet(context.getPrincipal().getAuthorities())
35+
.stream()
36+
.map(c -> c.replaceFirst("^ROLE_", ""))
37+
.collect(Collectors.collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet)); // <6>
38+
claims.put("roles", roles); // <7>
39+
});
40+
}
41+
};
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[[how-to-extension-grant-type]]
2+
= How-to: Add authorities to custom claims in JWT-based access tokens
3+
:index-link: ../how-to.html
4+
:docs-dir: ..
5+
:examples-dir: {docs-dir}/examples
6+
7+
This guide demonstrates how to append resource owner authorities to a JSON Web Token (JWT)-based access token.
8+
The term 'authorities' may be described in varying forms such as roles, permissions, or groups of the resource owner.
9+
10+
To make resource owners' authorities available to the resource server, we add custom claims to an access token issued by Spring Authorization Server.
11+
The client using the issued token to access protected resources will then have information about the resource owner’s level of access, among other potential uses and benefits.
12+
13+
* <<custom-claims>>
14+
* <<custom-claims-authorities>>
15+
16+
[[custom-claims]]
17+
== Add custom claims to JWT-based access tokens
18+
19+
You may add your own custom claims to an access token using `OAuth2TokenCustomizer<JWTEncodingContext>` bean.
20+
Please note that this bean may only be defined once, and so care must be taken care of to ensure that you are customizing the appropriate token type — an access token in this case.
21+
If you are interested in customizing the identity token, see xref:how-to-userinfo.adoc#customize-user-info-mapper[the UserInfo mapper guide for more information].
22+
23+
The following is an example of adding custom claims to an access token — in other words, every access token that is issued by the authorization server will have the custom claims populated.
24+
25+
[[sample.customClaims]]
26+
include::code:CustomClaimsConfiguration[]
27+
28+
[[custom-claims-authorities]]
29+
== Add authorities to JWT-based access tokens
30+
31+
To add authorities of the resource owner to a JWT-based access token, we can refer to the custom claim mapping method above
32+
and populate custom claims with the authorities of the `Principal`.
33+
34+
We define a sample user with a mix of authorities for demonstration purposes, and populate custom claims in an access token
35+
with those authorities.
36+
37+
[[sample.customClaims.authorities]]
38+
include::code:CustomClaimsWithAuthoritiesConfiguration[]
39+
40+
<1> Define a sample user `user1` within an internal user details service.
41+
<2> Define a few roles for `user1`.
42+
<3> Define `OAuth2TokenCustomizer<JwtEncodingContext>` bean that allows for customizing JWT token claims.
43+
<4> Check whether the JWT token is an access token.
44+
<5> From the encoding context, modify the claims of the access token.
45+
<6> Extract user roles from the `Principal` object. The role information for internal users is stored as a string prefixed with `ROLE_`, so we strip the prefix here.
46+
<7> Set custom claim `roles` to the set of roles collected from the previous step.
47+
48+
As a result of this customization, authorities information about the user will be included as a custom claim within an
49+
access token.

docs/src/docs/asciidoc/how-to.adoc

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
* xref:guides/how-to-ext-grant-type.adoc[Implement an Extension Authorization Grant Type]
1010
* xref:guides/how-to-userinfo.adoc[Customize the OpenID Connect 1.0 UserInfo response]
1111
* xref:guides/how-to-jpa.adoc[Implement core services with JPA]
12+
* xref:guides/how-to-custom-claims-authorities.adoc[Add authorities to custom claims in JWT-based access tokens]

0 commit comments

Comments
 (0)