Closed26

AADC 同期した拡張属性 (拡張スキーマ) を利用する SSO アプリを作るまでの道のり

OpenJNYOpenJNY

スキーマとは何か

  • スキーマ (Schema) とは、AD オブジェクトのブループリントをまとめたもの。各 AD オブジェクトは、スキーマ (特にクラス) のインスタンスに過ぎない。
  • スキーマは、複数の 属性 (attribute) と複数の クラス (class) から構成される。
    • 属性: AD オブジェクトに付与されるプロパティ。属性には型 (e.g., 整数、文字列、真偽値) がある
    • クラス: AD オブジェクトのインスタンス化に使われるインターフェイス。クラスは複数の属性を持っている。クラスの属性は、Mandatory (インスタンス化時に指定が必須) なものと、Optional なものに分類される。
  • Windows 2000 以降、Active Directory のバージョンアップごとに既定のスキーマは変更されてきた。スキーマの持つバージョン情報で判別可能。
  • 既定の属性一覧は https://docs.microsoft.com/ja-jp/windows/win32/adschema/attributes-all にある

例: ユーザー クラスに定義されている属性 (の一部)

参考

OpenJNYOpenJNY

スキーマの拡張

基本的には既定のスキーマ (属性) で事足りるけど、組織によってはどうしても足りない属性を足したいことがある。独自の属性を足すことを、スキーマを 拡張する (extend) と言う。

拡張するとスキーマを元に戻せなくなったり、管理が煩雑になったりするので、まずは拡張する前に既存スキーマで代替できないかを考えると良い。実際にスキーマ拡張を考える時は公式ドキュメントを必ず確認する。

https://docs.microsoft.com/ja-jp/windows/win32/ad/impact-of-schema-changes
参考:

OpenJNYOpenJNY

スキーマの確認方法

  1. ADDS の役割をインストールした Windows Server に、Admin (正確には Schema Admin 権限を持つユーザ) でログインする。

  2. Win + r や cmd.exe で以下を実行する。Pop up が出てくるので [OK]。

regsvr32.exe schmmgmt.dll
  • regsvr32 は COM コンポーネントをシステムに登録する管理ツール
  • schmmmgmt.dll は名前から類推できる通り、スキーマの管理コンポーネント
  1. Win + rmmc を実行して、スキーマ管理コンソールを立ち上げる。

  2. 左上の [File] から以下の通り操作して、スキーマの一覧を表示させる。

File > Add/Remove Snap-in > choose Active Directory Schema > Add > Ok

  1. こんな感じの画面が見える

OpenJNYOpenJNY

スキーマの拡張方法

手順としては、MMC の画面で Action (もしくは Attributes を右クリック) > New > Attribute するだけ。

属性作成に際して、準備するべき情報がいくつかある。

キー 意味
Common Name 属性の名前。人間フレンドリーな名前をつける
LDAP Display Name 内部的に使われる属性の名前。LDAP プロトコル的にはこちらを使うことになる
X500 Object ID 属性の ID。スコープが全世界となっていて、割当ては IANA で管理されている[1]。AD での利用目的なら、MS が発行してくれる OID を後述のツールで生成して、割り当てる
Syntax 属性の取りうる値。通常、Boolean / Unicode String / Numeric String / Integer / Large Integer / SID 等を使う

参考:

脚注
  1. https://software.fujitsu.com/jp/manual/manualfiles/M080179/J2UZ9110/02Z2B/irep05/irep0073.htm ↩︎

OpenJNYOpenJNY

CN / LDAP Display Name の名前付けベストプラクティス

  • CN と LDAP Display Name を統一する
  • <prefix>-<name> の命名規則を使う
    • <prefix> : 組織を一意に識別する文字列 (e.g., ドメイン、会社名の頭字語)
    • <name> : 十分に意味のある属性名
  • 開発/本番などのバージョンが存在する場合、さらに -<suffix> を末尾に付与して区別すると良い

例) contoso-SoftSkills

https://docs.microsoft.com/ja-jp/windows/win32/ad/naming-attributes-and-classes

OpenJNYOpenJNY

Object ID (OID) の生成方法

https://docs.microsoft.com/ja-jp/windows/win32/ad/obtaining-an-object-identifier-from-microsoft

  1. 公式ドキュメントで提供されているスクリプトを、oidgen.vbs として保存
スクリプトの中身
' oidgen.vbs 
'  
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED  
' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR  
' FITNESS FOR A PARTICULAR PURPOSE. 
' 
' Copyright (c) Microsoft Corporation. All rights reserved 
' Improvements made by Ryein C. Goddard
' 
' This script is not supported under any Microsoft standard support program or service.  
' The script is provided AS IS without warranty of any kind. Microsoft further disclaims all 
' implied warranties including, without limitation, any implied warranties of merchantability 
' or of fitness for a particular purpose. The entire risk arising out of the use or performance 
' of the scripts and documentation remains with you. In no event shall Microsoft, its authors, 
' or anyone else involved in the creation, production, or delivery of the script be liable for  
' any damages whatsoever (including, without limitation, damages for loss of business profits,  
' business interruption, loss of business information, or other pecuniary loss) arising out of  
' the use of or inability to use the script or documentation, even if Microsoft has been advised  
' of the possibility of such damages. 
' ---------------------------------------------------------------------- 
Function GenerateOID() 
    'Initializing Variables 
    Dim guidString, oidPrefix 
    Dim guidPart0, guidPart1, guidPart2, guidPart3, guidPart4, guidPart5, guidPart6 
    Dim oidPart0, oidPart1, oidPart2, oidPart3, oidPart4, oidPart5, oidPart6 
    On Error Resume Next 
    'Generate GUID 
    Set TypeLib = CreateObject("Scriptlet.TypeLib") 
    guidString = TypeLib.Guid 
    'If no network card is available on the machine then generating GUID can result with an error. 
    If Err.Number <> 0 Then 
        Wscript.Echo "ERROR: Guid could not be generated, please ensure machine has a network card." 
        Err.Clear 
        WScript.Quit 
    End If 
    'Stop Error Resume Next 
    On Error GoTo 0 
    'The Microsoft OID Prefix used for the automated OID Generator 
    oidPrefix = "1.2.840.113556.1.8000.2554" 
    'Split GUID into 6 hexadecimal numbers 
    guidPart0 = Trim(Mid(guidString, 2, 4)) 
    guidPart1 = Trim(Mid(guidString, 6, 4)) 
    guidPart2 = Trim(Mid(guidString, 11, 4)) 
    guidPart3 = Trim(Mid(guidString, 16, 4)) 
    guidPart4 = Trim(Mid(guidString, 21, 4)) 
    guidPart5 = Trim(Mid(guidString, 26, 6)) 
    guidPart6 = Trim(Mid(guidString, 32, 6)) 
    'Convert the hexadecimal to decimal 
    oidPart0 = CLng("&H" & guidPart0) 
    oidPart1 = CLng("&H" & guidPart1) 
    oidPart2 = CLng("&H" & guidPart2) 
    oidPart3 = CLng("&H" & guidPart3) 
    oidPart4 = CLng("&H" & guidPart4) 
    oidPart5 = CLng("&H" & guidPart5) 
    oidPart6 = CLng("&H" & guidPart6) 
    'Concatenate all the generated OIDs together with the assigned Microsoft prefix and return 
    GenerateOID = oidPrefix & "." & oidPart0 & "." & oidPart1 & "." & oidPart2 & "." & oidPart3 & _ 
        "." & oidPart4 & "." & oidPart5 & "." & oidPart6 
End Function 



Set oShell = WScript.CreateObject ("WScript.Shell")
oShell.run "cmd /c Regsvr32 Schmmgmt.dll"

Set objFSO=CreateObject("Scripting.FileSystemObject")
outFile="C:\Users\Administrator\Desktop\oidInfo.txt"
Set objFile = objFSO.CreateTextFile(outFile,True)

'Output the resulted OID with best practice info 
oidText = "Your root OID is: " & VBCRLF & GenerateOID & VBCRLF & VBCRLF & VBCRLF & _ 
    "This prefix should be used to name your schema attributes and classes. For example: " & _ 
    "if your prefix is ""Microsoft"", you should name schema elements like ""microsoft-Employee-ShoeSize"". " & _ 
    "For more information on the prefix, view the Schema Naming Rules in the server " & _  
    "Application Specification (http://www.microsoft.com/windowsserver2003/partners/isvs/appspec.mspx)." & _ 
    VBCRLF & VBCRLF & _ 
    "You can create subsequent OIDs for new schema classes and attributes by appending a .X to the OID where X may " & _ 
    "be any number that you choose.  A common schema extension scheme generally uses the following structure:" & VBCRLF & _ 
    "If your assigned OID was: 1.2.840.113556.1.8000.2554.999999" & VBCRLF & VBCRLF & _ 
    "then classes could be under: 1.2.840.113556.1.8000.2554.999999.1 " & VBCRLF & _  
    "which makes the first class OID: 1.2.840.113556.1.8000.2554.999999.1.1" & VBCRLF & _ 
    "the second class OID: 1.2.840.113556.1.8000.2554.999999.1.2     etc..." & VBCRLF & VBCRLF & _ 
    "Using this example attributes could be under: 1.2.840.113556.1.8000.2554.999999.2 " & VBCRLF & _ 
    "which makes the first attribute OID: 1.2.840.113556.1.8000.2554.999999.2.1 " & VBCRLF & _ 
    "the second attribute OID: 1.2.840.113556.1.8000.2554.999999.2.2     etc..." & VBCRLF & VBCRLF & _ 
     "Here are some other useful links regarding AD schema:" & VBCRLF & _ 
    "Understanding AD Schema" & VBCRLF & _ 
    "http://technet2.microsoft.com/WindowsServer/en/Library/b7b5b74f-e6df-42f6-a928-e52979a512011033.mspx " & _ 
    VBCRLF & VBCRLF & _ 
    "Developer documentation on AD Schema:" & VBCRLF & _ 
    "http://msdn2.microsoft.com/en-us/library/ms675085.aspx " & VBCRLF & VBCRLF & _ 
    "Extending the Schema" & VBCRLF & _ 
    "http://msdn2.microsoft.com/en-us/library/ms676900.aspx " & VBCRLF & VBCRLF & _ 
    "Step-by-Step Guide to Using Active Directory Schema and Display Specifiers " & VBCRLF & _ 
    "http://www.microsoft.com/technet/prodtechnol/windows2000serv/technologies/activedirectory/howto/adschema.mspx " & _ 
    VBCRLF & VBCRLF & _ 
    "Troubleshooting AD Schema " & VBCR & _ 
    "http://technet2.microsoft.com/WindowsServer/en/Library/6008f7bf-80de-4fc0-ae3e-51eda0d7ab651033.mspx  " & _ 
    VBCRLF & VBCRLF 

objFile.Write oidText
objFile.Close
  1. Admin 権限を持つ cmd / powershell セッションで、./oidgen.vbs を実行
  1. デスクトップに生成される oidInfo.txt を開いて、2 行目にある謎の文字列 (root OID) を確認

例)

Your root OID is: 
1.2.840.113556.1.8000.2554.16166.49194.xxxxx.yyyyy.zzzzz.1921813.16708071
  1. root OID の末尾に .2.<unique-number> を付与すれば、それがあなたの新属性の OID 👏

例)

1.2.840.113556.1.8000.2554.16166.49194.xxxxx.yyyyy.zzzzz.1921813.16708071.2.1
OpenJNYOpenJNY

作成した属性をユーザー クラスに追加

カスタムな属性を作っても、その属性を活用するクラスがいなければ意味がないです。特に、今回はユーザー (クラスからインスタンス化されたユーザー オブジェクト) に、新しく作った属性を付与したいです。

  1. 今度は MMC の "class" の定義を開いて、以下の通りポチポチ

Console Root/Active Directory Schema/Classes > user > Attributes > Add...

  1. 追加したい属性を Optional に入れて、最後に [OK]

  1. 仕上げに ADDS を再起動することで、変更を反映

Windows + R > "services.msc" > Active Directory Domain Services > Restart

OpenJNYOpenJNY

ユーザー オブジェクトの属性値を確認 & 設定

  1. Active Directory Users and Computers を開く
  2. Advanced Features を有効化

View > Advanced Features

  1. Users オブジェクトのプロパティから属性を確認

Users > "ユーザー名" > Attribute Editor

  1. ダブルクリックして適当に値を入れておく
OpenJNYOpenJNY

ここまでで役に立ったリンクのまとめ

翻弄された情報

OpenJNYOpenJNY

と、ここまで来たはいいものの、ちゃんと最初から環境を作りたくなったので terraform を書いて、ADDS 構築からやりなおすことに・・・

OpenJNYOpenJNY

とりあえず以下設定で Azure 上に AADS 環境を構築

  • VNet の [DNS サーバー] 設定は 10.0.0.4
  • AADS VM の設定
    • NIC: 10.0.0.4 (Static)
    • NIC の [DNS サーバー]: 168.63.129.16
    • OS: Windows Server 2019
    • Data Disk: Cache なしの 256 のデータディスクを 1 枚追加
OpenJNYOpenJNY

まずは Data Disk を NTFS でフォーマットする

Get-Disk -Number 2 | Initialize-Disk
Get-Disk -Number 2 | New-Partition -UseMaximumSize -DriveLetter F | Format-Volume -FileSystem NTFS -NewFileSystemLabel Volume -Force

コメント:

  • ディスクの指定は、パーティション作ってない最初のディスク (Get-Disk | where NumberOfPartitions -eq 0)[0] と迷ったけど、 -Number 2 の決め打ちでいいと判断。
  • ドライブレターも多分 (Get-Partition).DriveLetter に含まれないものとか使ったほうが良いと思うけどめんどいので F で決め打ち
OpenJNYOpenJNY

ADDS の役割をサーバーにインストール

Add-WindowsFeature -Name AD-Domain-Services, DNS -IncludeManagementTools
Import-Module ADDSDeployment
$Params = @{
    DomainName        = "openjny.local";
    DomainNetbiosName = "OPENJNY";
    ForestMode        = "Win2012R2";
    DomainMode        = "Win2012R2";
    DatabasePath      = "F:\Windows\NTDS";
    LogPath           = "F:\Windows\NTDS";
    SysvolPath        = "F:\Windows\SYSVOL";
    SafeModeAdministratorPassword = (ConvertTo-SecureString "<password>" -AsPlainText -Force);
    InstallDns           = $true;
    CreateDnsDelegation  = $false;
    NoRebootOnCompletion = $false;
    Confirm = $false;
}
Install-ADDSForest @Params
shutdown -r -t 5

https://docs.microsoft.com/ja-jp/windows-server/identity/ad-ds/deploy/install-active-directory-domain-services--level-100-
https://blog.shibata.tech/entry/2015/09/10/102711

OpenJNYOpenJNY

管理者ユーザーを作って、RDP できるようにしておく。

$identity = "taroyamada"
$given_name = "Taro"
$surname= "Yamada"

New-ADUser `
  -UserPrincipalName "$identity@openjny.local" `
  -SamAccountName $identity `
  -Name "$given_name $surname" `
  -DisplayName "$given_name $surname" `
  -GivenName $given_name `
  -Surname $surname`
  -Accountpassword (ConvertTo-SecureString "<password>" -AsPlainText -Force) `
  -PasswordNeverExpires $true `
  -Enabled $true

Add-ADGroupMember -Identity Administrators -Members $identity
Add-ADGroupMember -Identity "Remote Desktop Users" -Members $identity

https://docs.microsoft.com/en-us/powershell/module/activedirectory/new-aduser

OpenJNYOpenJNY

せっかくなのでもうひとり追加。

$identity = "hanakoyamada"
$given_name = "Hanako"
$surname= "Yamada"

New-ADUser `
  -UserPrincipalName "$identity@openjny.local" `
  -SamAccountName $identity `
  -Name "$given_name $surname" `
  -DisplayName "$given_name $surname" `
  -GivenName $given_name `
  -Surname $surname`
  -Accountpassword (ConvertTo-SecureString "<password>" -AsPlainText -Force) `
  -PasswordNeverExpires $true `
  -Enabled $true
OpenJNYOpenJNY

スキーマの拡張 (ユーザークラスにカスタム属性を追加する)

  1. regsvr32.exe schmmgmt.dll を実行

  2. oidgen.vbs で OID を生成

  3. MMC で属性を追加 (openjny-TestAttribute)

  4. MMC で user クラスに属性を追加

  5. ADDS をリスタート

Windows + R > "services.msc" > Active Directory Domain Services > Restart

OpenJNYOpenJNY

Hybrid ID の事前準備

https://docs.microsoft.com/ja-jp/microsoft-365/enterprise/prepare-for-directory-synchronization?view=o365-worldwide

同期を始める前に色々と考慮する事項がある。属性に関しての考慮事項は以下。

  • proxyAddress / userPrincipalName はディレクトリ内で一意である
  • givenName / surname / sAMAccountName / displayName / mail / proxyAddresses / mailNickname / userPrincipalName が英数字等の問題を起こしづらい文字で構成されている

また、UPN (userPrincipalName) が AD と Azure AD で一致している必要がある。今回はオンプレで openjny.local を、AAD で openjny.com をドメイン設定しているので、このままでは同期できない。

対応方法は 2 通り。

  • ADDS に代替 UPN サフィックスを追加する
  • proxyAddresses (プライマリのメールアドレス) 属性に、AAD のドメインを使った UPN を設定する (+ Azure AD Connect の構成で UPN )

今回は代替 UPN サフィックスによる方法を利用してみることにする。

代替 UPN の設定

https://docs.microsoft.com/ja-jp/microsoft-365/enterprise/prepare-a-non-routable-domain-for-directory-synchronization?view=o365-worldwide

  1. 代替 UPN サフィックス (openjny.com) を追加

Active Directory Domains and Trusts > Properties > Alternative UPN suffixes:

  1. ユーザーの UPN を代替 UPN サフィックスに変更
$LocalUsers = Get-ADUser -Filter "UserPrincipalName -like '*openjny.local'" -Properties userPrincipalName -ResultSetSize $null
$LocalUsers | foreach {$newUpn = $_.UserPrincipalName.Replace("@openjny.local","@openjny.com"); $_ | Set-ADUser -UserPrincipalName $newUpn}
OpenJNYOpenJNY

AAD Connect のインストール

https://docs.microsoft.com/ja-jp/azure/active-directory/hybrid/reference-connect-version-history

最新版の ADDC をインストールする。

https://docs.microsoft.com/ja-jp/azure/active-directory/hybrid/how-to-connect-sync-feature-directory-extensions

AADC のインストールウィザードでは、基本的に画面で指示された通りすいすい進めていい。ただ、Optional features の画面で Directory extension attribute sync を有効化するのを忘れないようにする。

追加したカスタム属性を Directory extentions で指定することで、拡張したスキーマ通り sync が行われるようになる。

OpenJNYOpenJNY

拡張スキーム (属性) の制限

https://docs.microsoft.com/ja-jp/azure/active-directory/hybrid/how-to-connect-sync-feature-directory-extensions#customize-which-attributes-to-synchronize-with-azure-ad

  • 拡張したクラスとしては、ユーザーまたはグループオブジェクトのみ対応
  • 単一値のカスタム属性の場合、文字列 / バイナリ / 整数値 / ブール値のみ対応
  • 複数値のカスタム属性の場合、文字列 / バイナリのみ対応
  • 複数値のカスタム属性は、Azure AD のすべての機能で使えるわけではない
  • 属性値の最大長は 250 文字 (251 文字以降は削除して sync)
  • sync 対象にできるカスタム属性は最大で 100 個
  • "Constructed Attributes" と呼ばれる属性は sync の対象にできない

簡単にまとめると、ユーザー/グループのクラス定義を少々手直ししたくて、単一値属性を少し追加 (拡張) するくらいなら、Hybrid ID のシナリオでも利用に耐えうるという感じ。

OpenJNYOpenJNY

手動同期のコマンド

https://docs.microsoft.com/ja-jp/azure/active-directory/hybrid/how-to-connect-sync-feature-scheduler#full-sync-cycle

# 差分
Start-ADSyncSyncCycle -PolicyType Delta

# 完全
Start-ADSyncSyncCycle -PolicyType Initial

同期処理のデバッグ

https://docs.microsoft.com/ja-jp/azure/active-directory/hybrid/tshoot-connect-object-not-syncing#troubleshooting

Synchronization Service > Operations

まず最初に確認すべきは、Status が "success" になっていない同期処理があるかどうか。エラーが発生していると、以下のように表示される。エラーメッセージ (この例だと "permission-issue" でググると Azure AD 技術サポートの公式ブログ記事がヒットした)。

同期された属性の値も Synchronization Service Manager から確認できる。Profile Name が "Full Synchronization" あるいは "Delta Synchronization" になっている行をクリックして、以下のいずれかを確認する。

Inbound Synchronization > Connections with Flow Updates
Outbound Synchronization > Export Attribute Flow

OpenJNYOpenJNY

Tenant Schema Extension App

属性を拡張して AADC で最初に同期したとき、Azure AD に "Tenant Schema Extension App" という名前の Enterprise Application が登録される。
Application Type == Enterprise Applications のフィルターがかかっている状態だと検索に載ってこないので少し注意。

AAD の [Audit logs] にも記録されているので、Target が "Tenant Schema" から始まるログを検索すると良い。

OpenJNYOpenJNY

拡張した属性が同期されていることを確認する

方法1: AzureAD モジュール

Install-Module AzureAD
Connect-AzureAD

$appName = 'Tenant Schema Extension App'
$appObjId = (Get-AzureADApplication -SearchString $appName).Objectid
Get-AzureADApplication -ObjectId $appObjId | Get-AzureADApplicationExtensionProperty | fl 

以下のように extension_xxxxxx_<AD の属性名> のようなものが見えていれば OK。

DeletionTimestamp      : 
ObjectId               : ce23d50c-f7c0-4791-bf17-d9df896b34ab
ObjectType             : ExtensionProperty
AppDisplayName         : 
Name                   : extension_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_openjny_TestAttribute
DataType               : String
IsSyncedFromOnPremises : true
TargetObjects          : {User}

方法2: Azure AD の管理画面

  1. Tenant Schema Extension App アプリケーションの Application ID を記録
  2. Groups > New group と進み新しいグループを作成 (実際には作成しなくて良い)
  3. Membership typeDynamic User にして、Add dynamic query を選択
  4. Get custom extension properties を押して、先程の Application ID を入力して Refresh properties
  5. Choose a Property のドロップダウンを見ると、同期された拡張属性が確認できる

方法3: Graph API

  1. https://developer.microsoft.com/ja-jp/graph/graph-explorer にアクセス
  2. 左側のメニューからサインイン
  3. 以下のエンドポイントへのクエリを実行
# すべてのユーザ
https://graph.microsoft.com/v1.0/users?$select=userPrincipalName,<AAD での拡張属性名>

# 特定のユーザ
https://graph.microsoft.com/v1.0/users/taroyamada@openjny.com?$select=<AAD での拡張属性名>

AAD 上の拡張属性名は、AADC によって定められた命名規則 extension_<AppID>_<属性名> で決まるが、少しクセがある。

  • <AppID> は、Tenant Schema Extension App アプリケーションの Application ID から ハイフン (-) を取り除いたもの
  • <属性名> は、基本的にオンプレ AD で作成した属性名。ただ、ハイフン (-) がアンダーバー (_) に置換される現象が確認できている。正確な値は Synchronization Service Manager のログから追ったほうが良さそう。
OpenJNYOpenJNY

OIDC の claim に拡張属性を使ってみる (が失敗)

Azure AD の OIDC 認証ライブラリ MSAL を使って、拡張属性を token の claim に含められるか検証してみる。結論から言えば、OIDC の場合 claim にオンプレ AD で同期した拡張属性を選択することは出来ず、実現可能性がかなり低そう。PoC に使ったのは公式のサンプル。

https://github.com/Azure-Samples/ms-identity-python-webapp

Python 3.8 の環境を用意 docker run -it -p 5000:5000 python:3.8 bash して、README 通りの手順を実施。ここまでをやってから一旦 http://localhost:5000 にアクセス。ちゃんと login できること、Graph API で /user が叩けることを確認。

git clone https://github.com/Azure-Samples/ms-identity-python-webapp
cd ms-identity-python-webapp

# pip install -r requirements.txt はライブラリの依存関係が壊れてて動かなかった
pip install flask flask-session msal requests werkzeug

sed -e 's/Enter_the_Application_Id_here/<新規登録したアプリの App ID>/' app_config.py
sed -e 's/Enter_the_Client_Secret_Here/<発行したシークレット>/' app_config.py

flask run --host 0.0.0.0 --port 5000

ここからが本題。Token configuration から claim の追加ができるのだが、どうも extension_xxxx... のような属性が見当たらない。

公式ドキュメント によると、アプリの claim 定義は json 形式のマニフェストでもかけるらしく、そこに無理やり追加すると一応追加は出来た。

しかしながら、この claim はサポートされておらず、トークンには含まれないですよという警告が表示される。

なんでこんな動作になるのか (利用できないなら追加させる理由) わからないまま、色々を調べていった結果、以下 2 つの文献に答えらしきものを発見。AD から sync されてきた拡張属性は、別のアプリ Tenant Schema Extension App が持っている値なので、このアプリの claim には使えないということらしい。

したがって、開発アプリでの id/access token の claim に AD から Sync されてきた拡張属性を含めたければ、こんなワークアラウンドを考慮すればよいはず。だが、こんなことはやりたくないので断念。

  • 開発アプリにも拡張属性を作成する (Graph API で、/applications/<開発アプリの AppId>/extensionProperties に POST を投げるとできるっぽい)
  • AD Sync の拡張属性と、開発アプリで作成した拡張属性を定期的に Sync するバッチ処理を cron か何かで走らせる
OpenJNYOpenJNY

SAML の claim に拡張属性を使ってみる

SAML の動作テストには SAML 2.0 Test Service Provider を使った。

https://sptest.iamshowcase.com/instructions#spinit

手順はこちらのサイトが詳しいので割愛。

https://idmlab.eidentity.jp/2018/02/samlidpsp.html

一旦 SSO できるところまで作業をすすめたら、claim を編集していく。エンタープライズ アプリケーションの画面から、次のようにして claim を追加する。

Single sign-on > Attributes & Claims > Edit > Add new claim

  • Name: http://schemas.microsoft.com/identity/claims/testattribute
  • Source: Attribute
  • Source attribute: extension_xxxxxx_<属性名>

[Save] すると次のような感じで claim が増える。

あとは再度 SP-initiated の認証リンクを踏んで結果を見てみるだけ。AttributeStatement からも、追加した claim が SAML アサーションに含まれるようになったことがわかる。詳しくアサーションを見る場合は、SHOW SAML ASSERTION を押せばよい。

OpenJNYOpenJNY

結局のところ、、、

  • OIDC で認証する場合は、アプリに Graph API を叩かせるのが吉
    • Graph API なら、/user エンドポイントに ?$select=extension_xxxx パラメータ付きで GET するだけで、AADC 同期した AD 側拡張属性が取れる
    • 基本 MSAL を使うことになるだろうから、Bearer Token 取ってきて Graph API 叩くのも非常にお手頃。サンプルも割とある。
    • AAD の API permission 機能を使えば、Garaph API 叩く時の認可もコントロールしやすい。
  • SAML で認証するときは、claim に拡張属性を単に追加してしまうだけで OK
    • 設定も非常に簡単
    • SAML アサーションに含まれる値をアプリ側でよしなに処理する
このスクラップは2022/04/11にクローズされました