2018年8月30日木曜日

[Azure AD B2B]GoogleとのID連携によりユーザの招待が簡単になりました

こんにちは、富士榮です。

Azure AD B2Bを使うと外部のユーザを招待し、組織のアプリケーションへのアクセスを付与することが出来ます。
この招待は
・Azure ADテナントを持っている組織の人
・Azure ADテナントを持っていない組織の人や個人
に対して送信することが出来、これまでAzure ADテナントを持っていない人は招待メールを受け取ったら、招待元のディレクトリにサインアップする際にログイン・パスワードを設定する必要がありました。

つまり、滅多にアクセスしない外部組織のアプリケーション専用にアカウントを作らなければならない、ということが発生するのでゲストユーザからすると非常に面倒くさい話ですし、パスワード忘れなども発生しやすいので管理上の問題も発生しやすい状況でした。

今回、Azure AD B2Bの新しく公開(現状パブリック・プレビュー)されたのが、Googleアカウントを持っている個人(G Suiteではなく、gmail.comのユーザ)を対象に、Google側の認証でAzure AD B2Bのテナントへログインできるようにする機能です。

 公式Blog)
 Azure AD B2B Collaboration support for Google IDs is now in public preview
 https://cloudblogs.microsoft.com/enterprisemobility/2018/08/28/azure-ad-b2b-collaboration-support-for-google-ids-is-now-in-public-preview/

やっていることは非常に単純でAzure ADに外部Identity ProviderとしてGoogleを設定、ゲストアカウントのドメインがgmail.comならGoogleにリダイレクトする、という仕組みです。

では、やってみましょう。
詳細は公式ドキュメントを参照してください。

◆GoogleにOAuthのクライアント登録を行う

結局のところ、Azure AD B2BがGoogleに対するOAuthクライアントとなるので、クライアント登録をしてあげる必要があります。

GoogleのDeveloper Consoleより作業を行います。
 https://console.developers.google.com/

必要な作業は、
・プロジェクトの作成
・OAuth同意画面
・OAuthクライアントの登録
の3点です。

ポイントは、OAuthクライアント登録時のリダイレクトURIの設定くらいだと思いますので、詳細は省きますが以下の通り設定を行います。
リダイレクトURIとしてセットする値
 https://login.microsoftonline.com
 https://login.microsoftonline.com/te/{Azure ADのテナントID}/oauth2/authresp



こんな感じで登録されますので、Client IdとClient Secretをメモしておきます。


◆Azure ADに外部Identity Providerを設定する

次は、Azure AD側の設定です。

ポータルからAzure ADを開くと、「Organizational relationships」という見慣れないメニューが出てきているので、こちらを開いていきます。


続いてIdentity ProvidersからGoogleを追加します。

すると、GoogleのClient IDとClient Secretを求められるので、入力して保存します。

これでおしまいです。

◆Googleアカウントを招待する

これは従来のAzure AD B2Bの操作と全く同じです。
Gmailのメールアドレスで招待するだけですね。

これで招待メールが飛んでくるのでディレクトリへアクセスします。

従来はココでゲストユーザにパスワードを登録する様に求められましたが、今回の機能を使っているとパスワードは不要なのでそのままユーザが作成されます。


上手くいくとアクセス・パネルが表示されます。


アプリケーションも使え、属性が取得できています。


ちなみに、自組織にAzure ADテナントが無いゲストユーザがアクセス・パネルにアクセスする時は、https://myapps.microsoft.com が使えません。どのテナントにユーザがいるのかが判別できない&組織アカウントなのかマイクロソフト・アカウントなのかの判別が出来ないためです。(マルチテナントアプリケーションも同様です)

そこで、招待元のテナントを決めうちでアクセスする必要があるので、以下のように招待元ディレクトリのテナントIDをパラメータにつけてアクセスしてください。
https://account.activedirectory.windowsazure.com/r?tenantid={招待元のテナントID}

取り敢えず個人のGmailアカウントはこれで便利になりました。
ちなみにG Suiteの場合はこの機能ではなく、G SuiteをSAML IdPとして構成、ドメイン単位でのID連携を構成すれば動くはずです。(やってませんが。。また紹介します)

2018年8月27日月曜日

[LINE Login/LIFF]メールアドレス登録無しでLINEログインできるWebアプリを作るには

こんにちは、富士榮です。

LINEログインを使うと、WebサイトへLINE IDを使って簡単にログインすることが出来ます。

また、LINEログインにはオートログインという機能があり、特定の環境においては端末にLINEアプリがインストールされていれば、ブラウザでLINE IDとパスワードを打ち込むことなく、Universal Linkやインテントを使ってLINEアプリへの遷移、自動的にログインをすることが出来ます。

しかし、このオートログイン、少々適用条件が厳しめです。

https://developers.line.me/ja/faq/ より
iOSの場合
LINE 5.2.0以降:LINEのアプリ内ブラウザでLINEログインv2の自動ログインが可能
LINE 7.5.0以降:SafariブラウザでLINEログインv2の自動ログインが可能
LINE 7.12.0以降:LINEログインv2.1の自動ログインが可能

Androidの場合
LINE 6.3.0以降:外部ブラウザででLINEログインv2の自動ログインが可能
LINE 6.4.0以降:LINEのアプリ内ブラウザでLINEログインv2の自動ログインが可能
LINE 7.14.0以降:LINEログインv2.1の自動ログインが可能


こうなってくると、私のようにiOSでChromeを使っている人は結局IDとパスワードの入力から逃れられず、ソーシャルログインのメリットが目減りしてしまいます。
(もちろん、セッションが永続するので2度目以降は大丈夫なんですが)

Safariの場合:LINEアプリが立ち上がり自動ログインされる


Chromeの場合:初回はログイン画面が表示され、2回目以降は確認だけ行われる



結局のところ、外部ブラウザからの遷移を考えるからこうなるので、LINEアプリ内のブラウザでWebアプリを開いてもらえばこのような問題は起きない話しです。ただし、これまではユーザにアプリ内ブラウザの利用を強制する方法がなく、リッチメニュー(トークルームの下に表示できるカスタムメニュー)を個別に作って対応したりしていた訳です。

こういう時に便利なのが、LIFF(LINE Front-end Framework)です。

 LIFF概要
 https://developers.line.me/ja/docs/liff/overview/

仕組み的には、LINEのカスタムURLスキームを使ってLINEアプリ内のブラウザを立ち上げる、という単純な仕組みです。これまではLINEアプリ内でカメラを立ち上げたり、特定のボットのタイムラインを開くことは出来たのですが、アプリ内ブラウザを立ち上げることが出来なかったので、LIFFの登場によりLINEアプリを外部からコントロールする幅が大きく広がった、と言えるでしょう。

 LINEで利用できるURLスキームの一覧
 https://developers.line.me/ja/docs/messaging-api/using-line-url-scheme/


LIFFを立ち上げるには
 line://app/{liff_app_id}
を指定します。

LIFFアプリを作成する際、特定のURLを開くような形でLINEプラットフォームへ登録するため、カスタムURLスキームで外部からLIFFアプリが呼び出されると、LINEアプリ内であらかじめ登録したWebページが開かれる、という仕組みです。

この仕組みを応用すれば、LINEログインをさせたいアプリを開いたときはLIFFを経由して強制的にアプリ内ブラウザを起動する、ということが出来るので、呼び出し元ブラウザを意識することなくオートログインをさせることが出来るようになります。

では、早速やってみましょう。


◆LIFFアプリを登録する


LIFFはボット(Messaging API)の一部の機能として提供されていますので、LIFFを登録するためのエンドポイントへのPOSTを行う際は、Messaging APIのチャネルのアクセストークンを使います。

具体的には、こんな感じのクエリを投げます。
エンドポイントhttps://api.line.me/liff/v1/apps
メソッドPOST
リクエストヘッダauthorizationBearer {Messaging APIのチャネルアクセストークン}
content-typeapplication/json
ボディ{
"view":{
"type":"full",
"url":"起動したいWebアプリのURL(要https)"
}
}


上手くいくと、LIFFアプリIDがボディで返ってきます。
{
 "liffId": "xxxxxx"
}

このボディにセットするURLにLINEログインをさせたいWebアプリのURLを指定すればLINEアプリ内のブラウザでアプリを起動することが出来るので、オートログインができるようになります。


◆LIFF経由でWebアプリを呼び出す


後は呼び出すだけですので、User-Agentを見るなりなんなりしてモバイル系ならカスタムURLスキームで呼び出せば問題ありません。

LIFFアプリを外部ブラウザから呼び出します。


LINEアプリ内でWebアプリが起動され、自動ログオンされます。


ちょっとトリッキーではありますが、現段階で様々な環境のユーザをアプリ内ブラウザへ誘導するにはこの方法しかなさそうなので、覚えておくとよいかと思います。

2018年8月15日水曜日

サービス終了間際のAzure ACS無しでSharePoint ServerへAzure ADでログインする

こんにちは、富士榮です。

前回も書きましたが今年の11月でAzure Access Control Service(ACS)のサービス提供が終了します。

Azure ACSを自前サービス用に使っているようなB2B/B2C向けサービスを提供している企業の方はある程度切り替えは終わっているとは思いますが、意外と見落としがちなのがオンプレミスでSharePointを構築して使っている企業の方々です。

現状、SharePointサーバは最新バージョンであるSharePoint Server 2016でさえClaimベース認証を構成しようとするとプロトコルとしてws-federation、トークンはSAML1.1しかサポートしていません。

この制限により、SAML2.0トークンしかサポートしていないAzure ADとSharePoint Serverの間で直接のフェデレーションを構成することが出来ませんでした。

このことを解決するために、これまではAD FSやAzure ACSなど割と柔軟にws-federationの構成が出来る製品やサービスを間に噛ませてシングルサインオンを実現していました

こんな構成です。



が、いよいよAzure ACSのサービス提供が終了、ということでそろそろ対策を行わないと手遅れになってしまいます。
となると、引き続きAD FSを使う、というのも一つの手段ではありますが、今更オンプレミスにサーバを配置して管理するのも面倒なので、出来ることならSharePointとAzure ADを直接接続しておきたいところです。

と、言うことで今回はAzure ADにSAML1.1のトークンを発行させることでSharePoint Serverと直接接続するための方法を解説します。
尚、この手法は特に裏技というわけではなく、オフィシャルに(ひっそりと)公開されている手順です。
Using Azure AD for SharePoint Server Authentication
https://docs.microsoft.com/en-us/Office365/Enterprise/using-azure-ad-for-sharepoint-server-authentication

簡単に言うと、Azure ADのトークン発行ポリシーをカスタマイズしてSAML1.1のトークンを発行させることによって、SharePoint Serverが解釈できるようにしてやろう、という作戦です。

以下の順に構成を行います。

  • Azure ADのエンタープライズ・アプリケーションにSharePoint Server接続用のアプリケーションを登録する
    • SharePointのEntityID、Reply URLを登録する
    • トークン署名用の証明書を生成し、公開鍵をダウンロードする
    • ユーザの割り当てを行う
  • 作成したAzure AD上のアプリケーション(ServicePrincipal)にリンクされたトークン発行ポリシーを変更する
    • SAML1.1トークンを発行するカスタム・ポリシーを作成する
    • 元々ServicePrincipalにリンクされているSAML2.0トークン発行のポリシーとのリンクを解除する
    • 新規作成したカスタム・ポリシーをServicePrincipalにリンクする
  • SharePoint Serverの信頼済みアイデンティティ・トークン発行者としてAzure ADを構成する
    • Azure ADからダウンロードした公開鍵を登録する
    • クレームマッピング、識別用属性を指定し、アイデンティティ・トークン発行者登録を行う
  • SharePoint Serverのユーザ・ポリシーを構成する
    • サイトへのAzure AD上のユーザへのアクセス権限を設定する


◆まずはありのままを

はじめる前に、まずは何もしない素の状態のAzure ADのws-federationでSharePoint Serverと接続するとどうなるのか?について確認しておきたいと思います。
要はSAML2.0のトークンをSharePoint Serverが受け取ったらどういう挙動をするか?の確認です。
(上記の手順のトークン発行ポリシーの変更をしないとどうなるか?という話しです)

結果、ID4014エラーが出てSAML2.0はサポートされていない、と言って怒られます。
※エラー内容がわかりやすくなるように、web.configのcustomErrors modeをoffに設定しています。


では早速。

◆Azure ADのエンタープライズ・アプリケーションにSharePoint Serverを登録する

当然ギャラリーには無いアプリケーションなので、「ギャラリー以外のアプリケーション」を選択してアプリケーションを登録していきます。
つまり、この段階ではプロトコルもトークンもSAML2.0のアプリケーションとして登録します。


アプリケーションの作成が終わったら、シングルサインオン設定を行います。
必要な設定はSharePoint ServerのEntityIDとサインオンURLです。

  • EntityID
    • 任意の文字列(後でSharePoint Server側に登録するRealmの文字列と同一の文字列) ※通常は「urn:sharepoint:{サーバ名}」とか「http://{サーバ名}」を使うことが多いです。
  • サインインURL
    • https://{SharePointサーバ名}/_trust/default.aspx ※httpsが必要なので、先にSharePointのSSL化は済ませておくこと

こんな感じです。

次に、トークン署名用の証明書をダウンロードしておきます。

また、他にも後でAzure ADのサインインURLと作成したアプリケーションのオブジェクトIDが必要になるのでメモしておきましょう。
SSO URLはシングルサインオンの構成のページに表示されているものを使います。(実際はSAMLではなくws-federationを使うので、URLのパスはwsfedに変更する必要があります)

オブジェクトIDはプロパティのページにあります。


アプリケーションIDと間違えやすいの注意です。オブジェクトIDの方を使います。

また、同じページにユーザの割り当ての設定もあるので、Azure AD上のユーザでSharePointを利用するユーザの限定が必要なければ「割り当てが必要ですか?」は「いいえ」を設定しておきます。

◆SAML1.1トークン発行用のカスタム・ポリシーの作成とリンクを行う

この作業が一番のキモです。
PowerShellを使って構成することも可能ですが、結局はInvoke-RestMethodでGraph APIを叩いているだけなので、Azure AD Graph Explorer(https://graphexplorer.azurewebsites.net/)で直接実行した方が手っ取り早いと思います。(トラブルを避けるために、先のエンタープライズ・アプリケーションの登録に使ったグローバル管理者権限を持った組織アカウントでログインしてください。マイクロソフトアカウントは不可です)

実行するのは、以下のAPIです。

  • 現状のポリシーを確認する
    • メソッド:GET
    • リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほどメモしたエンタープライズ・アプリケーションのオブジェクトID}/policies
これで、現在アプリケーションにリンクされているトークン発行ポリシー(SAML2.0のトークンを発行するポリシー)のIDが取得できます。同時に複数のトークン発行ポリシーを一つのServicePrincipalにリンクすることは出来ないので、このポリシーとのリンクは削除してしまいます。(ポリシーそのものは他のアプリケーションで使っているので削除しない様に気を付けてください)

  • ポリシーとのリンクを削除する
    • メソッド:DELETE
    • リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほどメモしたエンタープライズ・アプリケーションのオブジェクトID}/$links/policies/{直前の手順で取得したリンクしているポリシーのオブジェクトID}
ちなみに、Graph Explorerを使うとDELETEなどHTTP 204 no contentsが返ってくるようなクエリはいつまでたっても結果が表示されずにプログレスバーがじりじりと動くだけですが、ちゃんと処理は実行されているので、遠慮なく止めてしまってOKです。

再度、リンクされているポリシーを確認するとnullが返ってくるのでトークン発行ポリシーとのリンクが解除されたことがわかります。

次は、いよいよカスタムポリシーを作成します。

  • SAML1.1トークン発行ポリシーを作成する
    • メソッド:POST
    • リソース:https://graph.windows.net/myorganization/policies/
    • ボディ:{"displayName":"SPSAML11","type":"TokenIssuancePolicy","definition":["{\"TokenIssuancePolicy\":{\"TokenResponseSigningPolicy\":\"TokenOnly\",\"SamlTokenVersion\":\"1.1\",\"SigningAlgorithm\":\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\",\"Version\":1}}"]}
作成が完了したら、作成したポリシーのオブジェクトIDを確認しておきます。

  • 作成したポリシーを確認する
    • メソッド:GET
    • リソース:https://graph.windows.net/myorganization/policies

ここで先ほど作ったカスタム・ポリシーのオブジェクトIDを取得しておき、エンタープライズ・アプリケーションとリンクします。

  • ポリシーのリンクを作成する
    • メソッド:POST
    • リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほど作成したエンタープライズ・アプリケーションのオブジェクトID}/$links/policies
    • ボディ:{"url":"https://graph.windows.net/myorganization/policies/{作成したカスタム・ポリシーのオブジェクトID}?api-version=1.6"}


このクエリも返事がない(no contents)のでポリシーのリンク状態を確認しておきます。


  • ポリシーのリンク状態を確認する
    • メソッド:GET
    • リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほど作成したエンタープライズ・アプリケーションのオブジェクトID}/policies


これでAzure AD側の準備は完了です。

◆SharePoint Serverに信頼済みアイデンティティ・トークン発行者を登録する

先ほどAzure AD上に登録したSharePoint ServerのEntityID、Azure ADのサインオンURL、ダウンロードした証明書を用意しておき、SharePoint管理シェル(PowerShell)を管理者権限で起動、以下のコマンドを実行します。

  • $realm : SharePoint ServerのEntityIDとしてAzure AD上に設定した文字列
  • $wsfedurl : Azure ADのサインオンURL。最後のsaml2をwsfedに変更する
  • $filepath : ダウンロードした証明書ファイルのパス


$realm = "urn:sharepoint:xxxx"
$wsfedurl="https://login.microsoftonline.com/{tenantid}/wsfed"
$filepath="C:\users\Administrator\desktop\sharepoint.cer"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($filepath)
New-SPTrustedRootAuthority -Name "AzureAD" -Certificate $cert
$map = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" -IncomingClaimTypeDisplayName "name" -LocalClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"
$map2 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" -IncomingClaimTypeDisplayName "GivenName" -SameAsIncoming
$map3 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" -IncomingClaimTypeDisplayName "SurName" -SameAsIncoming
$ap = New-SPTrustedIdentityTokenIssuer -Name "AzureAD" -Description "SharePoint secured by Azure AD" -realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map,$map2,$map3 -SignInUrl $wsfedurl -IdentifierClaim "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"

これで信頼済みのアイデンティティ・トークン発行者の登録が完了しますので、SharePoint Serverの管理ページのWebアプリケーションの管理で認証プロバイダとして設定を行います。

対象のWebアプリケーションを選択して認証プロバイダの設定を開き、信頼済みアイデンティティ・トークン発行者の設定で先ほど作成したAzure ADを選択します。


これで、SharePoint ServerのSSO設定も完了です。

いよいよ最後です。

◆ユーザーポリシー(ユーザへの権限付与)を構成する

最後に信頼済みアイデンティティ・トークン発行者からわたってくるユーザがサイトへアクセスできるように権限を付与します。
この手順が抜けると認証は出来ても認可がされないのでログインすることが出来ません。

対象のWebアプリケーションを選択してユーザ・ポリシーを開きます。
ユーザの追加より、ピープル・ピッカーを開き、Azure ADのname(今回は識別子をname属性にしているので)を選択した状態で画面上部の検索窓にAzure AD上のユーザ名を入れて検索ボタンをクリックし、出てくるユーザを追加します。


これで全ての設定が完了です。
早速サイトへアクセスするとAzure ADへリダイレクトされ、認証が終わるとコンテンツが表示されるはずです。

SAML Tracerでトレースをしてみると、ちゃんとトークンのバージョンがSAML1.1になっていることがわかります。

<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
    <t:Lifetime>
        <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2018-08-12T13:00:58.881Z</wsu:Created>
        <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2018-08-12T14:00:58.881Z</wsu:Expires>
    </t:Lifetime>
    <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
        <wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
            <wsa:Address>urn:sharepoint:xxxxx</wsa:Address>
        </wsa:EndpointReference>
    </wsp:AppliesTo>
    <t:RequestedSecurityToken>
        <saml:Assertion MajorVersion="1"
                        MinorVersion="1"
                        AssertionID="_d9aa279a-50f5-4f42-a553-ea45faa33ce4"
                        Issuer="https://sts.windows.net/{tenant id}/"
                        IssueInstant="2018-08-12T13:05:58.881Z"
                        xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
                        >



いかがでしょうか?まだACSを使っている人は早めにAzure ADと直接フェデレーションする様に構成を変更しておきましょう。

2018年8月13日月曜日

サービス終了間際!Azure ACSの状況を確認する

こんにちは、富士榮です。

数年前に一世を風靡したAzure ACS(Access Control Service)ですが、いよいよ11月でサービス提供が終了されます。

ということで過去に作ったACSネームスペースの整理を進めようと思います。

しかし、旧Azure Portalが既にアクセスできず、現在のAzure PortalからはACSのWeb管理コンソールへのリンクがどこにもない、そして作ったネームスペースの名前も忘れている、という状態で途方に暮れているのは私だけではないはずです。

そういう人のためのPowerShellのモジュールがこちらです。

Acs.Namespaces
https://www.powershellgallery.com/packages/Acs.Namespaces/1.0.2


これを使うと、過去に作成したネームスペースの一覧の参照や有効化・無効化・削除などが可能です。

早速使ってみましょう。
手順に従いモジュールのインストールをしたら、まずは「Connect-AcsAccount」でACSに接続します。
ACSのログイン画面がポップアップするのでMicrosoft Accountでログインします。

次に、Microsoft Accountが紐づいているサブスクリプションを「Get-AcsSubscription」取得します。ACSのネームスペースはサブスクリプションに紐づいているので、サブスクリプションIDを指定して検索する必要があるためです。

サブスクリプション一覧が取得できたら、「Get-AcsNamespace」ネームスペースの状態を確認してみます。パラメータには先ほど取得したサブスクリプションのIDを指定します。

こんな感じでネームスペースと管理URLが取得できます。

ちなみに、しばらく放置していたACSネームスペースは無効化されているので、StateがDisabledになっているものは再度有効化しないと管理コンソールへログインできません。
たしかこんな名前のネームスペースがあったはずだけどアクセスできなくなってる・・・という人は無効化されている可能性があるので、確認してみてください。

ネームスペースを有効化するには、「Enable-AcsNamespace」を使います。


これで管理URLへアクセスすると懐かしのACSの管理コンソールが使えます。


昔作ったリソースの移行忘れが無いようにしておきましょう。

特に久しぶりに触るSharePointの実験環境など、私も忘れていたモノがあったのでACSからAzure ADへの切り替えをしておこうと思います。(ちなみにAzure ADでSAML1.1のトークンが発行出来ない問題は密かに解決しているので、既にACSが無くても直接Azure ADでオンプレSharePointのClaim Based Authenticationは使えるようになっています。手順などはまた紹介します)