認証・認可周りのOSS・SaaSの調査として、今回はAuth0の認可モデルについて動作確認をしながら整理した。
まとめ
- 基本的な思想は、認証・認可の結果をアクセストークン(JWT形式の署名付きトークン)に埋め込み(ここまでがAuth0の責務)、各Resource Server (API) にてトークンを検証して埋め込まれた情報を元に処理をする、というものとなっている。
- Resource Serverで利用可能なトークンを発行するには、Authorization Requestの
audience
パラメータ(Auth0独自仕様)にResource Serverの識別子を指定する。これによりResource ServerのScopeの検証処理が実行される。 - ビルトインの認可ルールとしてRBACが利用できる。Resource Serverの
enforce_policies
をtrue
に設定することで有効化できる。※ その他にも独自の認可ルールをActionとして登録することができる。(参考:Auth0 Actions)- UserもしくはUserに設定したRoleに対して、利用可能なScopeを定義する。Authorization Requestの
scope
パラメータにて要求されたScopeと利用可能なScopeの積部分がアクセストークンのscope
クレームに設定される。 - 追加でResource Serverの
token_dialect
をaccess_token_authz
に設定した場合、要求されたScopeに関わらず利用可能なScopeがアクセストークンのpermissions
クレームに設定される。
- UserもしくはUserに設定したRoleに対して、利用可能なScopeを定義する。Authorization Requestの
- 1つのトークンは1つのResource Serverのみしか対象に設定できない制約がある。(
audience
パラメータには1つの識別子のみ設定可能。)複数のResource Serverでトークンを共有したい場合は1つとして登録する必要がある。(参考:Configure Logical API for Multiple APIs)
動作確認内容
(作業はWebコンソールではなく、Management APIをcurlで呼び出して行う。)
Management API用のトークンとテナントのURIを設定する。
TOKEN=eyJ...
BASE_URI=https://xxx.xx.auth0.com
Resource Server (API) を作成する。
RESOURCE_SERVER_ID=$(curl -s -X POST ${BASE_URI}/api/v2/resource-servers \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq -r .id
{
"identifier": "resource-server-1",
"scopes": [
{ "value": "scope-1" }, { "value": "scope-2" }, { "value": "scope-3" }
]
}
EOF
)
Client (Application) を作成する。curlから試せるようにPassword Grantを有効化する。
RESULT=$(curl -s -X POST ${BASE_URI}/api/v2/clients \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq .
{
"name": "client 1",
"grant_types": [ "password" ]
}
EOF
)
CLIENT_ID=$(echo ${RESULT} | jq -r .client_id)
CLIENT_SECRET=$(echo ${RESULT} | jq -r .client_secret)
Role(test role 1)を作成する。
ROLE_ID=$(curl -s -X POST ${BASE_URI}/api/v2/roles \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq -r .id
{ "name": "test role 1" }
EOF
)
Roleに利用可能なScope (Permission) を割り当てる。
curl -s -X POST ${BASE_URI}/api/v2/roles/${ROLE_ID}/permissions \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq .
{
"permissions": [
{
"resource_server_identifier": "resource-server-1",
"permission_name": "scope-1"
},
{
"resource_server_identifier": "resource-server-1",
"permission_name": "scope-2"
}
]
}
EOF
Userを作成する。
EMAIL=user-1@example.com
PASSWORD=$(echo $RANDOM | sha256sum | base64)
USER_ID=$(curl -s -X POST ${BASE_URI}/api/v2/users \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq -r .user_id
{
"email": "${EMAIL}",
"password": "${PASSWORD}",
"connection": "Username-Password-Authentication"
}
EOF
)
UserにRoleを割り当てる。
curl -s -X POST ${BASE_URI}/api/v2/users/${USER_ID}/roles \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq .
{
"roles": [ "${ROLE_ID}" ]
}
EOF
この状態でアクセストークンを発行してみる。
RESPONSE=$(curl -s -X POST \
"${BASE_URI}/oauth/token" \
-d "grant_type=password" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "username=${EMAIL}" \
-d "password=${PASSWORD}" \
-d "scope=openid scope-1 abc" \
-d "audience=resource-server-1"
)
echo $RESPONSE | jq .
jq -R 'fromjson | .access_token | split(".") | .[1] | @base64d | fromjson' <<< $RESPONSE
→ aud
クレームにResource Serverの識別子、scope
クレームにAuthorization Requestで要求したものが設定されている。
{
"aud": [
"resource-server-1",
"https://xxx.xx.auth0.com/userinfo"
],
"scope": "openid profile email address phone scope-1",
...
}
Resource Serverの下記の設定を変更して、再度アクセストークンを発行する。
-
enforce_policies
をtrue
に設定する。(Enable RBACを有効化する。) -
token_dialect
をaccess_token_authz
に設定する。(Add Permissions in the Access Tokenを有効化する。)
curl -s -X PATCH ${BASE_URI}/api/v2/resource-servers/${RESOURCE_SERVER_ID} \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @- << EOF | jq .
{
"enforce_policies": true,
"token_dialect": "access_token_authz"
}
EOF
→ permissions
クレームにUserが利用可能な全てのScopeが追加で設定されるようになる。
{
"aud": [
"resource-server-1",
"https://xxx.xx.auth0.com/userinfo"
],
"scope": "openid profile email address phone scope-1",
"permissions": [
"scope-1",
"scope-2"
]
}