1. 概要

このクイックチュートリアルでは、Spring Security OAuth2実装を使用し、 Spring SecurityOAuth2.2で導入された新しいJwtClaimsSetVerifierを使用してJWTクレームを検証する方法を学習します。 0.RELEASE

2. Maven構成

まず、最新バージョンのspring-security-oauth2pom.xmlに追加する必要があります。

<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>

3. トークンストアの構成

次に、リソースサーバーでTokenStoreを構成しましょう。

@Bean
public TokenStore tokenStore() {
    return new JwtTokenStore(accessTokenConverter());
}

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("123");
    converter.setJwtClaimsSetVerifier(jwtClaimsSetVerifier());
    return converter;
}

JwtAccessTokenConverterに新しいベリファイアを追加する方法に注意してください。

JwtTokenStore の構成方法の詳細については、Spring SecurityOAuthでJWTを使用するに関する記事をご覧ください。

次のセクションでは、さまざまなタイプのクレームベリファイアとそれらを連携させる方法について説明します。

4. IssuerClaimVerifier

次のように、 IssuerClaimVerifierを使用して発行者の「iss」クレームを確認することから、簡単に始めます。

@Bean
public JwtClaimsSetVerifier issuerClaimVerifier() {
    try {
        return new IssuerClaimVerifier(new URL("http://localhost:8081"));
    } catch (MalformedURLException e) {
        throw new RuntimeException(e);
    }
}

この例では、発行者を確認するために単純なIssuerClaimVerifierを追加しました。 JWTトークンに発行者の「iss」クレームに対して異なる値が含まれている場合、単純なInvalidTokenExceptionがスローされます。

当然、トークンに発行者の「iss」クレームが含まれている場合、例外はスローされず、トークンは有効であると見なされます。

5. カスタムクレームベリファイア

ただし、ここで興味深いのは、カスタムクレームベリファイアを作成することもできることです。

@Bean
public JwtClaimsSetVerifier customJwtClaimVerifier() {
    return new CustomClaimVerifier();
}

これがどのように見えるかの簡単な実装を次に示します– user_nameクレームがJWTトークンに存在するかどうかを確認します。

public class CustomClaimVerifier implements JwtClaimsSetVerifier {
    @Override
    public void verify(Map<String, Object> claims) throws InvalidTokenException {
        String username = (String) claims.get("user_name");
        if ((username == null) || (username.length() == 0)) {
            throw new InvalidTokenException("user_name claim is empty");
        }
    }
}

ここでJwtClaimsSetVerifierインターフェースを実装していることに注目してください。次に、verifyメソッドの完全なカスタム実装を提供します。これにより、必要なあらゆる種類のチェックに完全な柔軟性がもたらされます。

6. 複数のクレームベリファイアを組み合わせる

最後に、 DelegatingJwtClaimsSetVerifierを使用して複数のクレームベリファイアを組み合わせる方法を次のように見てみましょう。

@Bean
public JwtClaimsSetVerifier jwtClaimsSetVerifier() {
    return new DelegatingJwtClaimsSetVerifier(Arrays.asList(
      issuerClaimVerifier(), customJwtClaimVerifier()));
}

DelegatingJwtClaimsSetVerifier は、 JwtClaimsSetVerifier オブジェクトのリストを取得し、クレーム検証プロセスをこれらのベリファイアに委任します。

7. 単純な統合テスト

実装が完了したので、簡単な統合テストを使用してクレームベリファイアをテストしましょう。

@RunWith(SpringRunner.class)
@SpringBootTest(
  classes = ResourceServerApplication.class, 
  webEnvironment = WebEnvironment.RANDOM_PORT)
public class JwtClaimsVerifierIntegrationTest {

    @Autowired
    private JwtTokenStore tokenStore;

    ...
}

発行者を含まない(ただし、 user_name を含む)トークンから始めます。これは有効である必要があります。

@Test
public void whenTokenDontContainIssuer_thenSuccess() {
    String tokenValue = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

これが有効である理由は単純です。最初のベリファイアは、発行者のクレームがトークンに存在する場合にのみアクティブになります。 その主張が存在しない場合–検証者は開始しません。

次に、有効な発行者( http:// localhost:8081 )とuser_nameを含むトークンを見てみましょう。 これも有効である必要があります。

@Test
public void whenTokenContainValidIssuer_thenSuccess() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

トークンに無効な発行者( http:// localhost:8082 )が含まれている場合、トークンは検証され、無効であると判断されます。

@Test(expected = InvalidTokenException.class)
public void whenTokenContainInvalidIssuer_thenException() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

次に、トークンに user_name クレームが含まれていない場合、トークンは無効になります。

@Test(expected = InvalidTokenException.class)
public void whenTokenDontContainUsername_thenException() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

そして最後に、トークンに空の user_name クレームが含まれている場合、それも無効です。

@Test(expected = InvalidTokenException.class)
public void whenTokenContainEmptyUsername_thenException() {
    String tokenValue = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....";
    OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue);
    
    assertTrue(auth.isAuthenticated());
}

8. 結論

この簡単な記事では、SpringSecurityOAuthの新しいベリファイア機能について説明しました。

いつものように、完全なソースコードはGitHubから入手できます。