Auth0의 Management API를 M2M을 통해 사용해보기

Auth0의 매니지먼트 API를 M2M을 이용하여 좀 더 좁은 권한을 가지고 있는 액세스 토큰으로 사용하는 방법에 대해 알아보았습니다.
2021.03.15

Auth0란

인증 관련 Sass입니다. AWS의 Cognito와 같이 사용자의 인증이 주 기능이며, SSO, 커스텀할 수 있는 UI 제공 등 로그인 관련 개발 시간을 줄여주는 좋은 Sass입니다.

Auth0

Management API란?

Auth0를 사용하면서 자신이 가지고 있는 Auth0 계정의 정보들을 사용할 떄 사용합니다. 유저 정보, 로그 등 Auth0가 제공하는 API를 사용할 수 있습니다.

Auth0 API Docs

M2M이란?

M2M은 Machine to Machine의 줄임말으로 백엔드에서 Auth0의 management API를 사용하는 경우 액세스 토큰을 발급받아 사용하기 위해 만듭니다.

각 M2M 마다 권한을 다르게 줄 수 있습니다. 권한이 주어진 M2M으로 발급받은 액세스 토큰은 허용된 권한 내에서만 작동하기 때문에 권한을 나누기에 유용합니다.


작업의 흐름

흐름은 아래와 같습니다.

  1. M2M 생성 및 Management API에서 사용할 M2M에 특정 권한 주기
  2. 생성한 M2M 으로 Management API 사용할 액세스 토큰 획득
  3. 얻은 액세스 토큰으로 Management API 사용하기


액세스 토큰을 얻을 M2M 생성

Auth0 로그인 후 Apllications 탭에서 오른쪽 위 CREATE APPLICATION을 눌러주세요.

이름은 편하신 이름으로 설정해주세요.

맨 오른쪽의 Machine to Machine Applications을 선택한 후 아래의 CREATE 버튼을 눌러주세요.

사용할 매니지먼트 API를 선택해주시고,

아래의 scope 중 등록된 유저들의 이메일을 확인하기 위해 read:users을 사용해보겠습니다.

read:users를 선택하신 후 아래의 AUTORIZE를 눌러주시면 M2M이 생성되게 됩니다.

실제 사용법

APIs 탭에서 Auth0 Management API를 들어가면 보이는 Test 탭에서는 간단한 예제들이 나와있습니다.

cURL 및 여러 언어들의 예제가 나와있어서 실제 자신의 프로젝트에서 사용중인 언어 예제를 사용하시면 되겠습니다.

액세스 토큰 발급

현재 저는 Python으로 사용중이니 Python예제를 사용해보겠습니다.

예제에서 좀 더 사용하기 쉽게 변경한 코드는 아래와 같습니다.

import http.client
import json

conn = http.client.HTTPSConnection(domain)

payload = {
    'client_id': client_id,
    'client_secret': client_secret,
    'audience': audience,
    'grant_type': 'client_credentials'
    }
headers = {'content-type': 'application/json'}

conn.request('POST', '/oauth/token', json.dumps(payload), headers)

res = conn.getresponse()
data = res.read()

access_token = json.loads(data.decode('utf-8')).get('access_token')

return access_token

위의 코드에서 따로 필요한 부분은 domain, audience, M2M의 client id, m2m의 client secret입니다.

Domain은 자신의 Auth0 계젱에 대한 도메인 입니다. e.g) {계정 테넌트명}.{국가}.auth0.com

Audience는 jwt의 aud에 해당됩니다. e.g) 'ttps://{계정 테넌트명}.{국가}.auth0.com/api/v2/

Client id와 client secret은 M2M의 고유하게 가지는 값들입니다.

위의 테스트 예제위의 박스에서 사용할 M2M을 선택하시면 자동으로 입력되어지므로 참고하시면 편합니다.

위 코드는 액세스 토큰에 해당되는 스트링 값만 반환되어지게 됩니다.

Management API 사용

import http.client
import json

conn = http.client.HTTPSConnection(domain)

access_token = get_access_token(domain, client_id, client_secret, audience)
headers = {'authorization': f'Bearer {access_token}'}
conn.request('GET', f'https://{domain}/api/v2/users', headers=headers)

res = conn.getresponse()
data = res.read()
user_email_list = json.loads(data.decode('utf-8'))

return user_email_list

이제 액세스 토큰을 받게 되면 management API에 사용하면 됩니다.

https://{domain}/api/v2/users는 등록된 유저들의 정보를 볼 수 있는데요.

저 같은 경우는 등록된 유저들의 이메일들을 확인하기 위해 사용했습니다.

user_email_list[0]['email] 같이 사용하면 첫 번째로 들어있는 유저의 이메일을 확인할 수 있습니다.

더 많은 API에 대한 문서는 아래의 링크에서 확인해주세요.

Auth0 API Docs

팁으로는 왼쪽 위에 SET API TOKEN에 토큰을 설정해두면 DOCS에서 바로 확인해 볼 수 있어 편합니다.

전체 코드

import http.client
import json

domain = 'xxx.jp.auth0.com'
audience = 'https://xxx.jp.auth0.com/api/v2/'
client_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
client_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

auth0_config = (domain, audience, client_id, client_secret)

def get_access_token(auth0_config: tuple) -> str:
    domain, audience, client_id, client_secret = auth0_config

    conn = http.client.HTTPSConnection(domain)

    payload = {
        'client_id': client_id,
        'client_secret': client_secret,
        'audience': audience,
        'grant_type': 'client_credentials'
        }
    headers = {'content-type': 'application/json'}

    conn.request('POST', '/oauth/token', json.dumps(payload), headers)

    res = conn.getresponse()
    data = res.read()

    access_token = json.loads(data.decode('utf-8')).get('access_token')

    return access_token


def get_user_email(auth0_config: tuple) -> list:
    domain, audience, client_id, client_secret = auth0_config

    conn = http.client.HTTPSConnection(domain)

    access_token = get_access_token(auth0_config)
    headers = {'authorization': f'Bearer {access_token}'}
    conn.request('GET', f'https://{domain}/api/v2/users', headers=headers)

    res = conn.getresponse()
    data = res.read()
    user_email_list = json.loads(data.decode('utf-8'))

    return user_email_list


print(get_user_email(auth0_config)[0]['email'])
# xxx@classmethod.jp

물론 auth0_config의 내용들은 다른 곳으로 빼두거나 람다를 사용한다면 AWS SSM의 파라미터 스토어에 저장하는 편이 좋겠네요.