Keycloakの知識を背景に、AWS Cognitoを調査してみて感じたこと

Keycloakの使用方法はある程度確認したので、今度はAWSのCognitoを自分への夏休みの宿題としてちょっとだけ調査してみました。 実際にCognitoを触ってみて、Keycloakとどこが違うのかを軽く確認したのでその内容を感想レベルで記述していこうと思います。

AWS Cognitoを確認してみる

まずはCognitoについて改めて確認しました。

Amazon Cognito とは - Amazon Cognito

気になったのはユーザプールの説明に以下の文があったことでした。

Amazon Cognito ユーザープールが発行する OAuth 2.0 トークンと OpenID Connect (OIDC) トークンを使用すると、次のことができるようになります。

CognitoにはユーザプールとIDプールの2つのコンポーネントがありますが、ユーザプールは「認証」、IDプールは「認可」を担当するものであると認識していました。

repost.aws

しかし、ユーザプールがOAuth2.0トークン(アクセストークン)とOIDCトークン(IDトークン)を発行するのであれば、ユーザプールだけで認証も認可もできるのではないかと思いました。

ただ、IDプールの説明を改めてよく読むと「他のAWSサービスへのアクセス」に対して認可を与えるものであることがわかります。

ID プールでは認可 (アクセスコントロール) ができます。ID プールを使用すると、ユーザーに一意の ID を作成して、他の AWS サービスへのアクセスを許可できます。

この時点でKeycloakの比較対象はユーザプールであることがなんとなくわかったので、まずはユーザプールを触ってみました。

ユーザプールを使ってみる

環境構築

以下のページを参考に環境を構築しました。

Amazon Cognito と AWS Amplify を使用して React アプリケーションユーザーを認証する - AWS 規範的ガイダンス

AWS cognitoとReactでログインを実装する

ReactにCognitoでサインイン機能をつける | DevelopersIO

UIが新しくなっていて記事と異なる部分もありましたが、OIDCの仕様上設定する必要がある項目はKeycloakでも当然共通して存在していたためユーザプールはサクッと作成することができました。

注意したのはクライアントの種類(※今回はReactを使用するつもりだったのでパブリッククライアントを選択)と、「Hosted UI」(※AWS Cognitoが用意してくれるサインイン画面)を使用したかったのでチェックを入れました。

docs.aws.amazon.com

caution

実際に動作させてみる

Reactで作成したサンプルアプリでは参考にしたページの通り、Amplify(ライブラリ)の認証機能を使用しています。

Amplifyを使用することで、驚くほど簡単に認証処理を実装することができました。

アプリを起動してログイン画面を開いてみると、先ほど設定した「Hosted UI」が表示されることを確認できました。

「Hosted UI」はカスタマイズ可能なようですが、KeycloakのUIのカスタマイズと比べるとややできることが少ないように思いました。

できること Cognito Keycloak 備考
ロゴの設定 ⚪︎ ⚪︎ -
CSSの編集 ⚪︎ Cognitoは限定的だが、KeycloakはApache FreeMarkerを使用しているためHTMLを自由に生成できるためCSSも自由に適用できる
スクリプトの追加 × ⚪︎ -
画像の追加 × ⚪︎ -
メッセージの編集 × ⚪︎ KeycloakではApache FreeMarkerを使用しているため、フォームの各種ラベルの文言を編集することができる
言語の追加 × ⚪︎ Keycloakでは英語がデフォルトだが、日本語やその他言語にも対応することが可能

login

ログインできたら、以下のコードを適当な箇所に入れることで「idToken」「accessToken」「refreshToken」を取得していることをChromeデベロッパーツールで確認できます。

import { Auth} from 'aws-amplify'
.
.
.
const session = await Auth.currentSession()
console.log(session)

IDプールを使ってみる

ユーザプールの使用方法がある程度わかったので、今度はIDプールの使用方法を確認してみました。

IDプールはユーザプールよりも記事が少ないように感じたので手順を記述します。

環境

まずはIDプールを用意します。

前提として、先ほど作成したユーザプールを使用することとします。

  • Cognitoの画面から「IDプールを作成」ボタンを押下します。

  • 「認証されたアクセス」「Amazon Cognitoユーザプール」にチェックを入れます。

(※ゲストアクセス(未認証ユーザに認可することを許可するか)は任意)

idpool1

  • 「新しいIAMロールを作成」にチェックする(既存のものを使用する場合は「既存のIAMロールを使用」をチェックする)

※ユーザに付与するロール(認可情報)を作成または選択でき、認証済みのユーザと未認証のユーザで権限を分けることができたりする

idpool2

  • 作成したユーザプールの情報を入力する

idpool3

  1. ユーザプールID:上記で作成したユーザプールのIDを選択
  2. アプリクライアントID:上記で作成したユーザプール上に作成したアプリクライアントのIDを選択する
  3. ロール設定:ここではデフォルトの認証されたロールを使用(⇒項番3で設定したものを使用することになる)
  4. アクセスコントロールの属性(クレームマッピング):非アクティブに設定

※クレームマッピングではログインユーザのIDトークンから特定のクレームをIDプールで発行する認可情報に付与することができるよう。ただし、IDトークンに存在しないクレームを「デフォルトマッピング」や「カスタムマッピング」で指定してしまうと「invalid identity pool configuration. check assigned iam roles for this pool」となり正しく認可処理できないことになる(これでだいぶハマった...

  • IDプール名を入力する

「次へ」ボタンを押下してIDプール作成する

idpool4

実装について

ユーザプールでの認証で使用したサンプルアプリにコードを追加してIDプールへアクセスします。 aws-sdkを使用する手順がIDプールのページには記載されていますが、Amplifyでアクセスすることもできるようです。

idpool5

aws-sdkを使用する方法

サインイン後に ID プールを使用して AWS サービスへアクセスする - Amazon Cognito

・Amplifyを使用する方法

以下のコードを適当な場所に入れる

// 設定項目に「identityPoolId」を付け足す
const configuration = {
  region: 'ap-northeast-1',
  userPoolWebClientId: process.env.REACT_APP_CLIENT_ID ?? '',
  userPoolId: 'ap-northeast-xxxxxxxxxxx',
  identityPoolId: process.env.REACT_APP_IDENTITY_POOL_ID ?? '', ★
  oauth: {
    domain: `${congitoDomain}`,
    scope: ['email', 'openid', 'phone'],
    redirectSignIn: 'http://localhost:3000',
    redirectSignOut: 'http://localhost:3000',
    responseType: 'code',
  },
}

Amplify.configure({
  Auth: configuration,
})

・キーの取得方法

Auth.currentCredentials().then(v => {console.log(v)}).catch(e => {console.log(e)})

実際に動作させてみる

上記のAuth.currentCredentials()でIDプールからAWSのリソースに対する認可情報を取得します。

成功すると「accessKeyId」「secretAccessKey」「 sessionToken」などが取得されていることを確認できます。

まとめ

個人的なざっくりとした感想ですが、総合するとCognitoの方が使い勝手がよく便利に感じました。特にAmplifyが強力で、実装が非常に簡単だった点が大きいです。

Keycloakでも「Keycloakアダプター」としてライブラリが用意されていますが、廃止の方向に向かっているようです。 依存度が軽減される一方で、勉強コストは高くなってしまうため参入障壁が高くなってしまう気がしました。

Update on deprecation of Keycloak adapters - Keycloak

またCognitoを調査して改めてKeycloakを振り返ってみると、Keycloakは概念が複雑なように感じてしまします。(よく言えば柔軟性があるのかもしれませんが)

Keycloakには「レルム」というCognitoのユーザプールに近い概念のものがありますが、この「レルム」を管理する権限を持ったユーザ自体も一般ユーザと同じように「レルム」という概念の管理下におかれたり、管理コンソールとは別にアカウントのコンソールが存在していたりします。どちらかというとKeycloakのユーザはCognitoのユーザプールに存在するユーザより、AWSでいうところのIAMユーザの方が概念としては近いのかなとも思いました。

KeycloakとCognito、両方を見比べることができて有意義な夏休みの宿題になったかなと思っています。