BLOG

[보안] 세분화된 권한 부여를 위한 방법: Amazon Cognito를 사용하여 자격 증명 토큰에 클레임 추가하기
작성일: 2022-06-15

Amazon Cognito를 사용하면 웹 및 모바일 애플리케이션에 회원가입, 로그인 및 액세스 제어를 빠르게 추가할 수 있습니다. 사용자가 성공적으로 로그인하면 Cognito는 사용자 인증을 위한 ID 토큰을 생성합니다. 이 서비스는 토큰 생성 전에 ID 토큰 클레임을 사용자 지정하는 데 사용할 수 있는 사전 토큰 생성 트리거를 제공합니다. 오늘 포스팅에서는 ID 토큰에 추가된 클레임을 사용하여 인증된 사용자에 대한 세부 정보를 제공하는 세분화된 권한 부여를 수행하는 방법을 알아보고자 합니다. 솔루션은 사전 토큰 생성 트리거를 사용하여 이러한 클레임을 ID 토큰에 추가합니다.

 

 

시나리오

 

엔지니어가 로그인하여 여러 프로젝트와 관련된 정보를 검토하는 건설 회사에서 사용하는 웹 애플리케이션이 있다고 가정해보겠습니다. 이 시나리오에서는 아키텍처를 설계하는 두 가지 다른 방법인 표준 설계와 보다 최적화된 설계를 살펴보겠습니다.

 

 

표준 아키텍처

 

이러한 애플리케이션에 대한 샘플 표준 아키텍처가 다양한 워크플로 단계에 대한 레이블과 함께 그림 1에 나와 있습니다.

 

  1. 사용자 인터페이스는 ReactJS (사용자 인터페이스 구축을 위한 JavaScript 라이브러리)를 사용하여 구현됩니다.
  2. 사용자 풀은 Amazon Cognito에서 구성됩니다.
  3. 백엔드는 Amazon API Gateway를 사용하여 구현됩니다.
  4. AWS Lambda 함수는 비즈니스 로직을 구현하기 위해 존재합니다.
  5. AWS Lambda CheckUserAccess 함수(5)는 사용자에게 AWS Lambda 함수(4)를 호출할 권한이 있는지 확인합니다.
  6. 프로젝트 정보는 Amazon DynamoDB 데이터베이스에 저장됩니다.

 

그림 1: 사용자의 projectID가 필요한 Lambda 함수는 GetProjectID Lambda 함수를 호출합니다.

 

 

이 시나리오에서 사용자는 여러 프로젝트의 정보에 액세스할 수 있으므로 여러 백엔드 함수는 요청된 정보를 제공하기 위해 CheckUserAccess Lambda 함수에 대한 호출(그림 1의 5단계)을 사용합니다. 이로 인해 동일한 사용자에 대해 함수에 대한 여러 호출이 발생하여 시스템에 대기 시간이 발생합니다.

 

 

최적화된 아키텍처

 

오늘은 그림 2와 같이 CheckUserAccess API 엔드포인트에 대한 호출을 크게 줄이는 최적화된 새로운 디자인을 소개해보겠습니다.

 

  1. 사용자가 로그인합니다.
  2. Amazon Cognito는 PretokenGenerationLambdaFunction-pretokenCognito 함수를 한 번만 호출합니다.
  3. PretokenGenerationLambdaFunction-pretokenCognito 함수는 DynamoDB 테이블에서 프로젝트 ID를 쿼리하고 해당 정보를 ID 토큰에 추가합니다.
  4. DynamoDB는 쿼리 결과를 PretokenGenerationLambdaFunction-pretokenCognito 함수에 전달합니다.
  5. 이 자격 증명 토큰은 Amazon API Gateway 엔드포인트를 호출하기 위한 권한 부여 헤더로 전달됩니다.
  6. 자격 증명 토큰 클레임의 정보는 추가 세분화된 권한 부여를 위해 비즈니스 로직이 포함된 Lambda 함수에서 사용됩니다. 따라서 CheckUserAccess 함수(7)를 호출할 필요가 없습니다.

 

개선된 아키텍처는 그림 2에 나와 있습니다.

 

그림 2. projectID를 가져와 ID 토큰의 사용자 지정 클레임에 삽입

 

 

이 접근 방식의 이점은 다음과 같습니다.

 

  1. DynamoDB 테이블에서 프로젝트 ID를 가져오기 위한 호출 수가 줄어들어 전체 지연 시간이 줄어듭니다.
  2. CheckUserAccess Lambda 함수에 대한 종속성 이 비즈니스 로직에서 제거되었습니다. 이렇게 하면 다이어그램에 표시된 것처럼 아키텍처의 결합이 줄어듭니다.

 

여기서 제공된 코드 샘플의 사용자 인터페이스는 단순화를 위해 사용자 컴퓨터에서 로컬로 실행됩니다.

 

 

코드 샘플

 

코드와 AWS CloudFormation 템플릿이 포함된 zip 파일을 다운로드하여 이 솔루션을 구현할 수 있습니다. 이 솔루션을 설명하기 위해 제공하는 코드는 다음 섹션에서 설명하도록 하겠습니다.

 

 

전제 조건

 

이 솔루션을 배포하기 전에 먼저 다음을 수행해야 합니다.

 

  1. Python 3.7 이상을 다운로드하여 설치합니다.
  2. 다음 pip 명령을 사용하여 Python용 AWS SDK(Boto3) 라이브러리를 다운로드합니다 .
    핍 설치 boto3
  3. 다음 pip 명령을 사용하여 argparse 패키지를 설치합니다 .
    핍 설치 argparse
  4. AWS 명령줄 인터페이스(AWS CLI) 를 설치합니다.
  5. AWS CLI 를 구성합니다.
  6. Python용 코드 편집기를 다운로드합니다. 이 포스트에서는 Visual Studio Code 를 사용했습니다.
  7. Node.js 를 설치합니다.

 

 

인프라 설명

 

오늘 제공된 코드는 AWS 계정에 다음 인프라를 설치합니다.

 

 

 

솔루션 배포

 

이 섹션에서는 인프라를 배포하고, 트리거 구성을 저장하고, Cognito 사용자 풀에 사용자를 추가하고, 웹 애플리케이션을 실행하는 방법을 설명해 보겠습니다.

솔루션 인프라를 배포하려면

  1. zip 파일을 컴퓨터에 다운로드합니다. addclaimstoidtoken 폴더 의 readme.md 파일에는 코드의 주요 파일을 설명하는 표가 포함되어 있습니다.
  2. 디렉토리를 addclaimstoidtoken. cd addclaimstoidtoke으로 변경합니다.
  3. stackInputs.json을 검토합니다. userPoolDomainName 매개변수의 값을 선택한 임의의 고유 값으로 변경합니다. 이 예에서는 pretokendomainname을 Amazon Cognito 도메인 이름으로 사용합니다. 선택한 고유한 도메인 이름으로 변경해야 합니다.
  4. 다음 Python 스크립트를 실행하여 인프라를 배포합니다.
    python3 setup_pretoken.py

 

CloudFormation 스택 생성이 완료되면 그림 3과 같이 생성된 인프라의 세부 정보가 표시되어야 합니다.

 

그림 3: 인프라 세부 정보

 

 

이제 Amazon Cognito 사용자 풀에 사용자를 추가할 준비가 되었습니다.

 

Cognito 사용자 풀에 사용자를 추가하려면

  1. Cognito 사용자 풀에 사용자를 추가하고 DynamoDB 저장소를 구성하려면 addclaimstoidtoken 디렉터리에서 Python 스크립트를 실행합니다.
    python3 add_user_info.py
  2. 이 스크립트는 한 명의 사용자를 추가합니다. 사용자의 사용자 이름, 이메일 및 비밀번호를 제공하라는 메시지가 표시됩니다.

참고: 이것은 샘플 코드이기 때문에 다단계 인증과 같은 Cognito의 고급 기능을 사용할 수 없습니다. 프로덕션 애플리케이션에 대해 이러한 기능을 활성화하는 것이 좋습니다.

addUserInfo.py 스크립트는 두 가지 작업을 수행합니다.

    • Cognito 사용자 풀에 사용자를 추가합니다.

 

그림 4: Cognito 사용자 풀에 추가된 사용자

 

    • DynamoDB 테이블에 샘플 데이터를 추가합니다.

 

그림 5: UserInfoTable이라는 DynamoDB 테이블에 추가된 샘플 데이터

 

이제 애플리케이션을 실행하여 사용자 지정 클레임 추가를 확인할 준비가 되었습니다.

웹 애플리케이션을 실행하려면

 

  1. 디렉토리를 pre-token-web-app 디렉토리로 변경하고 다음 명령을 실행하세요.
    cd pre-token-web-app
  2. 이 디렉토리에는 ID 토큰의 세부 정보를 표시하는 ReactJS 웹 응용 프로그램이 포함되어 있습니다. 터미널에서 다음 명령을 실행하여 ReactJS 애플리케이션을 실행합니다.
    npm install
    npm start

그러면 로그인 버튼 이 표시된 기본 브라우저 창에서 http://localhost:8081 이 열립니다.

 

그림 6: 브라우저가 URL http://localhost:8081로 열립니다.

 

3. 로그인 버튼을 선택합니다. 그렇게 하면 Cognito에서 호스팅하는 로그인 화면이 표시됩니다. Cognito 사용자 풀에 사용자를 추가하려면 절차의 1단계에서 addUserInfo.py 스크립트를 사용하여 생성한 사용자 ID로 웹 사이트에 로그인 합니다.

 

그림 7: Cognito 호스팅 로그인 화면에서 자격 증명 입력

 

4. 로그인에 성공하면 다음 화면에 URL의 ID 및 액세스 토큰이 표시됩니다. 토큰 세부 정보 표시 단추를 선택하여 사용자 지정 클레임이 토큰에 추가되었는지 확인하기 위해 토큰 세부 정보를 표시할 수 있습니다.

 

그림 8: 브라우저에 표시된 토큰 세부 정보

 

 

시나리오 밖에서는 무슨 일이?

 

이 웹 애플리케이션에서 다음 단계가 시나리오 밖에서 발생했습니다.

 

  1. 터미널 명령줄에서 npm start 명령을 실행하면 package.json 에서 react-scripts start 명령이 실행됩니다 . 포트 번호(8081)는 pre-token-web-app.env 파일에 구성되었습니다. 이것은 URL http://localhost:8081 의 기본 브라우저에서 app.js 에 정의된 웹 애플리케이션을 열었습니다.
  2. 로그인 버튼은 constants.js 파일에 정의된 URL로 이동하도록 구성됩니다. constants.js 파일 은 setup_pretoken.py 스크립트 실행 중에 생성되었습니다. 이 URL은 Cognito에서 호스팅하는 기본 로그인 사용자 인터페이스를 가리킵니다.
  3. 로그인 정보(사용자 이름 및 암호)를 제공하면 Amazon Cognito가 사용자를 인증했습니다. 토큰 세트(ID 토큰 및 액세스 토큰)를 생성하기 전에 Cognito는 먼저 토큰 생성 전 Lambda 트리거를 호출했습니다. 이 Lambda 함수에는 DynamoDB 데이터베이스에 연결하는 코드가 있습니다. 그러면 Lambda 함수는 userInfo 테이블에 저장된 사용자에 대한 프로젝트 정보에 액세스할 수 있습니다. Lambda 함수는 이 프로젝트 정보를 읽고 웹 애플리케이션에 전달된 자격 증명 토큰에 추가했습니다.

 

 

람다 함수 코드

 

const AWS = require(“aws-sdk”);

 

// Create the DynamoDB service object

var ddb = new AWS.DynamoDB({ apiVersion: “2012-08-10” });

 

// PretokenGeneration Lambda

exports.handler = async function (event, context) {

    var eventUserName = “”;

    var projects = “”;

 

    if (!event.userName) {

        return event;

    }

 

    var params = {

        ExpressionAttributeValues: {

            “:v1”: {

                S: event.userName

            }

        },

        KeyConditionExpression: “userName = :v1”,

        ProjectionExpression: “projects”,

        TableName: “UserInfoTable”

    };

 

    event.response = {

        “claimsOverrideDetails”: {

            “claimsToAddOrOverride”: {

                “userName”: event.userName,

                “projects”: null

            },

        }

    };

 

    try {

        let result = await ddb.query(params).promise();

        if (result.Items.length > 0) {

            const projects = result.Items[0][“projects”][“S”];

            console.log(“projects = ” + projects);

            event.response.claimsOverrideDetails.claimsToAddOrOverride.projects = projects;

        }

    }

    catch (error) {

        console.log(error);

    }

 

    return event;

};

Lambda 함수의 코드는 다음과 같습니다.

 

  1. 로그인에 성공하면 Amazon Cognito가 앱 클라이언트 설정 섹션에 지정된 URL로 리디렉션하고 URL에 토큰을 추가했습니다.
  2. 웹 페이지가 URL에서 토큰을 감지하고 토큰 세부 정보 표시 버튼을 표시했습니다. 버튼을 선택하면 웹 페이지는 URL의 토큰을 읽고 토큰을 디코딩하고 관련 텍스트 상자에 정보를 표시합니다.
  3. 디코딩된 ID 토큰 상자에는 PretokenGenerationLambdaFunction-pretokenCognito 트리거에 의해 추가된 projectID를 표시하는 프로젝트라는 사용자 지정 클레임이 표시됩니다.

 

 

애플리케이션에서 샘플 코드를 사용하는 방법

 

다음 수정 사항과 함께 이 샘플 코드를 사용하는 것이 좋습니다.

 

  1. 제공된 코드는 사용자 지정 클레임 정보를 사용하는 API 게이트웨이 및 Lambda 함수를 구현하지 않습니다. 필요한 Lambda 함수를 구현하고 이벤트 객체에 대한 사용자 지정 클레임을 읽어야 합니다. 이 이벤트 개체는 권한 부여 데이터를 포함하는 JSON 형식의 개체입니다.
  2. ReactJS 기반 사용자 인터페이스는 Amazon Simple Storage Service(Amazon S3) 버킷에서 호스팅되어야 합니다.
  3. 사용자의 projectId는 토큰에서 사용할 수 있습니다. 따라서 토큰이 Authorization 트리거에 의해 백 엔드로 전달되면 이 사용자 지정 클레임 정보를 사용하여 해당 사용자의 프로젝트와 관련된 작업을 수행할 수 있습니다. 예를 들어, 프로젝트와 관련된 해당 사용자의 모든 작업 항목을 가져옵니다.
  4. 토큰은 1시간 동안 유효하므로 사용자 지정 클레임 정보의 정보는 해당 시간 동안 사용자 인터페이스에서 사용할 수 있습니다.
  5. AWS Amplify 라이브러리를 사용하여 웹 애플리케이션과 Amazon Cognito 간의 통신을 간소화할 수 있습니다. AWS Amplify 는 웹 애플리케이션에 대한 토큰 보존 및 갱신 토큰 메커니즘을 처리할 수 있습니다. 이렇게 하면 URL에 토큰을 표시할 필요도 없습니다.
  6. Amazon Cognito를 사용하여 사용자를 관리하고 인증하는 경우 권한 부여자에서 인증 코드를 작성할 필요가 없기 때문에 Amazon Cognito 사용자 풀을 사용하여 API에 대한 액세스를 제어하는 ​​것이 더 쉽습니다.
  7. Lambda 권한 부여자를 사용하기로 결정한 경우 API Gateway Lambda 권한 부여자를 생성하는 단계 주제에서 다음 중요 정보를 참고하십시오. “프로덕션 코드에서는 권한 부여 전에 사용자를 인증해야 할 수 있습니다. 그렇다면 해당 공급자에 대한 설명서의 지시에 따라 인증 공급자를 호출하여 Lambda 함수에 인증 로직을 추가할 수도 있습니다.”
  8. 사용자 지정 클레임을 기반으로 최종 승인(단순한 토큰 유효성이 아님) 결정이 내려진 경우 Lambda 권한 부여자가 권장됩니다.

 

 

결론

 

오늘 포스팅에서는 Amazon Cognito 사전 토큰 생성 트리거에 의해 생성된 자격 증명 토큰에 저장된 클레임을 사용하여 백엔드에 저장된 데이터를 기반으로 세분화된 권한 부여를 구현하는 방법을 알아보았습니다. 이 솔루션은 지연 시간을 줄이고 성능을 향상시키는 데 도움이 될 수 있습니다.

 

사전 토큰 생성 Lambda 트리거에 대한 자세한 내용은 Amazon Cognito 개발자 안내서를 참조하십시오.

 

원문URL: https://aws.amazon.com/ko/blogs/security/use-amazon-cognito-to-add-claims-to-an-identity-token-for-fine-grained-authorization/

메가존클라우드 TechBlog는 AWS BLOG 영문 게재 글이나 관련 기사 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아 정기적으로 게재하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.