AWS Cognito 그리고 토큰 인증

ian·2023년 12월 31일
0

인증

서비스의 권한이 주어진 사용자인지 확인하는 로그인 과정에 인증이 필요하다. HTTP는 프로토콜 특성 자체가 연결을 유지시키지 않는다. 따라서 HTTP 자체로는 요청 시마다 인증을 반복해야하는 문제점이 있다. 별도 추가적인 방법을 통해 인증을 유지해야 하는데 그 중에서도 토큰 인증에 대해 얘기하려고 한다. 로그인 성공 시 서버에서 클라이언트로 토큰을 발급하고 이를 Request 시마다 Header에 저장하여 인증/인가 시 사용한다.

토큰은 인증 유지에 사용된다. 인증 유지라는 개념은 사용자가 한번 로그인 한 이후 특정 시간 내에는 다시 로그인하지 않아도 사용자의 로그인 상태를 계속 유지시켜주는 개념이다. 인증 유지 개념이 없는 시스템이라면 사용자는 화면이 전환될 때 마다 매번 로그인을 해야 하거나 서버에서는 매번 요청에 대해 사용자가 이 요청을 처리할 수 있는 사용자인지에 대해 데이터베이스로부터 정보를 읽어와 확인해야 한다.

토큰 인증의 문제점

토큰이 탈취된 상황에 취약하다. 서버에서는 이미 발급된 토큰에 대해 아무런 제어도 불가하기 때문에, 유효기간이 지나기 전까지 특정 정보에 접근이 가능하다. 이러한 취약점을 보완하기 위한 것이 AccessTokenRefreshToken 개념이다. 기존의 AccessToken의 유효기간을 짧게 하고 RefreshToken이라는 새로운 토큰을 발급하면 AccessToken을 탈취당해도 상대적으로 피해를 줄일 수 있다.

AWS-Cognito

aws에서는 cognito라는 서비스를 통해 인증과 권한 부여 그리고 사용자 관리를 제공한다. Cognito의 구성 요소인 User Pool은 사용자 관리에 중점을 두고 있고, Identity Pool은 자격 증명의 관리와 AWS 리소스에 대한 권한 부여에 중점을 둔다.

User Pool 및 Identity Pool 사용법

  • User Pool: 사용자 등록, 로그인 및 그룹 관리
  • Identity Pool: 사용자에게 AWS 서비스에 대한 권한을 부여하기 위한 일회용 자격 증명을 생성

코드를 통해 알아보는 congito 시나리오

애플리케이션에서 사용자는 User Pool을 통해 인증하고, Identity Pool에서는 해당 사용자에게 AWS 자격 증명을 제공. Cognito User Pool과 Cognito Identity Pool을 사용하여 사용자를 인증하고, 인증된 사용자에게 Identity Pool을 통해 토큰을 얻어오는 시나리오

import { CognitoIdentity, CognitoIdentityServiceProvider } from 'aws-sdk';

const region = 'your-region';
const userPoolId = 'your-user-pool-id';
const clientId = 'your-client-id';
const identityPoolId = 'your-identity-pool-id';

const username = 'user@example.com';
const password = 'user-password';

// AWS SDK 인스턴스 생성
const identity = new CognitoIdentity({ region });
const serviceProvider = new CognitoIdentityServiceProvider({ region });

// 사용자 풀(User Pool)에 대한 로그인 정보 설정
const authData = {
  Username: username,
  Password: password,
};

const authDetails = new CognitoIdentityServiceProvider.AuthenticationDetails(authData);

const userData = {
  Username: username,
  Pool: new CognitoIdentityServiceProvider.CognitoUserPool({
    UserPoolId: userPoolId,
    ClientId: clientId,
  }),
};

const cognitoUser = new CognitoIdentityServiceProvider.CognitoUser(userData);

// 사용자 풀(User Pool)에서 로그인
cognitoUser.authenticateUser(authDetails, {
  onSuccess: (session) => {
    console.log('Authentication successful. Getting OpenID token...');

    // 사용자가 로그인한 세션을 사용하여 Identity Pool에서 OpenID 토큰 얻기
    const loginMap = {
      [`cognito-idp.${region}.amazonaws.com/${userPoolId}`]: session.getIdToken().getJwtToken(),
    };

    const getOpenIdTokenParams: CognitoIdentity.GetOpenIdTokenForDeveloperIdentityInput = {
      IdentityPoolId: identityPoolId,
      Logins: loginMap,
    };

    identity.getOpenIdTokenForDeveloperIdentity(getOpenIdTokenParams, (err, data) => {
      if (err) {
        console.error('Error getting OpenID token:', err);
      } else {
        console.log('Received OpenID token:', data);

        // OpenID 토큰을 사용하여 Identity Pool에서 AWS 자격 증명 얻기
        const getCredentialsParams: CognitoIdentity.GetCredentialsForIdentityInput = {
          IdentityId: data.IdentityId || '',
          Logins: loginMap,
        };

        identity.getCredentialsForIdentity(getCredentialsParams, (credErr, credData) => {
          if (credErr) {
            console.error('Error getting AWS credentials:', credErr);
          } else {
            console.log('Received AWS credentials:', credData);
          }
        });
      }
    });
  },
  onFailure: (err) => {
    console.error('Authentication failed:', err);
  },
  newPasswordRequired: (userAttributes, requiredAttributes) => {
    console.log('New password required.');
  },
});

https://docs.aws.amazon.com/ko_kr/cognitoidentity/latest/APIReference/Welcome.html

profile
Backend Developer

0개의 댓글