AWS/AWS 공부

[CDK] Cognito 개념 및 생성

Yuco 2024. 3. 17. 22:37

Cognito

AWS Cognito는 웹과 모바일 앱에 대한 인증과 권한 부여 및 사용자 관리를 제공하고, 사용자는 사용자 이름과 패스워드를 사용하여 직접 로그인하거나 Facebook, Amazon, Google 또는 Apple 같은 타사를 통해 로그인(OAuth)할 수 있습니다.

 

Cognito를 사용하면 좋은 점

  • 사용자를 손쉽게 관리할 수 있다.
  • 뛰어난 확장성
    • Cognito를 사용하면 사용자 디렉토리를 손쉽게 생성할 수 있습니다.
    • 이 디렉토리는 완전 관리형으로, 수억명까지 쉽게 확장됩니다.
  • 강화된 안전
    • AWS의 안전에 대한 경험이 녹아들어 있습니다. 
    • 이메일 및 SMS 인증, MFA 인증 등의 기능을 손쉽게 추가할 수 있습니다.
  • 모바일, 서버리스와 궁합이 잘 맞다. 

 

Cognito는 사용자 풀(User Pools)과 자격 증명 풀(Identity Pools)로 구성되어 있습니다.

사용자 풀은 사용자의 회원가입 및 로그인 옵션을 제공하고, 자격 증명 풀은 사용자 풀에 저장된 정보를 바탕으로 회원가입 또는 로그인에 성공한 사용자에게 AWS 서비스에 액세스할 수 있는 권한을 부여할 수 있습니다.

이 둘은 별도로 또는 함께 사용할 수 있습니다.

 

사용자 풀(User pool)

사용자 풀은 Cognito에 가입한 사용자에 대한 정보를 가지고 있는 하나의 사용자 데이터베이스 같은 역할을 합니다.

사용자 풀을 통해 회원가입과 로그인 기능을 사용할 수 있으며, 사용자 인증을 완료하면 Cognito는 JWT(JSON Web Token)를 사용자에게 반환하게 됩니다.

이 JWT는 API Gateway에서 자격 증명으로 사용되거나 AWS의 다른 자격 증명을 교환할 수 있습니다.

또한 사용자 풀에 있는 모든 사용자는 각각의 프로필을 보유하고 있으며, SDK를 통해 접근할 수 있습니다.

 

사용자 풀의 제공 기능

  • 회원가입 및 로그인 서비스
  • 사용자 로그인을 위한 내장 커스텀 웹 UI
  • Facebook, Google, Amazon, Apple을 통한 소셜 로그인 및 사용자 풀의 SAML 및 OpenID Connect(OIDC)를 통한 로그인 지원
  • 사용자 및 사용자 프로필 관리
  • 멀티 팩터 인증(MFA), 자격 증명 검증, 계정 탈취 보호, 전화 및 이메일 확인과 같은 보안 기능 제공
  • AWS Lambda 트리거를 이용한 Cognito의 인증 과정 등의 커스터마이징

 

자격 증명 풀(Identity pool)

자격 증명 풀은 사용자의 임시 AWS 자격 증명을 만들어 S3, DynamoDB등의 다른 AWS 서비스에 접근권한을 부여할 수 있습니다. 자격 증명풀은 다음과 같은 사용자를 포함할 수 있습니다.

  • Amazon Cognito user pools에 등록된 사용자
  • Facebook, Google, Amazon, Apple등의 소셜 로그인을 통해 인증된 사용자
  • SAML 및 OpenID Connect(OIDC)를 통해 인증된 사용자

 

아래는 CDK deploy를 통해 user pool 과 identity pool을 생성하는 CDK 스택입니다. 

import {Construct} from 'constructs'
import * as cdk from 'aws-cdk-lib'
import * as cognito from 'aws-cdk-lib/aws-cognito'

interface CustomStackProps {
  userPoolId: string
  userPoolName: string
  appClientId: string
  appClientName: string
  identityPoolId: string
  identityPoolName: string
}

export class CognitoStack extends cdk.Stack {
  constructor(scope: Construct, id: string, customProps: CustomStackProps, props?: cdk.StackProps) {
    super(scope, id, props)

    const userPool = new cognito.UserPool(this, customProps.userPoolId, {
      userPoolName: customProps.userPoolName,
      selfSignUpEnabled: true,
      signInCaseSensitive: true,
      signInAliases: {
        username: true,
        email: true,
      },
      standardAttributes: { // 사용자 등록 시 필요한 속성
        email: {
          required: true,
          mutable: true,
        },
      },
      passwordPolicy: {  // 비밀번호 정책 설정
        minLength: 7,
        requireLowercase: true,
        requireUppercase: false,
        requireDigits: true,
        requireSymbols: true,
        tempPasswordValidity: cdk.Duration.days(7),
      },
      mfa: cognito.Mfa.OFF,
      accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      email: cognito.UserPoolEmail.withCognito('no-reply@verificationemail.com'),
      enableSmsRole: false,
      snsRegion: 'ap-northeast-1',
    })

    // 인증을 위해 애플리케이션을 사용자 풀에 연결하는 데 사용, 인증 정의가 다른 동일한 풀에 대해 여러 클라이언트를 가질 수 있음
    const userPoolClient = new cognito.UserPoolClient(this, customProps.appClientId, {
      userPool: userPool,
      userPoolClientName: customProps.appClientName,
      generateSecret: true,
      authFlows: {
        userSrp: true,
        adminUserPassword: true,
      },
      authSessionValidity: cdk.Duration.minutes(3),
      refreshTokenValidity: cdk.Duration.days(60),
      accessTokenValidity: cdk.Duration.minutes(60),
      idTokenValidity: cdk.Duration.minutes(60),
      enableTokenRevocation: true,
      preventUserExistenceErrors: true,
    })
    
    // Cognito Identity Pool은 애플리케이션에 대한 인증 및 권한 부여를 담당
    const identityPool = new cognito.CfnIdentityPool(this, customProps.identityPoolId, {
      identityPoolName: customProps.identityPoolName,
      allowUnauthenticatedIdentities: false,
      cognitoIdentityProviders: [
        {
          clientId: userPoolClient.userPoolClientId,
          providerName: userPool.userPoolProviderName,
        },
      ],
    })

    const identityPoolArn = `arn:aws:cognito-identity:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:identitypool/${identityPool.ref}`;

    // AWS CDK 스택의 출력(Output)으로 값을 제공하기 위해 사용되는 클래스, Pool의 식별자 값을 출력하고 활용하고자 할 때는 해당 코드를 작성
    new cdk.CfnOutput(this, 'userPoolId', {
      value: userPool.userPoolId,
    })
    new cdk.CfnOutput(this, 'userPoolClientId', {
      value: userPoolClient.userPoolClientId,
    })
    new cdk.CfnOutput(this, 'identityPoolId', {
      value: identityPool.ref,
    })
    new cdk.CfnOutput(this, 'userPoolArn', {
      value: userPool.userPoolArn,
    })
    new cdk.CfnOutput(this, 'identityPoolArn', {
      value: identityPoolArn,
    })
  }
}

 

아래 cdk.App()는 AWS CDK (Cloud Development Kit)에서 애플리케이션을 정의하는 데 사용되는 기본 애플리케이션 객체로서, 이 코드를 사용하여 AWS CDK를 사용하여 애플리케이션을 정의하고 배포할 수 있게 합니다. 

 

CDK 배포 단계는 간단하게 아래와 같이 설명할 수 있습니다. 

1. AWS CDK를 설치하고 프로젝트를 초기화합니다.

2. CDK 코드를 작성하여 애플리케이션을 정의합니다.

3. CDK CLI(Command Line Interface)를 사용하여 애플리케이션을 배포합니다. 

 

아래 CDK 객체를 생성해 코그니토를 생성할 수 있습니다. CustomStackProps를 설정함으로써, 원하는 이름으로 코그니토를 생성할 수 있습니다. account와 region은 AWS 계정 정보를 넣어주시면 됩니다. 

 

import 'source-map-support/register'
import * as cdk from 'aws-cdk-lib'
import {CognitoStack} from '../lib/cognitoStack'

require('dotenv').config()

const cognitoName = `new-cognito`


const app = new cdk.App()

new CognitoStack(app, cognitoName, {
  userPoolId: `${cognitoTenantName}-user-pool`,
  userPoolName: `${cognitoTenantName}-user-pool`,
  appClientId: `${cognitoTenantName}-app-client`,
  appClientName: `${cognitoTenantName}-app-client`,
  identityPoolId: `${cognitoTenantName}-identity-pool`,
  identityPoolName: `${cognitoTenantName}-identity-pool`,
}, {
      account: process.env.ACCOUNT,
      region: process.env.REGION,
    }
)