Open2
Managed Identity から取得したトークンでアプリケーションの認証をしてみる

トークンの取得方法と含まれるクレーム
Managed Identity を有効にした VM 上で以下のコマンドを実行するとトークンを取得できる。
curl "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=api%3A%2F%2Fbd239da0-3acf-424c-95f8-41518d3a3079" -H "Metadata:true"
上記の例のようにresource
に指定できるリソースは、Azure のサービスだけでなく、ME-ID のアプリ登録したアプリの ID も指定できる。
つまり、エンタープライズ アプリケーションで登録されているアプリの識別子 URI
をリソースとして指定できる。
ただし、リソースの種類によって、トークンに含まれるクレームが異なる。特に、Managed Identity が割り当てられたリソースの識別子であるxms_mirid
は、含まれるリソースの種類、含まれないリソースの種類がある。
以下は、resource
に、https://appservice.azure.com
を指定した時のトークンをデコードした例。
{
"aud": "https://appservice.azure.com",
"iss": "https://sts.windows.net/<tenant id>/",
"iat": 1699635590,
"nbf": 1699635590,
"exp": 1699722290,
"aio": "E2VgYGh6ssKNcXFN/Pv5qdNuzRedCQA=",
"appid": "d090b38d-59ff-4c47-b759-f70024c19814",
"appidacr": "2",
"idp": "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/",
"oid": "c7c89e9a-a179-47b2-9273-f57c5dcaed96",
"rh": "0.ARoAv4j5cvGGr0GRqy180BHbR3wK-qu2pjZHgxBYVVCHh80aAAA.",
"sub": "c7c89e9a-a179-47b2-9273-f57c5dcaed96",
"tid": "<tenant id>",
"uti": "Bw88HDIcC0CsuhhwGMg4AA",
"ver": "1.0",
"xms_mirid": "/subscriptions/<subscription id>/resourcegroups/rg-mgidtest-1110/providers/Microsoft.Compute/virtualMachines/vmjumpbox"
}
一方で、以下はアプリケーション登録したリソースを指定した場合のデコード結果。xms_mirid
が含まれていない。
{
"aud": "api://bd239da0-3acf-424c-95f8-41518d3a3079",
"iss": "https://sts.windows.net/<tenant id>",
"iat": 1699633115,
"nbf": 1699633115,
"exp": 1699719815,
"aio": "E2VgYDiXeaVQ7VSKj1V61bZphy7VAwA=",
"appid": "d090b38d-59ff-4c47-b759-f70024c19814",
"appidacr": "2",
"idp": "https://sts.windows.net/<tenant id>/",
"oid": "c7c89e9a-a179-47b2-9273-f57c5dcaed96",
"rh": "0.ARoAv4j5cvGGr0GRqy180BHbR6CdI73POkxClfhBUY06MHkaAAA.",
"sub": "c7c89e9a-a179-47b2-9273-f57c5dcaed96",
"tid": "72f988bf-86f1-41af-91ab-2d7cd011db47",
"uti": "Bw88HDIcC0CsuhhwfYs3AA",
"ver": "1.0"
}
xms_mirid
が含まれないとアクセス元を特定できないため、アプリケーションの検証が出来ない。
トークンを検証するコード
from jose import jwt
from jose.exceptions import JWTError
import requests
def get_azure_ad_public_keys(tenant_id):
url = f"https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys"
response = requests.get(url)
return response.json()['keys']
def validate_token(token, azure_ad_public_keys, audience, issuer):
try:
# トークンのデコードと検証
decoded_token = jwt.decode(
token,
azure_ad_public_keys,
algorithms=['RS256'],
audience=audience,
issuer=issuer,
options={"verify_exp": True}
)
return decoded_token
except JWTError as e:
print(f"トークン検証エラー: {e}")
return None
# Azure AD テナント ID とトークン
tenant_id = "<tenant id>"
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6~~~~~~~~~~~~~~"
# Azure AD の公開鍵を取得
azure_ad_public_keys = get_azure_ad_public_keys(tenant_id)
# アプリケーションの Audience と Issuer
audience = "https://appservice.azure.com"
issuer = f"https://sts.windows.net/{tenant_id}/"
# トークンの検証
validated_token = validate_token(token, azure_ad_public_keys, audience, issuer)
print(validated_token)
if validated_token:
print("トークンは有効です")
else:
print("トークンは無効です")
実行結果:
tsunomur@vmjumpbox:~$ python3 validate.py
{'aud': 'https://appservice.azure.com', 'iss': 'https://sts.windows.net/<tenant id>/', 'iat': 1699635590, 'nbf': 1699635590, 'exp': 1699722290, 'aio': 'E2VgYGh6ssKNcXFN/Pv5qdNuzRedCQA=', 'appid': 'd090b38d-59ff-4c47-b759-f70024c19814', 'appidacr': '2', 'idp': 'https://sts.windows.net/<tenant id>/', 'oid': 'c7c89e9a-a179-47b2-9273-f57c5dcaed96', 'rh': '0.ARoAv4j5cvGGr0GRqy180BHbR3wK-qu2pjZHgxBYVVCHh80aAAA.', 'sub': 'c7c89e9a-a179-47b2-9273-f57c5dcaed96', 'tid': '<tenant id>', 'uti': 'Bw88HDIcC0CsuhhwGMg4AA', 'ver': '1.0', 'xms_mirid': '/subscriptions/<subscription id>/resourcegroups/rg-mgidtest-1110/providers/Microsoft.Compute/virtualMachines/vmjumpbox'}
トークンは有効です

ドキュメント
トークンの検証方法