ラベル Azure AD の投稿を表示しています。 すべての投稿を表示
ラベル Azure AD の投稿を表示しています。 すべての投稿を表示

2024年5月10日金曜日

Entra IDの外部認証プロバイダの設定を試す(1)

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

先日当Blogにも書いたとおり、最近Previewが公開されたEntra IDの外部認証を少しずつ試していきます。

設定はこの辺りのドキュメントを見ればできそうです。

https://learn.microsoft.com/ja-jp/entra/identity/authentication/how-to-authentication-external-method-manage


ざっとやり方と条件を見ていくと、こんな感じっぽいです。

  • Entra ID上にマルチテナントアプリとして外部認証システムをクライアント登録する
  • 外部認証システムがEntra IDが発行したid_token_hintを検証できるようにEntra IDのDiscoveryエンドポイントを解釈できるように構成する
  • 外部認証システムへEntra IDをクライアント登録する
  • 外部認証システムの認証強度の要求はclaimsパラメータを利用し、amr/acrの値が要求される。そのため外部認証システムは指定された値のamr/acrを返却できるように構成する必要がある
  • 外部認証システムの認可エンドポイントへのアクセスはPOSTで行われる
  • 外部認証システムからEntra IDへのid_tokenの引渡しはform_postを使う必要がある

まだ細かいところは色々とありますが、やりながら潰していきましょう。

しかしまぁ、結構条件厳しめですね。やはり自作IdPをカスタマイズしつつ対応させていくのが良さそうです。


と言うことで徐々に試します。今回は外部認証システムへ認証要求が飛ぶところまでを見ていきます。

マルチテナントアプリの登録

まずはEntra IDに外部認証システムを登録してあげる必要があります。ログイン前に参照することが必要になる、かつ他のマルチテナントアプリに対して認証する可能性があることから、外部認証システム自体の登録もマルチテナントアプリとしてクライアント登録を行います。

この際、redirect_uriには外部認証システムの認可エンドポイントのURLを指定する必要があります。

次に、APIアクセス許可を行います。

Microsoft Graphへのアクセス許可をする(委任されたアクセス許可)必要があります。

対象の権限にはopenidとprofileを指定します。

管理者の同意を付与しておきます。


外部認証の設定を行う

いよいよ外部認証システムの登録を行います。
  • 名前は適当でも良いのですが後から変えられないので注意が必要です。
  • クライアントIDは外部認証システム側にEntra IDを登録する際に発行されるクライアントIDを指定します。(次回以降で外部認証システム側への登録の話をします)
  • 検出エンドポイントには外部認証システムのdiscoveryエンドポイントを指定します。
  • アプリIDは先ほどEntra ID上に登録したマルチテナントアプリのクライアントIDを指定します。

また、この認証方式を使うことができるユーザが所属するグループを指定し、設定を有効にして保存します。

動作を確認する

この状態でユーザでログインをする際に多要素認証が求められるように設定しておくと、認証方式として先ほど指定した方式が出てきます。(出てこない場合はMicrosoft Authenticatorが現在使えない、というリンクをクリックすると出てきます)

こちらを選択すると、外部認証システムへリダイレクトされるのですが、トレーサーでリクエストを見ると以下のように認可エンドポイントへPOSTでid_tokenやclaimsを含んだリクエストが飛んでいることがわかります。

id_token_hintを紐解くとこんな感じです。

おすすめは外部認証システム側にoid(オブジェクトID)とtid(テナントID)を紐づけた形でユーザを作成しておき、当該のユーザで認証することです。(preferred_usernameだと変わってしまう可能性があるので)

また、認証方式・強度などに関する要求はclaimsパラメータで指定がされていますので、外部認証システムはこの条件を満たす形で認証を行い、id_tokenのacr/amrに値を含めてEntra IDへ送出してあげる必要があります。 

{
"claims": {
"id_token": {
"amr": {
"essential": true,
"values": [
"face",
"fido",
"fpt",
"hwk",
"iris",
"otp",
"tel",
"pop",
"retina",
"sc",
"sms",
"swk",
"vbm"
]
},
"acr": {
"essential": true,
"values": [
"possessionorinherence"
]
}
}
}
}

次回以降は外部認証システム側の設定を調整していきたいと思います。

 



2024年5月8日水曜日

Entra IDの外部認証プロバイダの利用機能がPreview公開されています



Entra IDで外部の認証手段が使えるようになったようです。

むかーし、3rdパーティの多要素認証プロバイダの設定を行う機能が一瞬出て消えていったものの後継ですね。当時はPremium P2ライセンスが必要でDuoやRSA、Trusonaなどプリセットされたものを認証プロバイダとして利用することができました。
当時の記録

まぁ、中身はid_token_hintを使ってIdPをチェインさせているだけだった気がしますが、当時はあんまり流行らなかったんですかね・・・。

今回のアナウンスとドキュメントを見ているとやはりid_token_hintを使った認証状態の引き回しとチェインであることには変わらなさそうですが、より柔軟に構成を行うことができるようになっていますね。ライセンスもPremium P1でOKっぽいですし。

ということで私のテナントでも機能が有効になったのでおいおい試してみたいと思います。


2024年1月5日金曜日

バックエンドが充実していない環境でOpenID Providerを作る

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


昨日こんなことを書きましたので、ちょっと深掘りしてみようと思います。

この辺りは別ポストで詳しくお話しようと思いますが、最後までステートレスにこだわったMicrosoftは認可コードをJWTにして認証済みユーザの属性情報を暗号化して入れることでトークン要求時に認可コードからセッションをLookupしてid_tokenを生成する必要をなくしていたり、VittorioがAuthorのRFC9068/JWT Profile for OAuth 2.0 Access Tokenの様にIntrospectionエンドポイントが無くてもトークンの有効性検証ができる仕組みを実装したり、Hybrid Flowでもないのにフロントで取得できるid_tokenにはほとんど情報を入れず、userInfoやGraph APIへのアクセスをしないとユーザ属性が全く取れなかったり、、、とグローバルスケールの認証基盤を運営する上での苦労が滲み出ていたりします


要するにEntra IDの話なんですが、良いか悪いかは置いておいてOpenID Providerを作るときにバックエンドにDBをなるべく持たずに認可コード、アクセストークン、IDトークンのやりとりを一貫性を持って実行するための工夫の話です。


そもそも何が課題なのか?

ご存知の通りOpenID ConnectやOAuthはIDトークンやアクセストークンを取得するためにユーザエージェント(ブラウザ)とRelying Party(クライアント)が認可エンドポイントとトークンエンドポイントとの間のアクセスを行ったり来たりする必要があります。(いわゆるOAuth Dance)

これを実装しようとすると認可エンドポイントへのアクセスとトークンエンドポイントへのアクセスが本当に同一トランザクションの中でのやりとりなのかを確認しないといけませんし、サーバ(OpenID Provider)側としてはトランザクション内での情報の保持をしないといけなくなります。ただHTTPは本来ステートレスな仕組みなので、通常のWebアプリケーションを作る場合と同じ様にサーバ側でのセッション管理をどうするか、しかも認可エンドポイントはユーザエージェントから直接アクセス、トークンエンドポイントはクライアントからのバックエンドアクセスという形なのでcookieで、というわけにも行きません。

通常の実装では何の疑問もなくバックエンドにデータベースを置いてステート管理をサーバ側で実装することになるのですが、グローバルでスケールしている認証サービスの様に極めて高い可用性が必要とされるサービスでその様なインフラを作るのは非常にコストが高い行為といえます。(Entra IDの様に基本無償で提供される様なサービスなら難しい判断になると思います)


そうだ、クライアントにステート情報のハンドリングを任せよう!

そこで考えられたのが全てのやりとりの中で最終的にIDトークンやアクセストークンを発行するのに必要となる情報をもと回れば良いではないか、という考え方だと思われます。(Entra ID以外で見たことはありませんが)

簡単に流れを説明するとこんな感じになっているんだと思います。

認可エンドポイント

  1. ユーザを認証する→最終的にIDトークンに含めるユーザの属性情報を取得する
  2. nonceやaud(クライアントID)など、同じく最終的にIDトークンに含める属性をクエリパラメータから取得する
  3. 1,2で取得した情報を暗号化してJWTにして認可コードとしてクライアントへ戻す
トークンエンドポイント
  1. クライアントからPOSTされた認可コードの検証、復号を行う
  2. 復号した情報をもとにIDトークンを生成してクライアントへ返却する


この辺りをミニマムで実装してみるとこんな感じのコードになると思います。(テスト実装なので細かいところは気にしないでください)



const router = require("express").Router();
const jwt = require("jsonwebtoken");

// jwt署名に使う共有シークレット
const jwtSecretForCode = "this_is_a_secret_for_code_signing";
const jwtSecretForToken = "this_is_a_secret_for_token_signing";

// 認可エンドポイント
router.get("/authorization", async (req, res) => {
    // 本来なら実装する処理
    // - ユーザの認証
    // - response_typeによるフローの振り分け
    // - client_idの登録状態の確認
    // - redirect_uriとclient_idが示すクライアントとの対応確認
    // - scopeの確認
    // - 属性送出に関する同意画面の表示

    // codeの生成(本来は暗号化しておく)
    // 最終的にid_tokenに入れる値をDBに保存する代わりに暗号化してcodeに入れておくことでバックエンドを持たずにすませる
    const jwtPayload = {
        iss: "myOpenIDProvider",
        aud: req.query.client_id,
        sub: "authenticatedUserIdentifier",
        email: "test@example.jp",
        given_name: "taro",
        family_name: "test",
        nonce: req.query.nonce
    };
    const jwtOptions = {
        algorithm: "HS256", // 面倒なのでHS256にする
        expiresIn: "30s" // コードの有効期限なので短め
    };
    const code = jwt.sign(jwtPayload, jwtSecretForCode, jwtOptions);
    // redirect_uriへリダイレクト
    res.redirect(req.query.redirect_uri + "?code=" + code + "&state=" + req.query.state);
});

// トークンエンドポイント
router.post("/token", (req, res) => {
    // 本来なら実装する処理
    // - クライアントの認証
    // - grant_typeの検証
    // - codeの検証(有効期限、発行先クライアント、スコープ)
    // - access_tokenの発行
    // - id_tokenの発行
    const code = req.body.code;
    jwt.verify(code, jwtSecretForCode, (err, decoded)=> {
        if(err){
            res.json({
                err: "counld not verify code"
            })
        };
        if(decoded){
            // 本来は検証が終わったらcodeを無効化する
            // codeの中身を取り出してid_tokenを作る
            const jwtPayload = {
                iss: decoded.iss,
                aud: decoded.aud,
                sub: decoded.sub,
                email: decoded.email,
                given_name: decoded.given_name,
                family_name: decoded.family_name,
                nonce: decoded.nonce
            };
            const jwtOptions = {
                algorithm: "HS256", // 面倒なのでHS256
                expiresIn: "10m" // id_tokenの有効期限なので少しだけ長め
            };
            const token = jwt.sign(jwtPayload, jwtSecretForToken, jwtOptions);
            res.json({
                access_token: token, // ちなみにEntra IDの場合はaccess_tokenもid_tokenとほぼ同じものが使われるケースもある。
                token_type: "Bearer",
                expires_in: 3600,
                id_token: token
            });
        }
    });
});

module.exports = router;


実際に動きを見てみます。
  • 認可エンドポイントへのアクセス
http://localhost:3000/oauth2/authorization?client_id=111&redirect_uri=https://localhost:3000/cb&state=hoge

  • コールバックへのリダイレクト
https://localhost:3000/cb?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJteU9wZW5JRFByb3ZpZGVyIiwiYXVkIjoiMTExIiwic3ViIjoiYXV0aGVudGljYXRlZFVzZXJJZGVudGlmaWVyIiwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuanAiLCJnaXZlbl9uYW1lIjoidGFybyIsImZhbWlseV9uYW1lIjoidGVzdCIsImlhdCI6MTcwNDQyMDk1MCwiZXhwIjoxNzA0NDIwOTgwfQ.XKi6JLc5IwDNyZG1C7Lrk1UrBiWpOV5EC2NgpqWSXjk&state=hoge

  • 認可コードの中身(面倒なので今回は暗号化はしていません)
  • トークンエンドポイントへのPOST 

  • 取得できたIDトークンの中身



本当にこれでいいのか?

まぁ確かにスケーラビリティを考えると非常にエコなので実装としてはありだと思いますが、色々と割り切りをしないといけません。

例えば、

  • 認可コードのサイズが大きくなる
  • アクセストークンはJWT形式(内包型トークン)が前提となり、Introspectionエンドポイントの実装はできない
などが代表的なところです。
特に認可コードのサイズが大きくなる問題は結構深刻で、認可エンドポイントからクライアントへのリダイレクト時のクエリパラメータの長さがものすごいことになりますので、クライアントの実装によっては認可コードが受け取れない、ということが結構あります。ここはMSALを使え!というMicrosoftの理屈なんだと思いますが、既存のアプリケーションとEntra IDを繋ぐ際にはしばしば問題になる可能性があるので、Entra IDの導入を行う際は要注意のポイントの一つです。

まぁ、いずれにしてもID基盤の導入はアプリケーション開発側との認識合わせ・仕様合わせが一番大きなポーションを占めると思うので、この辺りも念頭におきながらEntra IDライフを楽しむべきでしょう。

2022年10月15日土曜日

ようやくAzure ADのデータが日本のデータセンターに

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

最近アクティビティが減っていますが分散型IDを含む諸々の活動は継続していますので時間をとって何かアウトプットしていかないとなぁ、と考えている今日この頃です。

ちょうどIgniteがあったのでAzure AD周りも色々と発表がありましたが、その中でもやっとか・・・というのがAzure ADのデータの置き場所問題です。

これまでAzure ADのデータは日本リージョンにテナントを作っても他の地域へレプリケーションされていましたが、今回のUpdateで日本データセンターに配置されることになりました。(今回の発表はAzure ADのみが対象でB2B/B2Cを含む各種サブセットについては対象外です。各コンポーネントごとのデータ配置は後述のサイトで確認できます)


公式Blog:「Announcing a New Azure AD, part of Microsoft Entra, region in Japan」

https://techcommunity.microsoft.com/t5/microsoft-entra-azure-ad-blog/announcing-a-new-azure-ad-part-of-microsoft-entra-region-in/ba-p/2967453


ざっくりいうと、

  • 新規に日本リージョンに作ったテナントは日本データセンターに(対象コンポーネントはauthentication, core directory storage, and premium features storage)
  • 以前に日本リージョンに作ったテナントのマイグレーションは今後の発表を待て

ということです。

なお、コンポーネント単位のデータ配置場所は「https://aka.ms/aaddatamap」で確認することができます。

「AAD Directory Data & Management」や「Authentication」など対象となっているサービスを選択すると「大阪、東京、埼玉(笑)」と出ます。



では、自分のテナントのデータの配置場所がどこになっているのか?はどうやって確認するのかですが、2つ方法があります。

一つ目は単純にポータルからディレクトリのプロパティを見る方法です。

■10月に新しく作ったテナント

 リージョン(国または地域):Japan

 データの場所:Japan datacenters


■昔作ったテナント

 国または地域(リージョン):Japan

 データの場所:Asia, United States, Europe datacenters


※余談ですが何年か前に古巣バハレーンに作ったテナントのデータの場所はEUになってました。



もう一つの方法はアクセストークンの中のClaimを見る方法です。

アプリケーションでリージョンを絞りたい場合などはこちらを使うことができそうです。

こちらが日本データセンターにデータがあるテナントのアクセストークンをjwt.ioでデコードしたものです。

tenant_region_scopeというClaimに"JPR"という値が入っています。


それに対してこちらが古いテナント(まだ海外にデータがレプリケーションされている)のものです。



自治体とか金融機関とか医療関係などデータの置き場所に縛りのあるシナリオではこの辺りをうまく活用していくと良いでしょう。





2021年4月6日火曜日

Azure AD Verifiable Credentialsがやってきた(Public Preview)

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

ようやく出ました、Azure AD Verifiable CredentialsのPublic Preview。


AlexのBlog

https://techcommunity.microsoft.com/t5/azure-active-directory-identity/announcing-azure-ad-verifiable-credentials/ba-p/1994711


各種リソース

https://www.microsoft.com/en-us/security/business/identity-access-management/verifiable-credentials

某社もソリューションパートナーになってます。

この辺りからチュートリアルも触れるのでガシガシ触っていけると面白いと思います。

Microsoft Authenticatorを最新版にアップデートするとこんな感じでVerifiable Credentialsをどんどん発行していけます。これで各種デジタルな証明書を持ち運んでIdPにアクセスすることなくVerifierへ証明書を提示していくことができるようになるはずです。




2021年3月17日水曜日

[Azure AD B2C]遂にカスタムドメインがやってきた

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


おそらくAzure AD B2Cユーザ最大の要望だったカスタムドメイン(b2clogin.comのサブドメインではなく持ち込みのドメイン)がようやくパブリック・プレビューになりました。

参考)b2clogin.comのサブドメインをカスタムドメインと言っていた頃の記憶


当時もコレジャナイ感を感じつつ、Azure AD B2Cを使っているはずのレアル・マドリードのサイトを見ると自前ドメインを使ってるやん、、的な羨望の眼差しを抱えつつ実案件ではUSまで押しかけてプライベート・プレビューとして個別にカスタムドメインをアンロックしてもらったり、と苦労していたものです。。。


この苦労は当然世界共通で、中にはWeb Appをフロントにたててrewriteを使って無理矢理カスタムドメインを実現してしまう猛者まで現れる、という状態でした。

(ちなみにこの方法、当然のことながら可用性は落ちますし、Identity Protectionを使ったクライアント判定もできなくなるのでオススメはできません)



ということで、ようやくパブリック・プレビューです。

https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/custom-domain?pivots=b2c-custom-policy


仕組みとしては、Azure Front DoorをAzure AD B2Cの手前においてURLのRewriteする、という形です。ってこれ、上で紹介した猛者のやってた技をオフィシャルに実装した、という感じなんですね。

Identity Protectionなどはちゃんと効くのか、などはおいおい深堀りしてみるとして、まずはファーストルックです。


大まかな手順としては、

  1. Azure AD B2Cの実体となっているAzure ADにカスタムドメインを追加する
  2. Azure Front Doorを作り、b2clogin.comへ振り分け設定をする
  3. Azure Front Doorにカスタムドメインを設定する
という流れです。


順に確認してみましょう。

1. Azure AD B2Cの実体となっているAzure ADにカスタムドメインを追加する

ご存知の通り、Azure AD B2Cには実体となっているAzure ADが存在します。ポータルからAzure AD B2Cを立ち上げると、別のテナントが開き、その中でAzure AD B2Cの管理を行う、という形になります。この別テナントにもAzure ADが存在しているので、Azure AD B2Cの管理画面からテナントを変えずにAzure Portalのホームへ遷移、改めてAzure ADの管理メニューを開くと実体の管理ができるようになります。(分かりにくいですね)

そのテナントは通常のAzure ADなのでカスタムドメインを追加することができます。


ここで普通にカスタムドメインを追加し、ドメインの所有権の確認を行います。

これで第1段階はOKです。


2. Azure Front Doorを作り、b2clogin.comへ振り分け設定をする

次はAzure Front Doorを作って構成します。

Azure Front Doorは単純なエッジで動くレイヤ7のフロントサービスで、SSLのオフロードなどを含め高スケーラビリティなWebアプリをデプロイするのに役に立つサービスです。

必要な設定は、

  • フロントエンド設定(リクエストを受けるドメイン)
  • バックエンド(振り分け先となるWebアプリケーション)
  • 振り分けルール(パスやポートなど、バックエンドへの振り分け条件の設定)
の3種類です。

まずはフロントエンドです。この段階では適当な名前でAzure Front Doorドメイン(azurefd.net)上の名前を定義します。※どっちみち後でカスタムドメインをつけるので適当でOK、っていうことです。


次にバックエンドです。今回はAzure AD B2Cがバックエンドとなりますので、カスタムドメインを使いたいAzure AD B2Cのテナントドメイン名(xxx.b2clogin.com)を設定します。

最後が振り分けルールです。

ここでは特に考えずにフロントとバックエンドをストレートにマッピングしておきます。

ここもカスタムドメインを追加した後でちゃんと設定しますので仮でOKです。

これでAzure Front Doorの基本設定は完了です。


3. Azure Front Doorにカスタムドメインを設定する

次はAzure Front Doorにもカスタムドメインを設定します。ここで設定するドメインは先にAzure ADに設定したドメインと同じものを使う必要があります。

Azure Front Doorのフロントエンドまたはドメインよりカスタムドメインを追加します。

CNAMEの設定と検証が走るので必要なレコードをDNSサーバ上に設定する必要がありますが、設定としては単純にカスタムドメインを追加するだけです。


正常にドメインが追加できたら、振り分け規則についてもカスタムドメインの設定を行います。フロントエンドまたはドメインの設定より追加したカスタムドメインを選択するだけなので特に難しいことはありません。


とりあえず設定関係はこれで完了です。

(ちなみにSSL証明書もAzure Front Door側が勝手に設定するので別途買う必要はありません)

ただ、忘れがちな点が何点かあります。

  • カスタムHTMLをAzure Storage上に配置している場合はCORS設定を行う
  • redirect_uriや各種エンドポイントのアドレスも当然変わるので外部IdPなどに設定してあるredirect_uriやアプリに設定してあるエンドポイントアドレスを修正する

カスタムHTMLを使っている場合のCORS設定

外部IdP(LINEの例)のredirect_uriの追加



これで本当に設定完了です。


試してみる

とりあえず適当なアプリの設定を変えたらログイン要求をしてみます。



ちゃんとカスタムドメインで動きます。

id_tokenの中のIssuerのURIも変わっていることが分かります。


特にむずかしいことはなく、問題なく動きました。


とはいえ気になる点は何点か。
  • Identity Protectionなどフロントの環境を取得して動くサービスやカスタムポリシーの要求リゾルバはちゃんと動くのか?
  • カスタムドメインを設定しても、https://カスタムドメイン/xxx.onmicrosoft.com(もしくはテナントID)となってしまうのをhttps://カスタムドメインだけにできないか?(ルール設定でなんとかなる気もしなくもない)
  • SAML IdPとしてAzure AD B2Cをつごかす場合のIdPのEntityIDも変わっちゃう?
などなど。


引き続き試してみようと思います。











    2020年12月17日木曜日

    OpenID Connectの脇役たち

    本記事は Digital Identity技術勉強会 #iddance Advent Calendar 2020 17日目の記事です。


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

    今日は年末ということもあり、普段はあまり表舞台に出てこないOpenID ConnectのOptionalなオプションにフォーカスを当ててみようかと思います。
    対象とする仕様は「OpenID Connect Core 1.0」とします。


    OpenID Connectの設計思想

    OpenID ConnectはいわゆるID連携(Federation)を行うための仕様として、OAuth2.0の上位にアイデンティティ層を載せる形で定義されています。

    そして、その設計思想は、
    • 簡単なことは簡単に
    • 難しいことも可能に
    • モジュラーデザイン
    という原則に則っています。

    この中の最初の原則である「簡単なことは簡単に」という部分が普段みなさんが使っているOpenID Connectを使ったログオンの実装の大半で、上記の仕様の第2章「Authentication」に定義されているAuthorization code flow、Implicit flow、Hybrid flowの3つ、特にAuthorization code flowを覚えておけば基本的なWebアプリケーションへのログインのシナリオでは何も難しいことはありません。
    ※当然、セキュリティ上の考慮事項などはそれなりに存在するため、stateやnonceを正しく使ってcodeを横取りされたりid_tokenを使いまわされることを防いだりする必要はありますので運用環境で使うためにはちゃんと仕様を理解して実装する必要はありますが。。。

    また、2つ目の「難しいことも簡単に」、3つ目の「モジュラーデザイン」の原則の通り、OpenID Connect DiscoveryやOpenID Connect Dynamic Client Registrationなど関連仕様との組み合わせでより高度なシナリオにも対応することができるようになっています。

    今回はニッチを狙いますので、OPTIONALなパラメータを重点的に見ていきたいと思います。

    RFCにおける要求レベルの定義

    仕様を読んでいるとMUST、SHOULD、MAY、OPTIONALなど各パラメータ毎に要求レベルが定義されています。
    この要求レベル自体はRFC2119で以下の通り定義されています。
    ※RFC2119の日本語訳はIPAのホームページで公開されています。

    以下、IPAの日本語訳です(赤字・太字は筆者)。
    1. 「しなければならない( MUST )」 
      • この語句、もしくは「要求されている( REQUIRED )」および「することになる( SHALL )」は、その規定が当該仕様の絶対的な 要請事項であることを意味します。
    2. 「してはならない( MUST NOT )」
      • この語句、もしくは「することはない( SHALL NOT )」は、その規定が当該仕様の絶対的な禁止事項であることを意味します。
    3. 「する必要がある( SHOULD )」
      • この語句もしくは「推奨される( RECOMMENDED )」という形容表現は、 特定の状況下では、特定の項目を無視する正当な理由が存在するかもしれませんが、 異なる選択をする前に、当該項目の示唆するところを十分に理解し、 慎重に重要性を判断しなければならない、ということを意味します。
    4. 「しないほうがよい( SHOULD NOT )」 
      • この語句もしくは「推奨されない( NOT RECOMENDED )」という形容表現は、 特定の動作が容認できる、ないし、非常に有用である、というような 特定の状況下では、正当な理由が存在するかもしれませんが、 このレベルの動作を実装する前に、当該項目の示唆するところを十分に理解し、慎重に重要性を判断しなければならない、ということを意味します。
    5. 「してもよい( MAY )」 
      • この語句、もしくは「選択できる( OPTIONAL )」という形容表現は、ある要素が、まさに選択的であることを意味します。 その要素を求めている特定の市場があるから、あるいは、 他のベンダーはその要素を提供しないだろうが、その製品機能を拡張する と察知して、その要素を含む選択をするベンダーがあるかもしれません。 特定の選択事項(オプション)を含まない実装は、おそらく機能的には劣る ことになるでしょうが、そのオプションを含む他の実装との相互運用に備えなければなりません( MUST )。 同様に、特定のオプションを含む実装は、そのオプションを含まない実装 との相互運用に備えなければなりません( MUST )。(当然ながら、そのオプションが提供する機能は除かれます。)

    まさに今回のターゲットはMAY、もしくはOPTIONALな部分です。

    MAYとOPTIONALを仕様から抽出する

    早速、仕様の中にどのくらいMAYとOPTIONALがあるのか抽出してみます。
    • MAY:87個
    • OPTIONAL:53個
    ・・・結構ありますね。

    全部カバーしているとキリがないので、独断と偏見でMAY/OPTIONALを5個選んで番付的に紹介してみようと思います。
    ※もちろんOPTIONALなので実装しているOpenID Providerばかりではありませんので、動かしてみても期待する反応がえられないケースが多いので悪しからず。

    十両:prompt

    認証リクエストにpromptパラメータを付加することで再認証や同意を求めることができます。

    仕様では3.1.2.1のAuthentication Requestの項に定義されています。(OpenIDファウンデーションジャパンの日本語訳から引用)
    OPTIONAL. Authorization Server が End-User に再認証および同意を再度要求するかどうか指定するための, スペース区切りの ASCII 文字列のリスト. 以下の値が定義されている.
    none
    Authorization Server はいかなる認証および同意 UI をも表示してはならない (MUST NOT). End-User が認証済でない場合, Client が要求する Claim 取得に十分な事前同意を取得済でない場合, またはリクエストを処理するために必要な何らかの条件を満たさない場合には, エラーが返される. 典型的なエラーコードは login_requiredinteraction_required であり, その他のコードは Section 3.1.2.6 で定義されている. これは既存の認証と同意の両方, またはいずれかを確認する方法として使用できる.
    login
    Authorization Server は End-User を再認証するべきである (SHOULD). 再認証が不可能な場合はエラーを返す (MUST). 典型的なエラーコードは login_required である.
    consent
    Authorization Server は Client にレスポンスを返す前に End-User に同意を要求するべきである (SHOULD). 同意要求が不可能な場合はエラーを返す (MUST). 典型的なエラーコードは consent_required である.
    select_account
    Authorization Server は End-User にアカウント選択を促すべきである (SHOULD). この prompt 値は, End-User が Authorization Server 上に複数アカウントを持っているとき, 現在のセッションに紐づくアカウントの中から一つを選択することを可能にする. End-User によるアカウント選択が不可能な場合はエラーを返す (MUST). 典型的なエラーコードは account_selection_required である.
    prompt パラメータは Client に対して, End-User のセッションがアクティブであることを確認したり, End-User にリクエストに対する注意を促すことを可能にする. none がその他の値とともに用いられる場合はエラーとなる.

    アプリの仕様でトランザクションの種類によって強制再認証を求めたり、同意を求めたりするケースもあると思うので、そのような場合はうまくpromptパラメータを使うと良いですね。

    前頭:target_link_uri

    SAMLでいうrelayStateですね。

    仕様にも記載がありますが、全てのログインフローがRelying PartyからOPへのリクエストによって始まるわけではなく、OP起点だったり別のシステム(ポータルなど)から起動されることもあります。そのような場合、ログインフローを起動するシステムはRPのログイン開始エンドポイントへユーザをリダイレクトしてフローを起動するわけですが、ログインが完了した後、必ずしもRPのデフォルトのランディングページに着地させたいわけではなく、別のページへ飛ばしたい、というケースもあります。そのような場合にtarget_link_uriに指定するとログイン完了後に望むページへ遷移させることができます。

    ただ、注意点として記載がある通りOpenリダイレクタにならないように指定できるURLはきちんと検証しないといけません。

    仕様では4のInitiating Login from a Third Partyの項に定義されています。(OpenIDファウンデーションジャパンの日本語訳から引用)
    target_link_uri
    OPTIONAL. 認証後, RP がリダイレクトするよう要求された URL. RP は外部サイトへのオープンリダイレクターとして使用されることを防ぐために target_link_uri の値を検証しなければならない(MUST).
    SAMLを使ったシステム導入の際はrelayStateに関する要望は結構あったので、今後このパラメータもメジャーになってくるかな?と思います。

    関脇:request/request_uri

    いわゆるRequest Objectです。FAPI Part2では認可要求自体への署名が要求されるので、普通にQuery Stringに各種リクエストパラメータをくっつけるのではなく、JWTとして認可サーバへ渡してあげる必要があります。また認可要求にJWTそのものを渡すこともできますが、request_uriに指定したエンドポイントを参照させることによりリクエストパラメータを取りに来てもらうこともできます。

    仕様では6のPassing Request Parameters as JWTsの項に定義されています。(OpenIDファウンデーションジャパンの日本語訳から引用)
    request
    OPTIONAL. このパラメータにより, OpenID Connect リクエストを単一の self-contained なパラメータとすることができ, 任意で署名および暗号化を施せるようになる. パラメータ値は Request Object 値である (Section 6.1 参照). Request Object は, 各 Claim がリクエストパラメータとなる JWT である.
    request_uri
    OPTIONAL. このパラメータにより, 値そのものではなく参照を送ることが可能になる. request_uri 値は https スキーマで始まる URL であり, Request Object 値を含むリソースへの参照となる. 参照先の Request Object は, リクエストパラメータを含む JWT である.
    金融サービスに限らず要求についても隠蔽したいケースや署名をつけて確実に渡したいケースではこのパラメータは活躍する場面がありそうです。

    大関:id_token_hint

    完全に個人的な趣味です。実はAzure ADを使っていると結構活躍の機会が多いんです。例えば今はもう新規のサポートは受け付けていませんがPremium P2の機能のカスタムMFAプロバイダへのセッション引き継ぎはid_token_hintを使って行っていましたし、そもそもOffice365→Azure AD→外部IdPというようなチェーン構成のフェデレーションでは前段で入力されたユーザ名のドメインパートに基づきログイン先のIdPを動的に変更する、なんということもよくやります。そのようなケースでは前段のIdPでのユーザの挙動(入力した値や、その値から導き出された値など)を連鎖する後段のIdPにも伝えないと、ユーザ名を2回入力する必要が出てきたり、とUXを毀損してしまいがちです。

    このようなケースではid_token_hintの中に必要なパラメータを詰め込んで後段のIdPへJWTとして渡してあげることで格段にUXが向上します。
    (Office365のケースではOpenID Connect→ws-federationの連鎖なのでusernameというパラメータを使っていますが)

    仕様では3.1.2.1のAuthentication Requestの項に定義されています。(OpenIDファウンデーションジャパンの日本語訳から引用)
    id_token_hint
    OPTIONAL. Authorization Server が以前発行した ID Token. Client が認証した End-User の現在もしくは過去のセッションに関するヒントとして利用される. もしこの ID Token に紐づく End-User が認証済, もしくはこのリクエスト中で認証された場合, Authorization Server はポジティブレスポンスを返す. さもなければ, Authorization Server は login_required のようなエラーを返す (SHOULD). prompt=none を利用する場合は, 可能であれば id_token_hint を指定するべきであり (SHOULD), さもなければ invalid_request を返しても良い (MAY). ただしサーバーはその場合可能な限りサクセスレスポンスを返すこと. id_token_hint 利用時は, ID Token の audience に Authorization Server 自身が含まれている必要はない.
    id_token_hint として使用するために RP によって受信された OP からの ID Token が暗号化されていた場合, クライアントは暗号化された ID Token を含んだ署名済みの ID Token を復号しなければならない (MUST). クライアントは Authentication Server に送信する署名済みの ID Token をサーバーが ID Token を復号できる鍵を用いて再暗号化し, id_token_hint の値として使用してもよい (MAY).

    横綱:claims

    最後の横綱級はなんといってもclaimsでしょう。理由はシンプルで私も共同議長を勤めさせていただいるOpenID FoundationのeKYC and Identity Assurance WGで策定中のOpenID Connect for Identity Assuranceの仕様はclaimsがあるから成り立っている、といっても過言ではないからです。

    パラメータの意味合いとしてはRPからOPへの認証要求時にclaimsに指定した属性をid_tokenもしくはuserInfoとして提供することを明示的に求める、というものです。OpenID Connect for Identity Assuranceではこの機能を拡張してRPがOPに検証済みの属性を要求する、ということを実現しています。

    仕様では5.5のRequesting Claims using the "claims" Request Parameterの項に定義されています。(OpenIDファウンデーションジャパンの日本語訳から引用)
    claims
    OPTIONAL. 当パラメータは, 特定の Claim の返却を要求するのに用いられる. 値は要求する Claim をリスト化した JSON オブジェクトである.

    claims Authentication Request パラメータは, 特定の Claim を UserInfo Endpoint から, かつ/または ID Token 内で, 返却することを要求する. これは要求する Claim のリストを含む JSON オブジェクトとして表される. 要求する Claim のプロパティが指定されていてもよい (MAY).

    claims パラメータのサポートは任意である (OPTIONAL). 当パラメータをサポートしない OP に対して RP が当パラメータを使用したとき, OP は 適切と思われるヒューリスティックな方法を用いて, RP と End-User にとって有益と思われる Claim のセットを返すべきである (SHOULD). Discovery で得られる claims_parameter_supported は, OP が当パラメータをサポートしているかどうかを示す.

    claims パラメータ値は, OAuth 2.0 要求の中で, UTF-8 でエンコードされた JSON として表される (最終的には OAuth パラメータとして受け渡されるときに form-urlencoded される). Request Object 値として使用される際は, Section 6.1 により, JSON が claims メンバーの値として使用される.

    Claim 要求 JSON オブジェクトのトップレベルメンバーは以下の通り:

    userinfo
    OPTIONAL. UserInfo Endpoint へ返却を要求する個々の Claim のリストを示す. 当メンバーが存在した場合, scope 値で要求された Claim に加え, 当メンバーでリストされた Claim も返却される. 当メンバーが存在しなかった場合, scope 値で要求された Claim のみが返却される.
    userinfo メンバーを指定する際は, UserInfo Endpoint を使用するために, response_type に対し, Access Token を Client に発行するタイプの値を指定しなければならない (MUST).
    id_token
    OPTIONAL. ID Token 内に格納して返却を要求する個々の Claim のリストを示す. 当メンバーが存在した場合, デフォルトの Claim に加え, 当メンバーでリストされた Claim も返却される. 当メンバーが存在しなかった場合, デフォルトの Claim のみが返却される. デフォルトの Claim 等の ID Token の定義については Section 2を, フロー毎の ID Token 要件については Section 3.1.3.63.2.2.103.3.2.113.3.3.6 を参照すること.

    上記以外のメンバーが存在してもよい (MAY). 認識できないメンバーが使用された場合は無視しなければならない (MUST).


    通常のOPでclaimsを利用している実装ってあまり見かけないのですが、先日某芸能事務所のファンクラブサイトに娘がログインするところをトレースしていたらclaimsを使っているのが判明し驚愕しました(w)
    ちなみになぜclaimsを使っているのかはよくわかりません。。。自前RPと自前OPのはずなのでこんなことをしなくてもOPが必要な属性をid_tokenやuserInfoに入れて返してあげれば済むと思うのですが・・・



    いかがでしたか?
    他にもご紹介したいニッチなパラメータもいっぱいあるので、また機会があればご紹介できればと思います。

    2020年9月26日土曜日

    Microsoft IgniteでのDID/VC関連トピックス

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

    先週のオンライン開催されたMicrosoft IgniteではAzure Active Directoryを始めとするアイデンティティ関連のトピックスや新機能発表が色々とありました。

    個人的に気になったのは、

    • Identity ProtectionがAzure AD B2Cにもきた
    • 条件付きアクセスがGraph API経由で触れる様になった
    • ヘッダ認証が使える様になった
    • VC関係の近況と退役軍人向けの教育プログラムへの適用事例
    の4点です。

    1点目は先日Blogにも書いた通り、今後のB2C向けサービスの幅が非常に広がる話ですし、2点目はリスクイベントを拾ってTeamsなど外部サービスに連携させるデモなどもあり運用面で非常に有用だと思いました。また3点目は以前Ping Access連携で実現していたことがMS純正でできる様になる、というところでレガシーアプリケーションへの適用の面では非常に有用だと思います。

    そして、最後が本日のメインであるDID/VC関係の近況です。
    * DID : Decentralized Identifier
    * VC : Verifiable Credentials

    こちらも以前ブログに書きましたが、その後ブラッシュアップされてきているもです。
    ※この辺のキーワード(含む自己主権型アイデンティティ/SSI)の使い方は間違って使われているケースが散見される(Decentralized Identityとか)たり、=ブロックチェーンみたいな誤解もあるみたいなのでどこかでちゃんとまとめないとな、、、と。この辺りのスライドを書いてから、自分の理解も進んだのと標準化の方向性も進捗してるのでどこかでUpdateします。。。

    話がそれましたが、早速Igniteでのトピックスを追いかけてみましょう。

    VC関係の話が取り上げられたのはキーノートを含む以下の4つのセッションです。

    全体を簡単に要約すると、
    • VCを使うとVerifier(学校とか企業とか)が各種証明(学歴、職歴など)を簡単・確実に検証できるよ
    • VerifierがSubject(個人)の情報を一生懸命集める事によるプライバシー上の懸念もなくなるよ
    • すでに米国の退役軍人向けの教育プログラム(MILGears)で実証実験が走ってるよ
    • 今はプライベートプレビューだけど、もうすぐみんな使える様になるぞ!
    • VCをLinkedInのプロファイルに追加できるなるぞ!
    みたいな話でした。

    ざっくりみていきましょう。

    まずはSatyaのキーノートです。後半54分あたりからDecentralized Identity Systemの話が出てきます。

    私たちはオープンな分散型アイデンティティシステムを作り上げようとしています。そしてそれは、どんな中央集権的なオーソリティやテック企業からも独立しています。すでに退役軍人向けの教育プログラムでパイロットをしています。


    彼らは自身の検証済みの記録をスマートフォン上のWalletに保管することができ、大学や企業に直接提示することができます。大学はそれ(VC)を数秒で検証することができ、センシティブなデータを保管する必要はありません。また退役軍人たちは、VCをLinkedInのプロファイルに追加することができ、新たな職業を得る機会に役立つでしょう。


    次はVasuのキーノートです。途中16分すぎから出てくるIrinaのパートでIdentityの話があり、17分過ぎから分散型アイデンティティの話です。

    オンライン化に伴いデジタル信頼やプライバシーはとっても重要なものになっています。しかし現在私たちはアイデンティティをデジタルに検証する仕組みを持っておらず、またデジタル・プライバシーは私たちのコントロール外となっています。私たちがパーソナルデータをオンラインで共有する際、企業・組織は記載されている目的外には利用せず、許可なく共有することはないことを約束し、それらのパーソナルデータが盗まれない様に、誤用されない様に保護する努力をします。マイクロソフトはすべての人々が自身のアイデンティティをコントロールできる様にする必要があると考えています。アイデンティティはどんな組織やテック企業からも独立しているべきなのです。これが私たちが分散型アイデンティティ分野に投資する理由であり、すべての人が自身のデジタルアイデンティティを所有し、誰が何の目的でいつアクセスできるか決定できるべきだと考えています。
    年齢、学歴、職歴、クレジットスコア、生体情報は利用者自身のコントロール配下におかれ、政府や大学や企業の様なサードパーティはそれらの情報を検証できる様になります。それらすべてのクレデンシャルはデジタル・カードの様な形でMicrosoft Authenticatorの様なデジタル・ウォレットに保存されます。



    私たちはVerifiable CredentialsとDecentralized Identifiersに関するオープンな標準に基づく自己主権型アイデンティティのヴィジョンを現実のものとするため、Decentralized Identity Foundationと共に活動しています。

    私たちはこの分散型アイデンティティのシステムを多くの顧客と共にパイロットしており、MILGearsの教育プログラムもその一つです。 


    ここでMilGearの人のインタビュー動画が流れた後、VasuがIrinaに今のステータスと今後どうなるの?って聞いてくれます(Good Job!)。「We're currently in private preview, but soon anyone will be able to try it.」素晴らしい!


    次はおなじみJoyです。19分くらいから分散型アイデンティティ関係の話が始まります。


    我々が物理的な世界で行ってきたパスポートや学位やその他証明書のやりとりをデジタル化するにはどうすれば良いのでしょうか?私たちはデジタルにそれらのクレデンシャルを検証するメカニズムが必要です。しかし今日私たちが持っているシステムはデータ漏洩や誤用で溢れています。私たちは分散型アイデンティティシステムとVerifiable Credentialsが解決策になると信じています。コミュニティの努力とオープンな標準をベースに構成され、既存のアイデンティティシステムと簡単に接続することが可能です。それはオープンな標準技術を用いており、マイクロソフトを含むどんな組織も支配することはできません。そして、それはすでに現実のものとなっているのです。


    ここでやはりMILGearsの事例の話。どこにVerifiable Credentialsを提示したのか確認することができます。


    退役後、大学や企業に就職する際に、軍がIssuerとなってそれまでの学歴や経歴を証明する、という形態の様ですね。

    退役後、高等教育や企業への就職する際、大学や企業は学歴や軍でのトレーニング履歴にアクセスする方法がありませんでした。そのため、彼らは証明書などのドキュメントを収集し確認する長いプロセスを必要としていました。そして、多くの場合、それらのプロセスは紙をベースとしており、数ヶ月を要することもありました。

    このプロセスをデジタル化することにより、彼らの待ち時間を減らすだけでなく、自身のデータに関するコントロールを行うことができる様になりました。大学がデータを収集し、保管し、保護する必要がなくなったのです。


    ここでMILGearsのデモです。ここでMILGearsが保持している記録をVerifiable Credentialsとして発行します。

    QRコードが表示されるのでMicrosoft Authenticatorで読み込むとカードの形でVerifiable CredentialsがAuthenticator上に追加されます。

    次は大学にVerifiable Credentialsを提示します。こちらもQRコードを読み込むとVerifiable Credentialsが提示され、検証済みのデータとして大学側へ連携されます。


    デモに続いてテクニカルな話をMelanieさんから。必要なのはAzure Active Directoryサブスクリプション(正確にはPremium P1以上)とKeyVaultだけ(こちらも正確にはStorageは必要)。やるべきことはたった3つ。KeyVaultでキーペアの作成をする、Rulesファイルを作る、Displayファイルを作る、とってもシンプルでしょ、的なデモです。
    こちら、Rulesファイルですね。まぁ、確かに簡単な構造のjsonです。

    こちらはDisplayファイル。こちらも非常にシンプルなjsonファイル。Authenticatorに表示されるカードのロゴとか色を決める感じですね。


    というところでJoyのキーノートは終了です。

    最後はMicrosoft Mechanicsですが、こちらも結局Joyががっつり話をします。
    中身的には、W3Cの標準をちゃんとみてるよ、という話とこれまであったMILGearsの事例、KeyVault、RulesとDisplayなど実装にかかる話のおさらい的な感じのセッションです。

    MILGearsの事例をベースにIssuer=MILGears/Subject(Holder)=退役軍人/Verifier=大学など、と関係性を解説してくれています。わかりやすい。

    ブロックチェーンとの関係も最後に少しだけ触れられます。基本的にDID Documentと公開鍵の置き場所として使ってるだけです。



    全体的にまだ詳しいところは触れられない感じでしたが、こうして動いている姿を見ることができると非常に面白いですね。MILGearsのケースも非常に面白いと思います。退役軍人っていうともっと年寄りでそのまま隠居する?ってイメージでしたが結構若い間に退役して、その後大学に行ったり企業に就職したりするケースもあり、その場合に身元保証を軍がやる、というのは日本にいるとあまりイメージが湧きにくいとは思いますが、話を聞いてみると納得、という非常に良いユースケースだと思います。

    DID/VCはとても面白いテクノロジだとは思いますし、可能性も感じますが、別にDID/VCじゃなくても良いじゃん、というケースばかりなので今後DID/VCならではのユースケースがもっと研究されると良いな、というのが全体的な感想でした。




    2020年5月20日水曜日

    Build速報!FacebookでAzure ADへログインする

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

    Buildですね。リモート開催になって日本からでも参加しやすくなって睡眠時間が削られる日々をお過ごしだと思います。

    今回も色々とAzure ADに関する新機能の発表がありました。

    詳しくはAlexのBlogを参照してもらえれば良いのですが、今回はAzure AD B2Bの直接フェデレーションへのFacebookログインの登場(Public Preview)の話です。

    AlexのBlog)
    https://techcommunity.microsoft.com/t5/azure-active-directory-identity/build-2020-fostering-a-secure-and-trustworthy-app-ecosystem-for/ba-p/1257360

    Azure AD B2Bの直接フェデレーションについてはこれまでも取り上げてきましたが、Googleに対応してから約2年、ここに来てFacebookに対応しました。

    Googleとの連携の件
    https://idmlab.eidentity.jp/2018/08/azure-ad-b2bgoogleid.html

    カスタムドメイン vs 直接フェデレーションの件
    https://idmlab.eidentity.jp/2020/05/azure-adbyoid.html



    もはやB2Bとは?というしかない状態なのですが、早速触ってみましょう。

    外部アイデンティティプロバイダの設定

    これまでも紹介したことのある画面です。Azure ADのポータルを開き、External Identitiesメニューから「すべてのIDプロバイダー」を開くと「Google」に加えて新たに「Facebook」が選べるようになっています。


    ここでFacebookを追加して、AppIdとAppSecretを追加すれば基本は終わりなのですが、設定前に外部ユーザによるサインアップを許可しておく必要があります。
    「外部コラボレーションの設定」メニューを見ると、新しく「ユーザーフローによるゲストセルフサービスサインアップを有効にする」という設定が追加されているので有効にしておきましょう。

    後はFacebook Developerコンソールで作成したアプリケーションのAppIdとAppSecretを設定すれば終わりです。

    Facebook側の設定方法はAzure AD B2Cのドキュメントに記載がありますので、1点を除いてこちらをそのまま使って大丈夫です。
    https://docs.microsoft.com/en-us/azure/active-directory-b2c/identity-provider-facebook

    その1点とは、そうですredirect_uriです。
    直接フェデレーションの場合にFacebookに設定するredirect_uriはどうなるのか?というと、
    https://login.microsoftonline.com/te/{テナントID}/oauth2/authresp
    となります。

    ここまで設定を進めると、ユーザーフローからAzure ADにアクセスするためのアプリケーション「aad-extensions-app」が自動的に登録されます。


    ちなみに、このアプリケーションを削除すると面倒なことになるので、消さないようにしてください。
    万一消してしまったらAzure AD B2Cでのb2c-extension-appと同じように回復をしてください。
    参考)B2Cでの回復手順
    https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/extensions-app


    ユーザーフローの登録

    外部IDプロバイダの設定が終わったら、次はユーザーフローの登録です。
    基本この辺りもAzure AD B2Cと同じです。


    ユーザーフローの名称(ポリシー名となります)、利用するIDプロバイダ、連携する属性を設定していきます。
    尚、属性は標準で用意されているもの以外に「カスタムのユーザー属性」メニューから自分で好きな属性を追加することもできます。

    これでIDプロバイダとユーザーフローの登録はおしまいです。

    アプリケーションの登録

    次に、先ほど作成したユーザーフローを使ってサインアップやサインインを行う対象となるアプリケーションを登録します。
    ポイントは、APIのアクセス許可で「User.Read」スコープに対して管理者による同意をしておくこと、です。現状のユーザーフローでのユーザ作成やログイン時にユーザ自身による同意が上手く取れない?のでこの設定は入れておく必要がありそうです。

    ユーザーフローとアプリケーションの紐づけ

    アプリケーションを作成したら、先に作成しておいたユーザーフローを使う様に構成をします。
    先ほどのExternal Identitiesメニューに戻り、先ほど作成したユーザーフローを開きます。アプリケーションに関する設定項目がありますので、ここで作成したアプリケーションを指定します。

    これで一通りの設定は終了です。

    動作確認

    では早速動かしてみます。

    このアプリケーションにアクセスする為には、以下のパラメータをつけてAuthorizationエンドポイント(https://login.microsoftonline.com/{テナントID}/oauth2/authorize)へアクセスする必要があります。(通常のOpenID Connectのアプリケーションと同じです)

    • client_id={登録したアプリのClient Id}
    • response_type=id_token
    • scope=openid
    • nonce={生成したnonceの値。テストなら何でもOK}
    • redirect_uri={登録したアプリのredirect_url}

    今回、アプリケーションとしてはhttps://jwt.msを使ったのでこんなURLになります。
    https://login.microsoftonline.com/{テナントID}/oauth2/authorize?client_id={クライアントID}&response_type=id_token&scope=openid&nonce=hoge&redirect_uri=https:%2F%2Fjwt.ms

    実行してみると、いつものサインイン画面になるので、まずはアカウントを作成します。

    アカウントの作成画面に「Facebookアカウントでサインイン」というメニューが出来ています。
    ここでFacebookアカウントでサインインすると、Azure ADへのアカウント登録を行う際に追加で登録するアカウントを入力する画面が出てきます。

    続行するとアカウントがAzure AD上に登録されます。
    アカウントタイプはゲスト、ソースはFacebookになっているのがわかります。


    ちなみに登録後、サインインする場合はサインインオプションをクリックするとFacebookログインのメニューが出ていますので、そちらを使ってサインインします。


    いかがでしょうか?
    基本はAzure AD B2Cの機能の一部を通常のAzure ADの直接フェデレーション向けに開放しただけなので、Azure AD B2Cに慣れている方は直感的に理解できると思います。

    しかし、冒頭にも書きましたが、こうなってくると「B2Bとは?」という疑問がやはり出てきますが大人しくしておきましょう。

    おまけ

    たまたまテストに使ったAzure ADにG-SuiteとのSSO設定があったので、SAMLの属性マッピングの調整をちょこっとして、GmailにAzure ADの直接フェデレーションを使ってFacebookアカウントでログインする、というくだらないものを作ってみたので動画を貼っておきます。