Cognitoを検討した理由
- Googleなどのシングルサインオンを検討していた
- RDSをできるなら使いたくなかった
- ワンタイムパスワードなど丸投げしたかった
使わなくなった理由
- ロックインされる
- ユーザーをRDSなどに移したいときに移すのがめんどくさい
- CognitoUIがダサいし意外と使うのがめんどくさい
- シングルサインオンのアクセストークンをそのまま使う方が楽
CLoudFormationで構築
下のテンプレートのcallbackとlogoutを正しいのに置き換えてデプロイします。
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
ProjectName:
Description: 'Name of the project'
Type: String
Default: 'myproject'
Env:
Description: 'Environment (e.g., prod, dev, staging)'
Type: String
AllowedValues:
- prod
- dev
- staging
Default: 'dev'
CallbackURL:
Description: 'Callback URL after successful authentication'
Type: String
Default: 'http://localhost:8080/callback'
LogoutURL:
Description: 'URL to redirect after logout'
Type: String
Default: 'http://localhost:8080/logout'
Resources:
MyUserPool:
Type: 'AWS::Cognito::UserPool'
Properties:
UserPoolName: !Sub '${ProjectName}-${Env}-UserPool'
AutoVerifiedAttributes:
- email
EmailVerificationMessage: 'Your verification code is {####}.'
EmailVerificationSubject: 'Your verification code'
MfaConfiguration: 'OFF'
Policies:
PasswordPolicy:
MinimumLength: 8
RequireUppercase: true
RequireLowercase: true
RequireNumbers: true
RequireSymbols: true
AdminCreateUserConfig:
AllowAdminCreateUserOnly: false
MyUserPoolClient:
Type: 'AWS::Cognito::UserPoolClient'
Properties:
UserPoolId:
Ref: 'MyUserPool'
ClientName: !Sub '${ProjectName}-${Env}-UserPoolClient'
GenerateSecret: false
SupportedIdentityProviders:
- 'COGNITO'
ExplicitAuthFlows:
- 'ALLOW_USER_SRP_AUTH'
- 'ALLOW_REFRESH_TOKEN_AUTH'
CallbackURLs:
- !Ref CallbackURL
LogoutURLs:
- !Ref LogoutURL
AllowedOAuthFlows:
- 'code'
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthScopes:
- 'openid'
MyUserPoolDomain:
Type: 'AWS::Cognito::UserPoolDomain'
Properties:
UserPoolId:
Ref: 'MyUserPool'
Domain: !Sub '${ProjectName}-${Env}-userpooldomain'
Outputs:
UserPoolId:
Description: "The ID of the created Cognito User Pool"
Value:
Ref: "MyUserPool"
UserPoolClientId:
Description: "The ID of the created Cognito User Pool Client"
Value:
Ref: "MyUserPoolClient"
UserPoolDomain:
Description: "The domain of the created Cognito User Pool"
Value:
!Sub "${ProjectName}-${Env}-userpooldomain.auth.${AWS::Region}.amazoncognito.com"
CallbackURL:
Description: "Callback URL after successful authentication"
Value:
!Ref "CallbackURL"
LogoutURL:
Description: "URL to redirect after logout"
Value:
!Ref "LogoutURL"
Reactでログインページに飛ぶ
環境変数を設定
必要なパラメーターはすべて先ほどアップロードしたCloudformationのOutputから取れます。
.envファイルはreactのルートディレクトリ入れてください。
.env
REACT_APP_COGNITO_DOMAIN=
REACT_APP_COGNITO_CLIENT_ID=
REACT_APP_COGNITO_CALLBACK_URL=
reactで環境変数を読み込めるようにします
/src/utils/cognitoConfigs.ts
export const getCognitoLoginUrl = (): string => {
const domain = process.env.REACT_APP_COGNITO_DOMAIN ?? 'your-default-domain';
const clientId = process.env.REACT_APP_COGNITO_CLIENT_ID ?? 'your-default-client-id';
const callbackUrl = process.env.REACT_APP_COGNITO_CALLBACK_URL ?? 'your-default-callback-url';
const redirectUri = encodeURIComponent(callbackUrl);
const scope = encodeURIComponent('openid'); // ここで必要なスコープを追加する
// URLを生成し、response_typeを'code'に設定する
return `https://${domain}/login?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;
};
これでgetCognitoLoginUrlという関数でurlを作成してアクセスをするだけでCognitoのHostUIに行くことができます。
Callbackのページを作る
ここでは敢えてコードで書くことでもないので解説だけにします。
Reactの環境変数で指定したURLにSignInが成功するとcodeというクエリーパラメーターと共にリダイレクトされます。
そのコードをクライアントシークレットを設定していない場合はcognitoのあるエンドポイントにリクエストを送るとアクセストークンを取得することできます。