microsoft について
Microsoft Entra ID Emulatorは、認証フローをテストするアプリ開発者向けに、Microsoft Entra IDのOAuth 2.0とOpenID Connectのエンドポイントをエミュレートします。複数の認可フロー、OIDCディスカバリー、Microsoft Graphの`/v1.0/me`に対応します。
主な機能
- 01OAuth 2.0認可コードとクライアントクレデンシャルフロー
- 02PKCEとリフレッシュトークン
- 03RS256 IDトークンとJWKS
- 04OIDCディスカバリーとuserinfoエンドポイント
- 05Microsoft Graphの`/v1.0/me`
活用シーン
- 01Entra IDのサインインをローカルでテスト
- 02PKCEとトークン更新を検証
- 03OIDCクライアントのディスカバリーをテスト
- 04Graphのユーザープロフィール要求をエミュレート
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel-labs/ emulate --skill microsoftインストール後、Claude Code で/microsoftを入力して読み込まれたか確認します。
詳細
Microsoft Entra ID エミュレーター
Microsoft Entra ID(Azure AD)v2.0 の OAuth 2.0 および OpenID Connect のエミュレーションです。認可コードフロー、PKCE、クライアントクレデンシャル、RS256 ID トークン、OIDC ディスカバリー、Microsoft Graph /v1.0/me エンドポイントに対応しています。
起動
ローカルリスナーは、デフォルトで 127.0.0.1 にバインドされます。コンテナーや他のマシンからアクセスするには、CLI に --host 0.0.0.0 を渡すか、createEmulator に hostname: '0.0.0.0' を渡してください。それらのクライアントから到達可能な URL を公開するには、--base-url または baseUrl を設定してください。
# Microsoft only
npx emulate --service microsoft
# Default port (when run alone)
# http://localhost:4000
または、プログラムから起動できます。
import { createEmulator } from 'emulate'
const microsoft = await createEmulator({ service: 'microsoft', port: 4005 })
// microsoft.url === 'http://localhost:4005'
アプリをエミュレーターに接続する
環境変数
MICROSOFT_EMULATOR_URL=http://localhost:4005
OAuth URL のマッピング
| 実際の Microsoft URL | エミュレーター URL |
|---|---|
https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration | $MICROSOFT_EMULATOR_URL/{tenant}/v2.0/.well-known/openid-configuration |
https://login.microsoftonline.com/.well-known/openid-configuration | $MICROSOFT_EMULATOR_URL/.well-known/openid-configuration |
https://login.microsoftonline.com/common/oauth2/v2.0/authorize | $MICROSOFT_EMULATOR_URL/oauth2/v2.0/authorize |
https://login.microsoftonline.com/common/oauth2/v2.0/token | $MICROSOFT_EMULATOR_URL/oauth2/v2.0/token |
https://login.microsoftonline.com/common/discovery/v2.0/keys | $MICROSOFT_EMULATOR_URL/discovery/v2.0/keys |
https://graph.microsoft.com/oidc/userinfo | $MICROSOFT_EMULATOR_URL/oidc/userinfo |
https://graph.microsoft.com/v1.0/me | $MICROSOFT_EMULATOR_URL/v1.0/me |
Auth.js / NextAuth.js
import MicrosoftEntraId from '@auth/core/providers/microsoft-entra-id'
MicrosoftEntraId({
clientId: process.env.MICROSOFT_CLIENT_ID,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
authorization: {
url: `${process.env.MICROSOFT_EMULATOR_URL}/oauth2/v2.0/authorize`,
params: { scope: 'openid email profile User.Read' },
},
token: {
url: `${process.env.MICROSOFT_EMULATOR_URL}/oauth2/v2.0/token`,
},
userinfo: {
url: `${process.env.MICROSOFT_EMULATOR_URL}/oidc/userinfo`,
},
issuer: process.env.MICROSOFT_EMULATOR_URL,
})
Passport.js
import { OIDCStrategy } from 'passport-azure-ad'
const MICROSOFT_URL = process.env.MICROSOFT_EMULATOR_URL ?? 'https://login.microsoftonline.com'
new OIDCStrategy({
identityMetadata: `${MICROSOFT_URL}/.well-known/openid-configuration`,
clientID: process.env.MICROSOFT_CLIENT_ID,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
redirectUrl: 'http://localhost:3000/api/auth/callback/microsoft-entra-id',
responseType: 'code',
responseMode: 'query',
scope: ['openid', 'email', 'profile'],
}, verifyCallback)
MSAL.js
import { ConfidentialClientApplication } from '@azure/msal-node'
const msalConfig = {
auth: {
clientId: process.env.MICROSOFT_CLIENT_ID,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
authority: process.env.MICROSOFT_EMULATOR_URL,
knownAuthorities: [process.env.MICROSOFT_EMULATOR_URL],
},
}
const cca = new ConfidentialClientApplication(msalConfig)
シード設定
microsoft:
users:
- email: [email protected]
name: Test User
given_name: Test
family_name: User
tenant_id: 9188040d-6c67-4c5b-b112-36a304b66dad
oauth_clients:
- client_id: example-client-id
client_secret: example-client-secret
name: My Microsoft App
redirect_uris:
- http://localhost:3000/api/auth/callback/microsoft-entra-id
tenant_id: 9188040d-6c67-4c5b-b112-36a304b66dad
OAuth クライアントが設定されていない場合、エミュレーターは任意の client_id を受け入れます。クライアントが設定されている場合は、client_id、client_secret、redirect_uri に対して厳密な検証が適用されます。
API エンドポイント
OIDC ディスカバリー
# Default tenant
curl http://localhost:4005/.well-known/openid-configuration
# Tenant-scoped (common, organizations, consumers, or specific tenant ID)
curl http://localhost:4005/common/v2.0/.well-known/openid-configuration
標準的な OIDC ディスカバリードキュメントを返します。
{
"issuer": "http://localhost:4005/{tenant}/v2.0",
"authorization_endpoint": "http://localhost:4005/oauth2/v2.0/authorize",
"token_endpoint": "http://localhost:4005/oauth2/v2.0/token",
"userinfo_endpoint": "http://localhost:4005/oidc/userinfo",
"end_session_endpoint": "http://localhost:4005/oauth2/v2.0/logout",
"jwks_uri": "http://localhost:4005/discovery/v2.0/keys",
"response_types_supported": ["code"],
"subject_types_supported": ["pairwise"],
"id_token_signing_alg_values_supported": ["RS256"],
"scopes_supported": ["openid", "email", "profile", "User.Read", "offline_access"],
"token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"]
}
JWKS
curl http://localhost:4005/discovery/v2.0/keys
id_token の署名を検証するための RSA 公開鍵(kid: emulate-microsoft-1)を返します。
認可
# Browser flow: redirects to a user picker page
curl -v "http://localhost:4005/oauth2/v2.0/authorize?\
client_id=example-client-id&\
redirect_uri=http://localhost:3000/api/auth/callback/microsoft-entra-id&\
scope=openid+email+profile&\
response_type=code&\
state=random-state&\
nonce=random-nonce"
クエリパラメーター:
| パラメーター | 説明 |
|---|---|
client_id | OAuth クライアント ID |
redirect_uri | コールバック URL |
scope | スペース区切りのスコープ(openid email profile User.Read) |
state | CSRF 保護のための不透明な state |
nonce | ID トークン用の nonce(任意) |
response_mode | query(デフォルト)または form_post |
code_challenge | PKCE チャレンジ(任意) |
code_challenge_method | plain または S256(任意) |
トークン交換
curl -X POST http://localhost:4005/oauth2/v2.0/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "code=<authorization_code>&\
client_id=example-client-id&\
client_secret=example-client-secret&\
redirect_uri=http://localhost:3000/api/auth/callback/microsoft-entra-id&\
grant_type=authorization_code"
次を返します。
{
"access_token": "microsoft_...",
"refresh_token": "r_microsoft_...",
"id_token": "<jwt>",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid email profile"
}
id_token は、sub、oid、tid(テナント ID)、email、name、preferred_username、ver("2.0")、および任意の nonce を含む RS256 JWT です。
PKCE を使用する場合は、トークンリクエストに code_verifier を含めてください。
本文パラメーターの代わりに、base64 エンコードされた client_id:client_secret を指定した Authorization: Basic ヘッダーをサポートしています。
クライアントクレデンシャル
curl -X POST http://localhost:4005/oauth2/v2.0/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=example-client-id&\
client_secret=example-client-secret&\
grant_type=client_credentials&\
scope=https://graph.microsoft.com/.default"
access_token のみを返します(refresh_token と id_token は返しません)。
リフレッシュトークン
curl -X POST http://localhost:4005/oauth2/v2.0/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "refresh_token=r_microsoft_...&\
client_id=example-client-id&\
client_secret=example-client-secret&\
grant_type=refresh_token"
新しい access_token、ローテーションされた refresh_token、および新しい id_token を返します。提示する client_id と client_secret は、リフレッシュトークンを受け取ったクライアントに属している必要があります。保存済みのクライアントバインディングがない従来のリフレッシュレコードも引き続きサポートされます。
ユーザー情報
curl http://localhost:4005/oidc/userinfo \
-H "Authorization: Bearer microsoft_..."
次を返します。
{
"sub": "<oid>",
"email": "[email protected]",
"name": "Test User",
"given_name": "Test",
"family_name": "User",
"preferred_username": "[email protected]"
}
Microsoft Graph /me
curl http://localhost:4005/v1.0/me \
-H "Authorization: Bearer microsoft_..."
OData 形式のレスポンスを返します。
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"displayName": "Test User",
"mail": "[email protected]",
"userPrincipalName": "[email protected]",
"id": "<oid>"
}
ログアウト
curl "http://localhost:4005/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000"
有効な post_logout_redirect_uri が指定されている場合は、その URI にリダイレクトします。
トークンの失効
curl -X POST http://localhost:4005/oauth2/v2.0/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=microsoft_..."
200 OK を返します。トークンはエミュレーターのトークンマップから削除されます。
よくあるパターン
認可コードフロー全体
MICROSOFT_URL="http://localhost:4005"
CLIENT_ID="example-client-id"
CLIENT_SECRET="example-client-secret"
REDIRECT_URI="http://localhost:3000/api/auth/callback/microsoft-entra-id"
# 1. Open in browser (user picks a seeded account)
# $MICROSOFT_URL/oauth2/v2.0/authorize?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=openid+email+profile&response_type=code&state=abc
# 2. After user selection, emulator redirects to:
# $REDIRECT_URI?code=<code>&state=abc
# 3. Exchange code for tokens
curl -X POST $MICROSOFT_URL/oauth2/v2.0/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "code=<code>&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&redirect_uri=$REDIRECT_URI&grant_type=authorization_code"
# 4. Fetch user info with the access_token
curl $MICROSOFT_URL/oidc/userinfo \
-H "Authorization: Bearer <access_token>"
PKCE フロー
CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-43)
CODE_CHALLENGE=$(echo -n $CODE_VERIFIER | openssl dgst -sha256 -binary | base64 | tr -d '=' | tr '+/' '-_')
# 1. Authorize with challenge
# $MICROSOFT_URL/oauth2/v2.0/authorize?...&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256
# 2. Token exchange with verifier
curl -X POST $MICROSOFT_URL/oauth2/v2.0/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "code=<code>&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&redirect_uri=$REDIRECT_URI&grant_type=authorization_code&code_verifier=$CODE_VERIFIER"
OIDC ディスカバリーベースの設定
OIDC ディスカバリーをサポートするライブラリでは、ディスカバリードキュメントから自動設定できます。
import { Issuer } from 'openid-client'
const microsoftIssuer = await Issuer.discover(
process.env.MICROSOFT_EMULATOR_URL ?? 'https://login.microsoftonline.com/common/v2.0'
)
const client = new microsoftIssuer.Client({
client_id: process.env.MICROSOFT_CLIENT_ID,
client_secret: process.env.MICROSOFT_CLIENT_SECRET,
redirect_uris: ['http://localhost:3000/api/auth/callback/microsoft-entra-id'],
})
組み込みエミュレーターと併用するカスタムエミュレーター
npx emulate init --custom inventory を使用して、サードパーティ API のエミュレーターとテストをひな形から作成します。emulate の defineConfig を使って emulate.config.ts に登録し、{ emulator: "microsoft" } などの組み込みエントリーと併用します。npx emulate start --watch を実行すると、インポートが再読み込みされ、表示された /_emulate URL でカスタムの状態を確認できます。再読み込みに成功すると、実行状態はシードにリセットされます。既存のフラットなシード設定も引き続き使用できます。--config は明示的に指定したファイルを選択します。サードパーティ API エミュレーターの作成とテストについては、https://emulate.dev/docs/custom-emulators をご覧ください。