0
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?

【AWS×Webアプリ】CloudFront+Cognito認証(SAM)

Last updated at Posted at 2024-07-08

目的

・AWS上の静的Webサイトホスティングを有効にしたS3をCloudFrontで公開。
・Cognito認証を実装。

前提条件

・SAMを使用してAWS上にリソースを作成する。
・Lambda@Edgeを使用して実装する。

完成イメージ

image.png

SAMテンプレート

template.yaml
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

index.js
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サイトへアクセス
・サインイン画面が表示されることを確認
image.png

②サインアップ
image.png
image.png

③メールアドレスの検証
image.png
image.png

④サインイン
image.png

⑤MFAの登録
image.png

⑥Webサイトへアクセス(完了)
image.png

⑦MFA(次回サインイン後から)
image.png

参考(前回記事)

0
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
0
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?