2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【応用編】Spring Cloud GatewayでAPIゲートウェイを作ってみる -OAuth2認可コードフロー&JWT認証-

Last updated at Posted at 2025-09-09

🧭 はじめに

マイクロサービス構成では、各サービスに個別で認証を実装するのは非効率です。そこで登場するのが API Gatewayでの認証集中管理。Spring Cloud Gatewayは、OAuth2JWT を使った認証を統合することでセキュアなAPIアクセスを実現する方法を解説します。


🧩 システム構成図


⚙️ Keycloakの設定

1. RealmとClientの作成

  • Realm: demo-realm
  • Client: spring-gateway-client
    • Access Type: confidential
    • Valid Redirect URIs: http://localhost:8080/login/oauth2/code/keycloak
    • Web Origins: *

2. ユーザー作成

  • ユーザー名: demo-user
  • パスワード: password
  • ロール: USER

🛠️ Spring Cloud GatewayのOAuth2設定

application.yml

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: spring-gateway-client
            client-secret: <your-client-secret>
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
            scope: openid
        provider:
          keycloak:
            issuer-uri: http://localhost:8080/realms/demo-realm
  cloud:
    gateway:
      routes:
        - id: secured-route
          uri: http://localhost:8081
          predicates:
            - Path=/api/**
          filters:
            - JwtAuthenticationFilter

🧪 JWT認証フィルターの作成

JwtAuthenticationFilter.java

public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory<JwtAuthenticationFilter.Config> {

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String authHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }

            String token = authHeader.substring(7);
            try {
                Claims claims = Jwts.parser()
                    .setSigningKey(Keys.hmacShaKeyFor("your-signing-key".getBytes()))
                    .parseClaimsJws(token)
                    .getBody();

                exchange.getRequest().mutate()
                    .header("X-User-Id", claims.getSubject())
                    .header("X-User-Roles", claims.get("roles", String.class))
                    .build();

                return chain.filter(exchange);
            } catch (JwtException e) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
        };
    }

    public static class Config {}
}

👤 認証後のユーザー情報取得

バックエンドサービスでは、Gatewayが付加したヘッダーからユーザー情報を取得できます。

例:Spring Boot Controller

@GetMapping("/api/userinfo")
public ResponseEntity<Map<String, String>> getUserInfo(@RequestHeader("X-User-Id") String userId,
                                                       @RequestHeader("X-User-Roles") String roles) {
    Map<String, String> userInfo = new HashMap<>();
    userInfo.put("userId", userId);
    userInfo.put("roles", roles);
    return ResponseEntity.ok(userInfo);
}

✅ まとめ

Spring Cloud GatewayとKeycloakを組み合わせることで、OAuth2 + JWTによる堅牢な認証機構を構築できます。次回は、Rate Limitingの実装について紹介予定です。


📎 参考リンク

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?