Jun Koyama Tagbangers, Inc. We Make Stories. 社会人4 年目 / TB 3 年目 About speaker Spring / React / AWS / DevOps 日々の仕事をクリエイティブにする ソフトウェアを作っています 技術ブログ 初登壇 💪 デジタルプロダクト構築・成長支援 Spring 設計・開発支援 Architecture モダナイゼーション
API Gateway Browser ① Request resource ① ブラウザから API Gateway に対してフロントエンドページをリクエスト ② API Gateway がフロントエンドアプリ対してリクエストを渡す → 認証はかかっていないのでフロントエンドのリソースが取得できる https://api- gateway/judge/ ブラウザでは初回ページが表示されている状態 審査フロント (SPA) ② Request Resource About browser AuthN/AuthZ flow 3 / 12 1. 審査アプリのフロントエンドリソースを取得
API Gateway 審査 API Resource Servers OAuth Client Browser ① Request resource ② Request resource ❌ Rejected ① ブラウザから API Gateway に対して API を Ajax リクエスト ② API Gateway が保護された API に対してリクエストを渡す 401 Unauthorized Loading resources... https://api- gateway/api/judge/entries ブラウザではデータロード中の表示状態 About browser AuthN/AuthZ flow 4 / 12 2. 審査アプリで利用する保護されたリソースをリクエスト 未認証のリクエストのため API は 401 エラーをレスポンスする
API Gateway Keycloak AuthZ Server OAuth Client Browser ① Require AuthZ ② Redirect to Login page ① ブラウザは API Gateway に対し認証をリクエスト ② 認証サーバの認証ページにリダイレクト、 https://api- gateway/oauth2/authorization/judge?... https://keycloak/auth/realms/judge/protocol/openid- connect/auth?... ID & Password + MFA の二段階認証 ③ API Gateway にリダイレクト https://api- gateway/login/oauth2/code/judge?... Judge Realm user- a user- b ... client: gmark- api scope: judge:judge ユーザやクライアントなどの 認証・認可のリソースを管理 ③ Issue token API Gateway はトークンを認証サーバにリクエストし 取得したトークンをセッションに保存 About browser AuthN/AuthZ flow 5 / 12 3. 審査アプリは認証をリクエスト Authorization Code Flow
API Gateway Keycloak 審査 API Resource Servers AuthZ Server OAuth Client Browser ① Request resource ② Request with token ✅ Accept Request ③ Validate token ① ブラウザは API Gateway に対して API を Ajax リクエスト ② API Gateway がセッションからトークンを取り出し 保護された API サーバのリクエストに添付する ③ 保護された API サーバはトークンの権限と有効性を検証 問題なければ保護されたリソースをレスポンスする About browser AuthN/AuthZ 7 / 12 4. 審査アプリで利用する保護されたリソースをリクエスト https://api- gateway/api/judge/entries API Gateway には TokenRelay を有効にする必要あり spring: cloud: gateway: default-filters: - TokenRelay= Spring Cloud Gateway を利用している場合 application.yml に記述
API Gateway Keycloak 審査 API Resource Servers AuthZ Server OAuth Client Browser ① Request resource ② Request with token ✅ Accept Request ③ Validate token spring- boot- starter- oauth2- resource- server @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .authorizeRequests(authz -> authz .anyRequest().hasAnyAuthority("SCOPE_judge:judge")) .oauth2ResourceServer(oauth2 -> ...) .build(); } } SecurityConfig { ... "scope": "judge:judge ...", ... }
jwt.io JWT.IO JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiS... decode Payload 権限が含まれているか検証 権限がない場合は 403 Forbidden エラーを返す About browser AuthN/AuthZ 8 / 12
spring: security: oauth2: resourceserver: jwt: jwk-set-uri: "https://keycloak/auth/realms/judge/protocol/openid- connect/certs" API Gateway Keycloak 審査 API Resource Servers AuthZ Server OAuth Client Browser ① Request resource ② Request with token ✅ Accept Request ③ Validate token spring- boot- starter- oauth2- resource- server
jwt.io JWT.IO JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiS... VERIFY SIGNATURE decode ... 署名の有効性を検証 署名の検証により不正なトークンに よるリクエストを拒否 application.yml About browser AuthN/AuthZ 9 / 12
API Gateway Keycloak 審査 API Resource Servers AuthZ Server OAuth Client Browser ① Request resource ② Request with token ✅ Accept Request ③ Validate token About browser AuthN/AuthZ 10 / 12 以降はトークンを用いて保護されたリソースにアクセス JWT トークンはブラウザに公開されない
4 / 7 window.accessToken = "" Loginless AuthN for trusted device 審査 API Resource Server API Gateway ④ Request with token OAuth Client Native App WebView AuthZ Info ③ Request with token Keycloak AuthZ Server ① Issue token ✅ Accept Request ① アプリは認証サーバに対してトークンの発行をリクエスト ② 取得したトークンを WebView に変数として渡す ③ WebView の Ajax リクエストに対して Bearer Token を付与 認可のフロー https://keycloak/auth/realms/judge/protocol/openid- connect/token?... ⑤ Validate token ④ API Gateway が保護された API に対してリクエストを渡す const open = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { open.apply(this, arguments); this.setRequestHeader("Authorization", `Bearer ${window.accessToken}`); }; ② Inject token ⑤ 有効なトークンが付与されているため API は保護されたリソースをレスポンスする
7 / 7 Loginless AuthN for trusted device 審査 API Resource Server API Gateway ③ Request with token OAuth Client Native App WebView AuthZ Info ② Request with token Keycloak AuthZ Server ① Issue token ✅ Accept Request ④ Validate token 以降はトークンを用いて保護されたリソースにアクセス Trusted device 自動的に認証された状態で審査アプリが利用できるように