Azure Active Directory B2C カスタム ポリシーを使用して REST API を呼び出す

Azure Active Directory B2C (Azure AD B2C) カスタム ポリシーを使用することで、Azure AD B2C の外部で実装するアプリケーション ロジックを操作できます。 これを行うには、エンドポイントに対して HTTP 呼び出しを行います。 Azure AD B2C カスタム ポリシーには、この目的のための RESTful 技術プロファイルが用意されています。 この機能を使用することで、Azure AD B2C カスタム ポリシー内では使用できない機能を実装することができます。

この記事では、次のことについて説明します。

  • RESTful サービスとして使用するサンプル Node.js アプリを作成してデプロイする。

  • RESTful 技術プロファイルを使用して、Node.js RESTful サービスに対して HTTP 呼び出しを行う。

  • RESTful サービスがカスタム ポリシーに返すエラーを処理または報告する。

シナリオの概要

Azure AD B2C カスタム ポリシーを使用してユーザー体験にブランチを作成する」では、"個人用アカウント" を選択したユーザーは、有効な招待アクセス コードを指定して続行する必要があります。 ここでは静的アクセス コードを使用していますが、実際のアプリはこの方法では動作しません。 アクセス コードを発行するサービスがカスタム ポリシーの外部にある場合は、そのサービスを呼び出し、ユーザーが入力したアクセス コードを渡して検証する必要があります。 そのアクセス コードが有効な場合は、サービスから HTTP 200 OK 応答が返され、Azure AD B2C によって JWT トークンが発行されます。 それ以外の場合は、サービスから HTTP 409 Conflict 応答が返されるため、ユーザーはアクセス コードを再入力する必要があります。

A flowchart of calling a R E S T A P I.

前提条件

Note

この記事は、Azure Active Directory B2C での独自のカスタム ポリシーの作成と実行に関するハウツー ガイド シリーズの一部です。 このシリーズは、最初の記事から読み始めることをお勧めします。

手順 1 - Node.js アプリを作成してデプロイする

外部アプリとして機能するアプリをデプロイする必要があります。 その後、カスタム ポリシーがこのアプリに対して HTTP 呼び出しを行います。

手順 1.1 - Node.js アプリを作成する

  1. ノード アプリケーションをホストするフォルダーを作成します (例: access-code-app)。

  2. ターミナルで、cd access-code-appなどのノード アプリ フォルダーにディレクトリを変更し、npm init -yを実行します。 このコマンドは、Node.js プロジェクトのデフォルトの package.json ファイルを作成します。

  3. ターミナルで、npm install express body-parser を実行します。 このコマンドは、Express フレームワークと body-parser パッケージをインストールします。

  4. プロジェクトで、index.js ファイルを作成します。

  5. VS Codeで index.js ファイルを開き、次のコードを追加します。

        const express = require('express');
        let bodyParser = require('body-parser')
        //Create an express instance
        const app = express();
    
        app.use( bodyParser.json() );       // to support JSON-encoded bodies
        app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
          extended: true
        }));
    
    
        app.post('/validate-accesscode', (req, res) => {
            let accessCode = '88888';
            if(accessCode == req.body.accessCode){
                res.status(200).send();
            }else{
                let errorResponse = {
                    "version" :"1.0",
                    "status" : 409,
                    "code" : "errorCode",
                    "requestId": "requestId",
                    "userMessage" : "The access code you entered is incorrect. Please try again.",
                    "developerMessage" : `The provided code ${req.body.accessCode} does not match the expected code for user.`,
                    "moreInfo" :"https://docs.microsoft.com/en-us/azure/active-directory-b2c/string-transformations"
                };
                res.status(409).send(errorResponse);                
            }
        });
    
        app.listen(80, () => {
            console.log(`Access code service listening on port !` + 80);
        });
    

    ユーザーが間違ったアクセス コードを送信した場合、REST API から直接エラーを返すことができることを確認できます。 カスタム ポリシーでは、HTTP 4xx エラー メッセージ (たとえば、400 (無効な要求)、409 (競合) 応答状態コードなど) を errorResponse 変数で示されているような形式の応答 JSON の本文とともに返すことができます。 アプリ内の accessCode のソースは、データベースから読み取ることができます。 返される検証エラー メッセージについて詳細を確認してください。

  6. 以下の手順で、アプリが期待どおりに動作することをテストします。

    1. ターミナルで、node index.js コマンドを実行してアプリ サーバーを起動します。
    2. この例に示すような POST 要求を行うには、Microsoft PowerShellPostman などの HTTP クライアントを使用します。
        POST http://localhost/validate-accesscode HTTP/1.1
        Host: localhost
        Content-Type: application/x-www-form-urlencoded
    
        accessCode=user-code-code
    

    user-code-code を、54321 などのユーザーが入力したアクセス コードに置き換えます。 PowerShell を使用している場合は、次のスクリプトを実行します。

        $accessCode="54321"
        $endpoint="http://localhost/validate-accesscode"
        $body=$accessCode
        $response=Invoke-RestMethod -Method Post -Uri $endpoint -Body $body
        echo $response
    

    間違ったアクセス コードを使用した場合、応答は以下の JSON スニペットのようになります。

        {
            "version": "1.0",
            "status": 409,
            "code": "errorCode",
            "requestId": "requestId",
            "userMessage": "The access code you entered is incorrect. Please try again.",
            "developerMessage": "The provided code 54321 does not match the expected code for user.",
            "moreInfo": "https://docs.microsoft.com/en-us/azure/active-directory-b2c/string-transformations"
        }
    

この時点で、Node.js アプリをデプロイする準備が整いました。

手順 1.2 - Azure App Service に Node.js アプリをデプロイする

カスタム ポリシーが Node.js アプリに到達するには、アクセス可能である必要があるため、それをデプロイする必要があります。 この記事では、Azure App Service を使用してアプリをデプロイしますが、別のホスティング アプローチを使用します。

Azure へのアプリのデプロイに関する記事の手順に従って、Node.js アプリを Azure にデプロイします。 アプリの名前には、custompolicyapi などのわかりやすい名前を使用します。 したがって、以下のようになります。

  • アプリの URL は https://custompolicyapi.azurewebsites.net のようになります。

  • サービス エンドポイントは https://custompolicyapi.azurewebsites.net/validate-accesscode のようになります。

Microsoft PowerShellPostman などの HTTP クライアントを使用して、デプロイしたアプリをテストできます。 今回は、エンドポイントとして https://custompolicyapi.azurewebsites.net/validate-accesscode URL を使用します。

手順 2 - REST API を呼び出す

アプリが実行されたので、カスタム ポリシーから HTTP 呼び出しを行う必要があります。 Azure AD B2C カスタム ポリシーには、外部サービスの呼び出しに使用する RESTful 技術プロファイルが用意されています。

手順 2.1 - RESTful 技術プロファイルを定義する

ContosoCustomPolicy.XML ファイルで ClaimsProviders セクションを見つけ、次のコードを使用して新しい RESTful 技術プロファイルを定義します。

    <!--<ClaimsProviders>-->
        <ClaimsProvider>
            <DisplayName>HTTP Request Technical Profiles</DisplayName>
            <TechnicalProfiles>
                <TechnicalProfile Id="ValidateAccessCodeViaHttp">
                    <DisplayName>Check that the user has entered a valid access code by using Claims Transformations</DisplayName>
                    <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                    <Metadata>
                        <Item Key="ServiceUrl">https://custompolicyapi.azurewebsites.net/validate-accesscode</Item>
                        <Item Key="SendClaimsIn">Body</Item>
                        <Item Key="AuthenticationType">None</Item>
                        <Item Key="AllowInsecureAuthInProduction">true</Item>
                    </Metadata>
                    <InputClaims>
                        <InputClaim ClaimTypeReferenceId="accessCode" PartnerClaimType="accessCode" />
                    </InputClaims>
                </TechnicalProfile>
            </TechnicalProfiles>
        </ClaimsProvider>
    <!--</ClaimsProviders>-->

プロトコルから、RestfulProvider を使用するように技術プロファイルが構成されていることを確認できます。 また、メタデータ セクションでは、次の情報も確認できます。

  • ServiceUrl は API エンドポイントを表しています。 その値は https://custompolicyapi.azurewebsites.net/validate-accesscode です。 別の方法で Node.js アプリをデプロイした場合は、必ずエンドポイントの値を更新してください。

  • SendClaimsIn には、RESTful クレーム プロバイダーへの入力要求の送信方法を指定します。 指定できる値: Body (default)FormHeaderUrl、または QueryString。 この記事のように Body を使用する場合は、POST HTTP 動詞を呼び出し、要求の本文でキーと値のペアとして書式設定されている場合は API に送信するデータを呼び出します。 GET HTTP 動詞を呼び出し、クエリ文字列としてデータを渡す方法を確認してください。

  • AuthenticationType には、RESTful クレーム プロバイダーにより実行される認証の種類を指定します。 RESTful クレーム プロバイダーは保護されていないエンドポイントを呼び出すため、ここでは AuthenticationTypeNone に設定します。 認証の種類を Bearer に設定する場合は、アクセス トークンのストレージを指定する CryptographicKeys 要素を追加する必要があります。 RESTful クレーム プロバイダーでサポートされる認証の種類を確認してください。

  • InputClaimPartnerClaimType 属性は、API でデータを受け取る方法を指定します。

手順 2.2 - 検証技術プロファイルを更新する

Azure AD B2C カスタム ポリシーを使用してユーザー体験にブランチを作成する」では、要求変換を使用して accessCode を検証しました。 この記事では、外部サービスへの HTTP 呼び出しを行って accessCode を検証します。 そのため、新しいアプローチを反映するようにカスタム ポリシーを更新する必要があります。

AccessCodeInputCollector 技術プロファイルを見つけ、ValidationTechnicalProfile 要素の ReferenceIdValidateAccessCodeViaHttp に更新します。

更新前:

    <ValidationTechnicalProfile ReferenceId="CheckAccessCodeViaClaimsTransformationChecker"/>

この行を次のように変更します。

    <ValidationTechnicalProfile ReferenceId="ValidateAccessCodeViaHttp"/>

この時点で、IdCheckAccessCodeViaClaimsTransformationChecker の技術プロファイルは不要のため、削除することができます。

手順 3 - カスタム ポリシー ファイルをアップロードする

Node.js アプリが実行されていることを確認し、「カスタム ポリシー ファイルをアップロードする」の手順に従って、ポリシー ファイルをアップロードします。 ポータルに既にあるファイルと同じ名前のファイルをアップロードする場合は、[カスタム ポリシーが既に存在する場合は上書きします] を選択してください。

手順 4 - カスタム ポリシーをテストする

カスタム ポリシーをテストする」の手順に従って、カスタム ポリシーをテストします。

  1. [アカウントの種類] で、[個人用アカウント] を選択します。
  2. 必要に応じて残りの詳細を入力し、[続行] を選択します。 新しい画面が表示されます。
  3. [アクセス コード] に「88888」と入力し、[続行] を選択します。 ポリシーの実行が完了すると、https://jwt.ms にリダイレクトされ、デコードされた JWT トークンが表示されます。 手順を繰り返し、88888 以外の別のアクセス コードを入力すると、次のエラーが表示されます: 入力したアクセス コードが正しくありません。もう一度実行してください。

手順 5 - デバッグ モードを有効にする

開発時には、API によって送信される詳細なエラー (developerMessagemoreInfo など) を確認する必要がある場合があります。 この場合は、RESTful 技術プロバイダーでデバッグ モードを有効にする必要があります。

  1. ValidateAccessCodeViaHttp 技術プロバイダーを見つけて、技術プロバイダーの metadata に次の項目を追加します。

        <Item Key="DebugMode">true</Item>
    
  2. 変更を保存し、ポリシー ファイルをアップロードします。

  3. カスタム ポリシーをテストします。 間違ったアクセス コードを入力するようにします。 下のスクリーンショットに示すようなエラーが表示されます。

    A screenshot error when you enable debug mode.

複雑な要求 JSON ペイロードを処理する

呼び出す REST API で複雑な JSON ペイロードを送信する必要がある場合は、GenerateJson JSON 要求変換を使用してペイロードを作成することができます。 ペイロードを生成したら、ClaimUsedForRequestPayload メタデータ オプションを使用して、JSON ペイロードを含む要求の名前に設定できます。

たとえば、以下の要求変換を使用して JSON ペイロードを生成します。

    <ClaimsTransformation Id="GenerateRequestBodyClaimsTransformation" TransformationMethod="GenerateJson">
        <InputClaims>
            <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="customerEntity.email" />
            <InputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="customerEntity.userObjectId" />
            <InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="customerEntity.firstName" />
            <InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="customerEntity.lastName" />
            <InputClaim ClaimTypeReferenceId="accessCode" TransformationClaimType="customerEntity.accessCode" />
        </InputClaims>
        <InputParameters>
            <InputParameter Id="customerEntity.role.name" DataType="string" Value="Administrator" />
            <InputParameter Id="customerEntity.role.id" DataType="long" Value="1" />
        </InputParameters>
        <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="requestBodyPayload" TransformationClaimType="outputClaim" />
        </OutputClaims>
    </ClaimsTransformation>

ClaimsTransformation では、次の JSON オブジェクトが生成されます。

{
   "customerEntity":{
      "email":"john.s@contoso.com",
      "userObjectId":"01234567-89ab-cdef-0123-456789abcdef",
      "firstName":"John",
      "lastName":"Smith",
      "accessCode":"88888",
      "role":{
         "name":"Administrator",
         "id": 1
      }
   }
}

次に、下に示すように、RESTful 技術プロバイダーの MetadataInputClaimsTransformationsInputClaims を更新します。

    <Metadata>
        <Item Key="ClaimUsedForRequestPayload">requestBodyPayload</Item>
        <!--Other Metadata items -->
    </Metadata>
    
    <!--Execute your InputClaimsTransformations to generate your request Payload-->
    <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="GenerateRequestBodyClaimsTransformation" />
    </InputClaimsTransformations>
    
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="requestBodyPayload" />
    </InputClaims>

REST API からデータを受信する

REST API からデータが返される場合 (ポリシーに要求として含める場合)、RESTful 技術プロファイルの OutputClaims 要素で要求を指定して受信できます。 ポリシーで定義されている要求の名前が REST API で定義されている名前と異なる場合は、PartnerClaimType 属性を使用してこれらの名前をマップする必要があります。

データの受信」の手順を使用して、カスタム ポリシーで想定されるデータ形式にする方法、null 値を処理する方法、および REST API の入れ子になった JSON 本文を解析する方法について説明します。

次のステップ

次は、以下を学びます。