先日の MS 安納さんのポスト「【IDM】Windows Azure Active Directory と Office 365 と外部 IdP の関係(予想)」を見て、ちょうど Windows Azure Active Directory(WAAD)の中身を調査していたところだったので、色々と試してみました。
やろうとしたことは、WAAD の Access Control Service(ACS)を経由して Facebook や Google アカウントを使った Office365 へのシングルサインオンです。
結果、失敗するのですが、その過程で色々と仕組みが想像できたのでメモとして上げて起きます。
■まずは情報収集
現在、サードパーティ IdP での WAAD / Office365 へのフェデレーションの例としては、以下のような設定ドキュメントが公開されています。
・Ping Federate http://documentation.pingidentity.com/display/PFS/Set+up+Active+Directory+and+Directory+Synchronization#SetupActiveDirectoryandDirectorySynchronization-9000025
・Shibboleth
http://technet.microsoft.com/ja-jp/library/jj205463.aspx
後は、AD FS2.0 でシングルサインオンを構成した WAAD / Office365 のドメイン設定がどうなっているのか、を直接調べるとことも参考になりそうです。
また、Offce365 のシングルサインオンに関するドキュメントを見ると Office365 側の前提事項なども見えてきます。
https://portal.microsoftonline.com/IdentityFederation/IdentityFederation.aspx
調査の結果、WAAD / Office365 が外部 IdP とフェデレーションを行うには、以下が必要なことがわかります。
◆WAAD / Office365 側の状態
- ディレクトリ同期が行われている状態であること
こんな記載があります。
シングル サインオン (ID フェデレーション) をセットアップすると、ユーザーは会社の資格情報でサインインして、Microsoft Office 365 for enterprises のサービスにアクセスできます。シングル サインオンのセットアップの一部として、ディレクトリ同期をセットアップする必要もあります。また、これらの機能をお使いの社内のディレクトリおよびクラウドのディレクトリに統合する必要があります。
- シングルサインオンを有効にしたドメインを利用すること
まぁ当たり前ですが、ログイン画面(https://login.microsoftonline.com/login.srf)でログイン ID のドメインパート(@以下)を判別して、ログイン先の IdP を判別する以上、WAAD / Office365 がシングルサインオンドメインとして認識しているドメインが必要です。
ドメインの設定は Set-MsolDomainAuthentication コマンドレットを使うのですが、必要なパラメータは以下の通りです。
- DomainName : ドメイン名
- FederationBrandName : ブランド名(表示名)
- ActiveLogOnUri : Active Logon をする場合のエンドポイント
- IssuerUri : IdP の EntityID
- PassiveLogOnUri : Passive Logon をする場合のエンドポイント
- LogOffUri : ログオフする際のエンドポイント
- MetadataExchangeUri : Metadata Exchange のエンドポイント
- PreferredAuthenticationProtocol : 利用するフェデレーション・プロトコル
- SigningCertificate : 署名に利用する証明書
ちなみに AD FS2.0 と連携している WAAD / Office365 のドメインの情報を Get-MsolDomainFederationSettings コマンドレットで取得すると以下のような状態になっています。
パラメータ | 設定値 |
---|---|
DomainName | ドメイン名(コマンドレットの引数として指定) |
FederationBrandName | FQDN |
ActiveLogOnUri | https://FQDN/adfs/services/trust/2005/usernamemixed |
IssuerUri | http://FQDN/adfs/services/trust |
PassiveLogOnUri | https://FQDN/adfs/ls/ |
LogOffUri | https://FQDN/adfs/ls/ |
MetadataExchangeUri | https://FQDN/adfs/services/trust/mex |
PreferredAuthenticationProtocol | WSFed(コマンドレットでは出ない) |
SigningCertificate | 証明書の値 |
◆外部 IdP の設定
当然、外部 IdP 側には RP として WAAD / Office365 を設定する必要があリます。
WAAD / Office365 の Federation Metadata が
https://nexus.microsoftonline-p.com/federationmetadata/saml20/federationmetadata.xml
で公開されているので、中身を見てみます。
必要なのは、IdP から見ると Audience に該当する EntityID 部分とトークンを POST するアサーション・コンシューマ・サービスのエンドポイントアドレスです。
Federation Metadata を見ていくと、
- entityID="urn:federation:MicrosoftOnline"
- AssertionConsumerService ~中略~ Location="https://login.microsoftonline.com/login.srf"
とあります。
あとは、使用するプロトコルですが、Set-MsolDomainAuthentication コマンドレットなどフェデレーションドメインの設定用ツールのオプションである PreferredAuthenticationProtocol がとりうる値を見ると、WSFed / SAMLP とあるので、WS-Federation もしくは SAML-P が可能なことがわかります。
今回は ACS を使ったので、自動的に WSFed を選ぶことになりますが、その場合に SAML トークンのバージョンが気になります。FireFox の SAML Tracer などを使って AD FS2.0 と WS-Federation で連携している WAAD / Office365 との間を飛んでいる SAML トークンを見ると、
saml:Assertion+MajorVersion="1"+MinorVersion="1"+AssertionID=xxx
という記述が見えるので、 SAML トークンは 1.1 を使うことがわかります。
◆アサーション(クレーム)
- AD FS2.0 の要求規則を見ると、以下のアサーション(クレーム)が発行されることが必要です。
Attribute | Type | Value |
---|---|---|
nameidentifier | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier | AD上のオブジェクトのGUIDの値をbase64エンコードしたもの |
UPN | http://schemas.xmlsoap.org/claims/UPN | AD上のオブジェクトのUserPrincipalName(xx@xx.com) |
ImmutableID | http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID | AD上のオブジェクトのGUIDの値をbase64エンコードしたもの |
ちなみに、AD FS2.0 が実際にどのようなアサーションを出しているのかを確認する場合は、ClaimGrabber(http://www.theidentityguy.com/articles/2011/6/5/introducing-claimgrabber.html)を使うと便利です。
当然、このアサーションの中のそれぞれの値が WAAD / Office365 上に同期されたユーザの属性と一致している必要があります。(特に NameIdentityfier として使われる ImmutableID の値が重要)
ユーザの属性を調べるには Get-MsolUser コマンドレットを使います。
こんな感じで、ImmutableID の値を取得します。
> Get-MsolUser -UserPrincipalName xxx@xxx.com | fl ImmutableID
すると、
ImmutableId : VNzO5OVz+Emv66IULItTCg==
という形で値が取得できます。
まとめると、以下が外部 IdP と WAAD / Office365 のフェデレーションの条件になりそうです。
対象 | 条件 | |
---|---|---|
WAAD / Office365 | ディレクトリ同期 | 構成済みであること |
ドメイン | シングルサインオンドメインが構成されていること | |
外部 IdP | RP の 識別子(EntityID) | urn:federation:MicrosoftOnline |
RP の エンドポイント | https://login.microsoftonline.com/login.srf | |
プロトコル | WS-Federation | |
SAML トークン形式 | SAML 1.1 | |
アサーション | NameIdentifier | ADのGUIDをBase64エンコードした値(Get-MsolUserで取得した値と一致していること) |
ImmutableID | 同上 | |
UPN | ADのUserPrincipalNameの値 |
■実際にやってみる
では、早速 ACS を使って上記を構成してみます。
◆WAAD / Office365
ディレクトリ同期は普通に DirSync を使って構成します。
具体的なやり方は、手前味噌ですが、
@IT / Office 365とのアイデンティティ基盤連携を実現する(前)
http://www.atmarkit.co.jp/ait/articles/1211/14/news069.html
を参考にしてください。
ドメインの設定ですが、ACS の Federation Metadata から取得した値を設定します。
ACS の Federation Metadata は
https://テナント名.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml
なので、必要な値はここから取得します。
といっても使うのは IssuerUri と PassiveLogOnUri と MetadataExchangeUri だけです。
- IssuerUri : https://テナント名.accesscontrol.windows.net
- PassiveLogOnUri : https://テナント名.accesscontrol.windows.net/v2/wsfederation
- MetadataExchangeUri : https://waadnew1.accesscontrol.windows.net/v2/wstrust/mex
これらの値を使って WAAD / Office365 上にドメインを構成します。
まずは、ドメイン自体の作成です。
> Connect-MsolService
で WAAD / Office365 へ接続し、
> New-MsolDomain -Name 作成するドメイン名 -Authentication Federated
と打ってフェデレーションドメインを作成します。
次に、ドメイン所有権の確認のための CNAME レコードの出力と作成です。
> Get-MsolDomainVerificationDns -DomainName 作成したドメイン名
ここで出てくる Label の値を DNS 上に登録します。
登録が完了したら、確認と同時に IdP の設定もしてしまいます。
> $domainName = "ドメイン名"
> $brandName = "ラベル名"
> $issuerUri = "https://テナント名.accesscontrol.windows.net"
> $passiveLogOnUri = "https://テナント名.accesscontrol.windows.net/v2/wsfederation"
> $logOffUri = "https://テナント名.accesscontrol.windows.net/v2/wsfederation"
> $activeLogOnUri = "https://テナント名.accesscontrol.windows.net/v2/wsfederation"
> $metadataExchangeUri = "https://テナント名.accesscontrol.windows.net/v2/wstrust/mex"
> $signingCertificate = "証明書の値"
として引数を設定し、Confirm-MsolDomain コマンドレットを実行します。
> Confirm-MsolDomain -DomainName $domainName -FederationBrandName $brandName -ActiveLogOnUri $activeLogOnUri -IssuerUri $issuerUri -PassiveLogOnUri $passiveLogOnUri -LogOffUri $logOffUri -MetadataExchangeUri $metadataExchangeUri -PreferredAuthenticationProtocol WSFed -SigningCertificate $signingCertificate
◆ACS の設定
次は ACS の設定です。
ACS の IdP の設定として Facebook や Google などを設定するのですが、ここでは詳細は省略します。Facebook の場合、Facebook 上にアプリを構成して Consumer Key と Consumer Secret を取得するのと、Callback URL に ACS を設定するだけです。
ここでは RP 設定(証明書利用者アプリケーション)とクレーム・ルール(規則グループ)の設定を行います。
まずは RP 設定は以下の通りです。
- 領域 : urn:federation:MicrosoftOnline
- 戻り先 URL : https://login.microsoftonline.com/login.srf
- トークン形式 : SAML 1.1
次にクレーム・ルールですが、どうやって Facebook などから AD の GUID を Base64 エンコードした NameIdentifier / ImmutableID を取得しようか、、という話になります。
やり方としては実は ImmutableID は必ずしも AD の GUID を Base64 エンコードした値そのものでなくても良い、という点を利用します。ユーザを WAAD / Office365 に作っているのはディレクトリ同期ツール(つまり FIM2010)なので、ImmutableID(ディレクトリ同期ツール上では SourceAnchor)に Facebook から取得できる他の値に設定してあげればよいわけです。
ACS が Facebook から取得するクレームとしては Facebook 上のユーザID(数字の羅列)があるので、それを ImmutableID として設定してしまいます。
簡単なアプリケーションを作って ACS が Facebook から取得する nameidentifier の値を取得し、それを AD 上のどこか適当な属性の値に設定し、ディレクトリ同期ツールの属性マッピングの設定を変えてしまいましょう。
と、正攻法?は上記なのですが、面倒なので、逆のアプローチもあります。
AD と同期したユーザの ImmutableID の値を ACS が nameidentifier や ImmutableID として出力できればよいわけなので、ACS の出力要求の値に直接取得した ImmutableID の値を入れてしまいます。当然一人しか使えなくなりますが、実験なので良しとします。
ここまでで一通りの設定は終わりです。さっそく実験します。
■いざ、試す
結果、失敗します。
ここまでは順調。
そして失敗。。。
■原因を考えてみる。。
正常に使える AD FS2.0 でのログオンの場合と、失敗する Facebook のパターンを比較してみます。
Firefox の SAML Tracer を使って https://login.microsoftonline.com/login.srf に POST されるアサーションの中身を比較してみます。
saml:AttributeStatement の中身はほぼ同じです。AD FS2.0 側は NameIdentifierに Format プロパティで urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified が設定されていますが、AD FS2.0 のクレーム・ルールのオプションを付ける部分を削除してもちゃんとログオンはできたのでここは原因ではなさそうです。
しかし、そのままアサーションを見ていくと、、ありました、圧倒的な違いが。
AD FS2.0 の出力したアサーションには AuthenticationStatement が存在しますが、ACS の出力したアサーションには AuthenticationStatement がありません。
確かに ACS 自体は認証をしている訳ではないので AuthenticationStatement が出力されるわけがありません。ちなみに ACS の IdP を Google にしても結果は同じなので、ACS の先の IdP がどうやって認証したのか?という情報は ACS からの出力クレームには含まれません。
ということで、おそらく原因はこれです。
尚、私はここであきらめたのですが、どなたかその先を深堀して出来れば解決してみて頂きたいなぁ、、と。
■実験を通しての感想
ACS は非常に便利なのですが、クレーム・ルールの編集でできることが非常に少ないです。せめて AD FS2.0 の要求規則の編集程度のカスタマイズが出来れば色々と可能性が広がると思います。