Spring Security OAuthを使用したプリンシパルと権限の抽出
1. 概要
このチュートリアルでは、SpringBootとSpringSecurity OAuthを使用して、ユーザー認証をサードパーティとカスタム認証サーバーに委任するアプリケーションを作成する方法を説明します。
また、we’ll demonstrate how to extract both Principal and Authorities using Spring’s PrincipalExtractor and AuthoritiesExtractor interfaces.
Spring Security OAuth2の概要については、theseの記事を参照してください。
2. Mavenの依存関係
開始するには、pom.xmlにspring-security-oauth2-autoconfigureの依存関係を追加する必要があります。
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.0.1.RELEASE
3. Githubを使用したOAuth認証
次に、アプリケーションのセキュリティ構成を作成しましょう。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http)
throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/login**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin().disable();
}
}
つまり、誰でも/loginエンドポイントにアクセスでき、他のすべてのエンドポイントにはユーザー認証が必要になるということです。
また、構成クラスに@EnableOAuthSsoアノテーションを付けました。これにより、アプリケーションがOAuthクライアントに変換され、そのように動作するために必要なコンポーネントが作成されます。
Springはデフォルトでほとんどのコンポーネントを作成しますが、いくつかのプロパティを設定する必要があります:
security.oauth2.client.client-id=89a7c4facbb3434d599d
security.oauth2.client.client-secret=9b3b08e4a340bd20e866787e4645b54f73d74b6a
security.oauth2.client.access-token-uri=https://github.com/login/oauth/access_token
security.oauth2.client.user-authorization-uri=https://github.com/login/oauth/authorize
security.oauth2.client.scope=read:user,user:email
security.oauth2.resource.user-info-uri=https://api.github.com/user
ユーザーアカウント管理を扱う代わりに、サードパーティ(この場合はGithub)に委任しているため、アプリケーションのロジックに集中できます。
4. プリンシパルと権限の抽出
OAuthクライアントとして機能し、サードパーティを介してユーザーを認証する場合、次の3つのステップを考慮する必要があります。
-
ユーザー認証-ユーザーはサードパーティで認証します
-
ユーザー承認–認証に続き、ユーザーがアプリケーションに代わって特定の操作を実行することを許可したときです。ここでscopesが登場します
-
ユーザーデータの取得–取得したOAuthトークンを使用してユーザーのデータを取得します
ユーザーのデータを取得したら、Spring is able to automatically create the user’s Principal and Authorities。
それは受け入れられるかもしれませんが、多くの場合、私たちはそれらを完全に制御したいシナリオで自分自身を見つけます。
これを行うには、Spring gives us two interfaces we can use to override its default behavior:
-
PrincipalExtractor –Principalを抽出するためのカスタムロジックを提供するために使用できるインターフェース
-
AuthoritiesExtractor –PrincipalExtractorに似ていますが、代わりにAuthorities抽出をカスタマイズするために使用されます
デフォルトでは、これらのインターフェースを実装し、それらを作成するための事前定義された戦略を持つSpring provides two components – FixedPrincipalExtractor and FixedAuthoritiesExtractor –。
4.1. Githubの認証のカスタマイズ
私たちの場合、Githubのユーザーデータがlikeにどのように見えるか、そしてニーズに応じてそれらを調整するために何を使用できるかを認識しています。
そのため、Springのデフォルトのコンポーネントをオーバーライドするには、これらのインターフェイスも実装する2つのBeansを作成する必要があります。
アプリケーションのPrincipalには、ユーザーのGithubユーザー名を使用するだけです。
public class GithubPrincipalExtractor
implements PrincipalExtractor {
@Override
public Object extractPrincipal(Map map) {
return map.get("login");
}
}
ユーザーのGithubサブスクリプション(無料またはその他)に応じて、GITHUB_USER_SUBSCRIBEDまたはGITHUB_USER_FREEの権限をユーザーに付与します。
public class GithubAuthoritiesExtractor
implements AuthoritiesExtractor {
List GITHUB_FREE_AUTHORITIES
= AuthorityUtils.commaSeparatedStringToAuthorityList(
"GITHUB_USER,GITHUB_USER_FREE");
List GITHUB_SUBSCRIBED_AUTHORITIES
= AuthorityUtils.commaSeparatedStringToAuthorityList(
"GITHUB_USER,GITHUB_USER_SUBSCRIBED");
@Override
public List extractAuthorities
(Map map) {
if (Objects.nonNull(map.get("plan"))) {
if (!((LinkedHashMap) map.get("plan"))
.get("name")
.equals("free")) {
return GITHUB_SUBSCRIBED_AUTHORITIES;
}
}
return GITHUB_FREE_AUTHORITIES;
}
}
次に、これらのクラスを使用してBeanも作成する必要があります。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ...
@Bean
public PrincipalExtractor githubPrincipalExtractor() {
return new GithubPrincipalExtractor();
}
@Bean
public AuthoritiesExtractor githubAuthoritiesExtractor() {
return new GithubAuthoritiesExtractor();
}
}
4.2. カスタム認証サーバーの使用
サードパーティに依存する代わりに、ユーザー用に独自の承認サーバーを使用することもできます。
使用することを決定した認証サーバーにもかかわらず、PrincipalとAuthoritiesの両方をカスタマイズするために必要なコンポーネントは同じままです:PrincipalExtractorとAuthoritiesExtractor。
be aware of the data returned by the user-info-uri endpointを実行し、適切と思われる方法で使用する必要があります。
thisの記事で説明されている承認サーバーを使用してユーザーを認証するようにアプリケーションを変更しましょう。
security.oauth2.client.client-id=SampleClientId
security.oauth2.client.client-secret=secret
security.oauth2.client.access-token-uri=http://localhost:8081/auth/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8081/auth/oauth/authorize
security.oauth2.resource.user-info-uri=http://localhost:8081/auth/user/me
承認サーバーを指定しているので、両方のエクストラクターを作成する必要があります。この場合、PrincipalExtractorは、nameキーを使用して、MapからPrincipalを抽出します。
public class examplePrincipalExtractor
implements PrincipalExtractor {
@Override
public Object extractPrincipal(Map map) {
return map.get("name");
}
}
権限については、承認サーバーがすでにuser-info-uriのデータに配置しています。
そのため、それらを抽出して強化します。
public class exampleAuthoritiesExtractor
implements AuthoritiesExtractor {
@Override
public List extractAuthorities
(Map map) {
return AuthorityUtils
.commaSeparatedStringToAuthorityList(asAuthorities(map));
}
private String asAuthorities(Map map) {
List authorities = new ArrayList<>();
authorities.add("example_USER");
List> authz =
(List>) map.get("authorities");
for (LinkedHashMap entry : authz) {
authorities.add(entry.get("authority"));
}
return String.join(",", authorities);
}
}
次に、BeanをSecurityConfigクラスに追加します。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ...
@Bean
public PrincipalExtractor examplePrincipalExtractor() {
return new examplePrincipalExtractor();
}
@Bean
public AuthoritiesExtractor exampleAuthoritiesExtractor() {
return new exampleAuthoritiesExtractor();
}
}
5. 結論
この記事では、ユーザー認証をサードパーティとカスタム認証サーバーに委任するアプリケーションを実装し、PrincipalとAuthoritiesの両方をカスタマイズする方法を示しました。
いつものように、この例の実装はover on Githubにあります。
ローカルで実行している場合は、localhost:8082でアプリケーションを実行してテストできます。