使い方: JWT アクセストークンのカスタムクレームとして権限を追加する

このガイドでは、リソース所有者権限を JWT アクセストークンに追加する方法を説明します。「権限」という用語は、リソース所有者のロール、権限、グループなど、さまざまな形式を表す場合があります。

リソース所有者の権限をリソースサーバーで利用できるようにするために、アクセストークンにカスタムクレームを追加します。クライアントがアクセストークンを使用して保護されたリソースにアクセスすると、リソースサーバーはリソース所有者のアクセスレベルに関する情報や、その他の潜在的な用途や利点を取得できるようになります。

JWT アクセストークンにカスタムクレームを追加する

OAuth2TokenCustomizer<JWTEncodingContext>@Bean を使用して、独自のカスタムクレームをアクセストークンに追加できます。この @Bean は 1 回しか定義できないため、適切なトークン型 (この場合はアクセストークン) をカスタマイズするように注意する必要があることに注意してください。ID トークンのカスタマイズに興味がある場合は、詳細についてユーザー情報マッパーガイドを参照してください。

以下は、アクセストークンにカスタムクレームを追加する例です。つまり、認可サーバーによって発行されるすべてのアクセストークンにカスタムクレームが設定されます。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;

@Configuration
public class CustomClaimsConfiguration {
	@Bean
	public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() {
		return (context) -> {
			if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
				context.getClaims().claims((claims) -> {
					claims.put("claim-1", "value-1");
					claims.put("claim-2", "value-2");
				});
			}
		};
	}
}

JWT アクセストークンにカスタムクレームとして権限を追加する

リソース所有者の権限を JWT アクセストークンに追加するには、上記のカスタムクレームマッピングメソッドを参照し、カスタムクレームに Principal の権限を設定します。

デモンストレーションの目的で一連の権限を持つサンプルユーザーを定義し、アクセストークン内のカスタムクレームにそれらの権限を設定します。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

@Configuration
public class CustomClaimsWithAuthoritiesConfiguration {
	@Bean
	public UserDetailsService users() {
		UserDetails user = User.withDefaultPasswordEncoder()
				.username("user1") (1)
				.password("password")
				.roles("user", "admin") (2)
				.build();
		return new InMemoryUserDetailsManager(user);
	}

	@Bean
	public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() { (3)
		return (context) -> {
			if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { (4)
				context.getClaims().claims((claims) -> { (5)
					Set<String> roles = AuthorityUtils.authorityListToSet(context.getPrincipal().getAuthorities())
							.stream()
							.map(c -> c.replaceFirst("^ROLE_", ""))
							.collect(Collectors.collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet)); (6)
					claims.put("roles", roles); (7)
				});
			}
		};
	}
}
1 インメモリ UserDetailsService を使用してサンプルユーザー user1 を定義します。
2user1 のロールを割り当てます。
3JWT クレームのカスタマイズを可能にする OAuth2TokenCustomizer<JwtEncodingContext>@Bean を定義します。
4JWT がアクセストークンであるかどうかを確認します。
5JwtEncodingContext 経由でデフォルトのクレームにアクセスします。
6Principal オブジェクトからロールを抽出します。ロール情報は ROLE_ というプレフィックスが付いた文字列として保存されるため、ここではプレフィックスを削除します。
7 カスタムクレーム roles を、前の手順で収集したロールのセットに設定します。

このカスタマイズの結果、ユーザーに関する権限情報がアクセストークンのカスタムクレームとして含まれるようになります。