目的
・AWS上の静的Webサイトホスティングを有効にしたS3をCloudFrontで公開。
・Cognito認証を実装。
前提条件
・SAMを使用してAWS上にリソースを作成する。
・Lambda@Edgeを使用して実装する。
完成イメージ
SAMテンプレート
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
# ... 他のリソースは変更なし ...
WebBucketDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
DefaultCacheBehavior:
TargetOriginId: WebBucketOrigin
Compress: true
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
LambdaFunctionAssociations:
- EventType: viewer-request
LambdaFunctionARN: !Ref CognitoLambdaEdge.Version
CachePolicyId: !Ref WebBucketCachePolicy
OriginRequestPolicyId: !Ref WebBucketOriginRequestPolicy
PriceClass: PriceClass_200
DefaultRootObject: index.html
Enabled: true
Origins:
- DomainName: !GetAtt WebBucket.RegionalDomainName
Id: WebBucketOrigin
OriginAccessControlId: !GetAtt WebBucketOriginAccessControl.Id
S3OriginConfig:
OriginAccessIdentity: ''
# ... 他のリソースは変更なし ...
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Sub ${AWS::StackName}-user-pool
AdminCreateUserConfig:
AllowAdminCreateUserOnly: false
AliasAttributes:
- email
- preferred_username
AutoVerifiedAttributes:
- email
EnabledMfas:
- SOFTWARE_TOKEN_MFA
MfaConfiguration: 'ON'
Policies:
PasswordPolicy:
MinimumLength: 8
RequireUppercase: true
RequireLowercase: true
RequireNumbers: true
RequireSymbols: true
TemporaryPasswordValidityDays: 7
Schema:
- Name: email
AttributeDataType: String
Mutable: true
Required: true
- Name: preferred_username
AttributeDataType: String
Mutable: true
Required: false
- Name: name
AttributeDataType: String
Mutable: true
Required: true
StringAttributeConstraints:
MinLength: '1'
MaxLength: '100'
VerificationMessageTemplate:
DefaultEmailOption: CONFIRM_WITH_LINK
EmailSubject: メールアドレスの確認
EmailMessage: 'あなたのメールアドレスを確認するには、以下のリンクをクリックしてください: {####}'
CognitoUserPoolDomain:
Type: AWS::Cognito::UserPoolDomain
Properties:
Domain: !Sub ${AWS::StackName}-${AWS::AccountId}
UserPoolId: !Ref CognitoUserPool
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: !Sub ${AWS::StackName}-client
UserPoolId: !Ref CognitoUserPool
CallbackURLs:
- !Sub https://${WebBucketDistribution.DomainName}
SupportedIdentityProviders:
- COGNITO
AllowedOAuthFlows:
- code
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthScopes:
- openid
CognitoLambdaEdgeRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${AWS::StackName}-CognitoLambdaEdgeRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- edgelambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: CognitoLambdaEdgePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- Effect: Allow
Action:
- lambda:GetFunction
- lambda:EnableReplication*
- iam:CreateServiceLinkedRole
Resource: '*'
CognitoLambdaEdge:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: CognitoLambdaEdge
CodeUri: lambda/CognitoLambdaEdge
Handler: index.handler
Runtime: nodejs18.x
Timeout: 5
Tracing: Active
AutoPublishAlias: live
Role: !GetAtt CognitoLambdaEdgeRole.Arn
Outputs:
WebsiteURLonCF:
Description: URL for website hosted on CloudFront
Value: !GetAtt WebBucketDistribution.DomainName
①WebBucketDistribution(CloudFrontディストリビューション)
・LambdaFunctionAssociations:Lambda@Edgeとの関連付け
②CognitoUserPool(Cognitoユーザプール)
・AdminCreateUserConfig:ユーザがサインアップできるよう設定(AllowAdminCreateUserOnly: false)
・AliasAttributes:ユーザが「user_name」以外でのサインインを可能にする
(email, preferred_username)
・AutoVerifiedAttributes:ユーザー登録時に自動的に検証される属性を指定(email)
・EnabledMfas:User Pool で利用可能な多要素認証(MFA)の方法を指定(SOFTWARE_TOKEN_MFA: TOTP (Time-based One-Time Password) アプリを使用した MFA)
・MfaConfiguration:ユーザプール全体の MFA(多要素認証)ポリシーを定義
・PasswordPolicy:パスワードポリシーの設定
a. 最小長の設定(MinimumLength: 8)
b. 大文字必須(RequireUppercase: true)
c. 小文字必須(RequireLowercase: true)
d. 数字必須(RequireNumbers: true)
e. 記号必須(RequireSymbols: true)
f. 一時パスワードの有効期限(日数)(TemporaryPasswordValidityDays: 7)
・Schema:ユーザープロファイルに保存される属性(フィールド)を定義
a. Name: 属性の名前
b. AttributeDataType: データ型(String, Number, DateTime, Boolean など)
c. Mutable: 属性の変更可否
d. Required: 属性が必須かどうか
e. StringAttributeConstraints: 文字列属性の制約(最小/最大長など)
f. NumberAttributeConstraints: 数値属性の制約(最小/最大値など)
・VerificationMessageTemplate:検証のために送信されるメッセージのカスタマイズ
③CognitoUserPoolDomain(Cognitoユーザプールドメイン)
④CognitoUserPoolClient(Cognitoユーザプールクライアント)
・CallbackURLs:認証プロセス完了後、Cognito が認証コードまたはトークンをリダイレクトする先のURL
・SupportedIdentityProviders:ユーザプールクライアントが使用できる認証プロバイダーを指定
・AllowedOAuthFlows:クライアントアプリケーションが使用できる OAuth 2.0 認証フローを定義
・AllowedOAuthFlowsUserPoolClient:ユーザプールクライアントに対して OAuth 2.0 フローの使用を許可(= true)
・AllowedOAuthScopes:クライアントアプリケーションがアクセスを要求できる OAuth スコープを指定
Lambda
const { Authenticator } = require('cognito-at-edge');
const authenticator = new Authenticator({
region: 'user pool regionを指定',
userPoolId: 'user pool IDを指定',
userPoolAppId: 'user pool app client IDを指定',
userPoolDomain: 'user pool domainを指定',
});
exports.handler = async (request) => authenticator.handle(request);
動作確認
①Webサイトへアクセス
・サインイン画面が表示されることを確認
参考(前回記事)