Azure Active Directory B2C を使用してサンプルの Angular シングルページ アプリケーションで認証を構成する
この記事では、サンプルの Angular シングルページ アプリケーション (SPA) を使用して、Azure Active Directory B2C (Azure AD B2C) 認証を Angular アプリに追加する方法について説明します。
概要
OpenID Connect (OIDC) は OAuth 2.0 を基盤とした認証プロトコルであり、ユーザーをアプリケーションに安全にサインインさせるために利用できます。 この Angular サンプルでは、MSAL Angular と MSAL Browser を使用します。 MSAL は、Angular SPA への認証と承認のサポートの追加を簡素化する、Microsoft 提供のライブラリです。
サインイン フロー
サインイン フローでは、次の手順が実行されます。
- ユーザーがアプリを開き、[サインイン] を選択します。
- アプリによって認証要求が開始され、ユーザーが Azure AD B2C にリダイレクトされます。
- ユーザーはサインアップまたはサインインし、パスワードをリセットするか、ソーシャル アカウントを使用してサインインします。
- サインインに成功すると、Azure AD B2C からアプリに承認コードが返されます。 アプリによって次のアクションが実行されます。
- 承認コードを ID トークン、アクセス トークン、および更新トークンと交換する。
- ID トークン クレームを読み取る。
- 後で使用できるように、アクセス トークンと更新トークンをメモリ内キャッシュに格納する。 アクセス トークンを使用することで、ユーザーは Web API などの保護されたリソースを呼び出すことができます。 更新トークンは、新しいアクセス トークンを取得するために使用されます。
アプリの登録
アプリで Azure AD B2C を使用してサインインし、Web API を呼び出せるようにするには、Azure AD B2C テナントに 2 つのアプリケーションを登録する必要があります。
シングルページ アプリケーション (Angular) の登録により、アプリで Azure AD B2C を使用してサインインできるようになります。 アプリの登録時に、"リダイレクト URI" を指定します。 リダイレクト URI は、ユーザーが Azure AD B2C で認証された後にリダイレクトされるエンドポイントです。 アプリ登録プロセスは、アプリを一意に識別するアプリケーション ID (またはクライアント ID として知られています) を生成します。 この記事では、例としてアプリ ID: 1 を使用します。
Web API を登録すると、保護された Web API をアプリで呼び出すことができます。 この登録により、Web API のアクセス許可 (スコープ) が公開されます。 アプリの登録プロセスによって、Web API を一意に識別するアプリケーション ID が生成されます。 この記事では、例としてアプリ ID: 2 を使用します。 アプリ (アプリ ID: 1) のアクセス許可を Web API スコープ (アプリ ID: 2) に付与します。
次の図は、アプリの登録とアプリのアーキテクチャを示しています。
Web API の呼び出し
認証が完了した後、ユーザーがアプリと対話すると、保護された Web API が呼び出されます。 その Web API では、ベアラー トークン認証が使用されます。 ベアラー トークンは、アプリによって Azure AD B2C から取得されたアクセス トークンです。 アプリでは、HTTPS 要求の Authorization ヘッダーでトークンを渡します。
Authorization: Bearer <access token>
アクセス トークンのスコープが Web API のスコープと一致しない場合、認証ライブラリでは正しいスコープの新しいアクセス トークンが取得されます。
サインアウト フロー
サインアウト フローには、次の手順が含まれます。
- アプリから、ユーザーがサインアウトします。
- アプリによってそのセッション オブジェクトがクリアされ、認証ライブラリによってそのトークン キャッシュがクリアされます。
- アプリによってユーザーが Azure AD B2C サインアウト エンドポイントに移動し、Azure AD B2C セッションが終了されます。
- ユーザーが再びアプリにリダイレクトされます。
前提条件
この記事の手順に従う前に、コンピューターで以下が実行されていることを確認してください。
- Visual Studio Code、または別の任意のコード エディター。
- Node.js ランタイム と npm。
- Angular CLI。
手順 1: ユーザー フローを構成する
ユーザーがアプリにサインインしようとすると、ユーザー フローを介した承認エンドポイントへの認証要求がアプリによって開始されます。 ユーザー フローによって、ユーザーのエクスペリエンスが定義および制御されます。 ユーザーがユーザー フローを完了すると、Azure AD B2C によってトークンが生成され、ユーザーはアプリケーションにリダイレクトされます。
ユーザー フローまたはカスタム ポリシーの作成をまだ行っていない場合は、作成します。 手順を繰り返して、次のように 3 つの個別のユーザー フローを作成します。
- サインインと サインアップを結合したユーザー フロー (例:)
susi
。 このユーザー フローでは、パスワードを忘れた 場合のエクスペリエンスもサポート されています。 - プロファイル編集 ユーザー フロー (例:
edit_profile
) 。 - パスワードのリセット ユーザー フロー (例:
reset_password
)。
Azure AD B2C は、 B2C_1_
ユーザー フロー名の前に付加されます。 たとえば、susi
が B2C_1_susi
になります。
手順 2: Angular SPA と API を登録する
この手順では、Angular SPA と Web API アプリの登録を作成します。 また、Web API のスコープを指定します。
2.1 Web API アプリケーションを登録する
Web API アプリの登録 (App ID: 2) を作成するには、次の手順に従います。
Azure portal にサインインします。
ご自分の Azure AD B2C テナントが含まれるディレクトリを必ず使用してください。 ポータル ツールバーの [Directories + subscriptions](ディレクトリ + サブスクリプション) アイコンを選択します。
[ポータルの設定] | [Directories + subscriptions](ディレクトリ + サブスクリプション) ページの [ディレクトリ名] の一覧で自分の Azure AD B2C ディレクトリを見つけて、 [切り替え] を選択します。
Azure portal で、 [Azure AD B2C] を検索して選択します。
[アプリの登録] を選択し、 [新規登録] を選択します。
アプリケーションの名前を入力します (my-api1 など)。 [リダイレクト URI] と [サポートされているアカウントの種類] を既定値のままにします。
[登録] を選択します。
アプリ登録が完了したら、 [概要] を選択します。
アプリケーション (クライアント) ID の値を記録しておきます。これは、後で Web アプリケーションを構成するときに使用します。
2.2 スコープを構成する
作成した my-api1 アプリケーション (App ID: 2) を選択して、その [概要] ページを開きます。
[管理] の [API の公開] を選択します。
[アプリケーション ID URI] の横にある [設定] リンクを選択します。 既定値 (GUID) を一意の名前 (例: tasks-api) に置き換え、[保存] を選択します。
Web アプリケーションで Web API のアクセス トークンを要求するときに、API に対して定義する各スコープのプレフィックスとしてこの URI を追加する必要があります。
[この API で定義されるスコープ] で、 [スコープの追加] を選択します。
API への読み取りアクセスを定義するスコープを作成するには:
- [スコープ名] に tasks.read を入力します。
- [管理者の同意の表示名] で、「Read access to tasks API」を入力します。
- [管理者の同意の説明] で、「Allows read access to the tasks API」を入力します。
[スコープの追加] を選択します。
[Add a scope (スコープの追加)] を選択し、API への書き込みアクセスを定義するスコープを追加します。
- [スコープ名] に「tasks.write」を入力します。
- [管理者の同意の表示名] に、「Write access to tasks API」を入力します。
- [管理者の同意の説明] に、「Allows write access to the tasks API」を入力します。
[スコープの追加] を選択します。
2.3 Angular アプリを登録する
Angular アプリの登録を作成するには、次の手順のようにします。
- Azure portal にサインインします。
- 複数のテナントにアクセスできる場合、上部のメニューの [設定] アイコンを選択し、[ディレクトリとサブスクリプション] メニューからお使いの Azure AD B2C テナントに切り替えます。
- Azure portal で、 [Azure AD B2C] を検索して選択します。
- [アプリの登録] を選択し、 [新規登録] を選択します。
- [名前] にアプリケーションの名前を入力します。 たとえば、「MyApp」と入力します。
- [サポートされているアカウントの種類] で、 [Accounts in any identity provider or organizational directory (for authenticating users with user flows)]((ユーザー フローを使用してユーザーを認証するための) 任意の ID プロバイダーまたは組織のディレクトリのアカウント) を選択します。
- [リダイレクト URI] で、 [Single-page application (SPA)](シングルページ アプリケーション (SPA)) を選択し、URL ボックスに「
http://localhost:4200
」と入力します。 - [アクセス許可] で、 [Grant admin consent to openid and offline access permissions](OpenID とオフラインのアクセス許可に管理者の同意を与える) チェック ボックスをオンにします。
- [登録] を選択します。
- [アプリケーション (クライアント) ID] の値を記録しておきます。これは、後の手順で Web アプリケーションを構成するときに使用します。
2.5 アクセス許可を付与する
アプリ (アプリ ID: 1) にアクセス許可を付与するには、次の手順をおこないます。
[アプリの登録] を選択し、作成したアプリを選択します (アプリ ID: 1)。
[管理] の下にある [API のアクセス許可] を選択します。
[構成されたアクセス許可] の下で [アクセス許可の追加] を選択します。
[自分の API] タブを選択します。
Web アプリケーションへのアクセス許可が必要な API を選択します (アプリ ID: 2)。 たとえば、「my-api1」と入力します。
[アクセス許可] で、 [タスク] を展開し、前に定義したスコープを選択します(たとえば、tasks.read と tasks.write)。
[アクセス許可の追加] を選択します.
[<テナント名> に管理者の同意を与えます] を選択します。
[はい] を選択します。
[最新の情報に更新] を選択し、両方のスコープの [状態] に、Granted for ...(... に付与されました) と表示されていることを確認します。
[Configured permissions (構成済みのアクセス許可)] の一覧からスコープを選択し、スコープの完全な名前をコピーします。
手順 3: Angular のサンプル コードを取得する
このサンプルでは、Angular シングルページ アプリケーションでユーザーのサインアップとサインインに Azure AD B2C を使用する方法を示します。 その後、アプリでアクセス トークンを取得して、保護された Web API を呼び出します。
サンプルの .zip ファイルをダウンロードするか、次のコマンドを使用して GitHub リポジトリからサンプルをクローンします。
git clone https://github.com/Azure-Samples/ms-identity-javascript-angular-tutorial.git
3.1 Angular サンプルを構成する
SPA サンプルを入手したら、Azure AD B2C と Web API の値でコードを更新します。 サンプル フォルダーの src/app フォルダーの下にある auth-config.ts ファイルを開きます。 キーを対応する値で更新します。
Section | キー | 値 |
---|---|---|
b2cPolicies | names | 手順 1 で作成したユーザー フローまたはカスタム ポリシー。 |
b2cPolicies | authorities | your-tenant-name を Azure AD B2C のテナント名に置き換えます。 たとえば、 contoso.onmicrosoft.com を使用します。 次に、ポリシー名を、手順 1 で作成したユーザー フローまたはカスタム ポリシーに置き換えます。 (例: https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<your-sign-in-sign-up-policy> )。 |
b2cPolicies | authorityDomain | Azure AD B2C のテナント名。 (例: contoso.onmicrosoft.com )。 |
構成 | clientId | 手順 2.3 の Angular アプリケーション ID。 |
protectedResources | endpoint | Web API の URL: http://localhost:5000/api/todolist 。 |
protectedResources | スコープ | 手順 2.2 で作成した Web API のスコープ (例: b2cScopes: ["https://<your-tenant-name>.onmicrosoft.com/tasks-api/tasks.read"] )。 |
完成した src/app/auth-config.ts のコードは、次のサンプルのようになります。
export const b2cPolicies = {
names: {
signUpSignIn: "b2c_1_susi_reset_v2",
editProfile: "b2c_1_edit_profile_v2"
},
authorities: {
signUpSignIn: {
authority: "https://your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com/b2c_1_susi_reset_v2",
},
editProfile: {
authority: "https://your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com/b2c_1_edit_profile_v2"
}
},
authorityDomain: "your-tenant-name.b2clogin.com"
};
export const msalConfig: Configuration = {
auth: {
clientId: '<your-MyApp-application-ID>',
authority: b2cPolicies.authorities.signUpSignIn.authority,
knownAuthorities: [b2cPolicies.authorityDomain],
redirectUri: '/',
},
// More configuration here
}
export const protectedResources = {
todoListApi: {
endpoint: "http://localhost:5000/api/todolist",
scopes: ["https://your-tenant-namee.onmicrosoft.com/api/tasks.read"],
},
}
手順 4: Web API のサンプル コードを取得する
Web API を登録し、そのスコープを定義したので、Azure AD B2C テナントで動作するように Web API コードを構成します。
*.zip アーカイブをダウンロードするか、GitHub からサンプルの Web API プロジェクトをクローンします。 また、次のコマンドを使用して、GitHub で Azure-Samples/active-directory-b2c-javascript-nodejs-webapi プロジェクトを直接参照することもできます。
git clone https://github.com/Azure-Samples/active-directory-b2c-javascript-nodejs-webapi.git
4.1 Web API を構成する
サンプル フォルダーの config.json ファイルを開きます。 このファイルには、Azure AD B2C ID プロバイダーに関する情報が含まれています。 Web API アプリではこの情報を使用して、Web アプリからベアラー トークンとして渡されるアクセス トークンが検証されます。 アプリ設定の次のプロパティを更新します。
Section | キー | 値 |
---|---|---|
資格情報 | tenantName | Azure AD B2C テナント名の最初の部分。 (例: contoso )。 |
資格情報 | clientID | 手順 2.1 の Web API アプリケーション ID。 前の図では、これはアプリ ID: 2 のアプリケーションです。 |
資格情報 | 発行者 | (省略可能) トークン発行者の iss クレームの値。 既定では、次の形式で Azure AD B2C からトークンが返されます: https://<your-tenant-name>.b2clogin.com/<your-tenant-ID>/v2.0/ 。 <your-tenant-name> を、Azure AD B2C テナント名の最初の部分に置き換えます。 <your-tenant-ID> を、Azure AD B2C テナント ID に置き換えます。 |
policies | policyName | 手順 1 で作成したユーザー フローまたはカスタム ポリシー。 アプリケーションで複数のユーザー フローまたはカスタム ポリシーを使用する場合は、1 つのみ指定します。 たとえば、サインアップまたはサインイン ユーザー フローを使用します。 |
resource | scope | 手順 2.5 の Web API アプリケーション登録のスコープ。 |
最終的な構成ファイルは、次の JSON のようになります。
{
"credentials": {
"tenantName": "<your-tenant-namee>",
"clientID": "<your-webapi-application-ID>",
"issuer": "https://<your-tenant-name>.b2clogin.com/<your-tenant-ID>/v2.0/"
},
"policies": {
"policyName": "b2c_1_susi"
},
"resource": {
"scope": ["tasks.read"]
},
// More settings here
}
手順 5: Angular SPA と Web API を実行する
これで、Angular の API へのスコープ付きアクセスをテストする準備ができました。 このステップでは、ローカル コンピューターで Web API とサンプル Angular の両方のアプリケーションを実行します。 その後、Angular アプリケーションにサインインし、 [TodoList] ボタンを選択して、保護された API に対する要求を開始します。
Web API を実行する
コンソール ウィンドウを開き、Web API サンプルが含まれるディレクトリに移動します。 次に例を示します。
cd active-directory-b2c-javascript-nodejs-webapi
次のコマンドを実行します。
npm install && npm update node index.js
コンソール ウィンドウには、アプリケーションがホストされている場所のポート番号が表示されます。
Listening on port 5000...
Angular アプリケーションを実行する
別のコンソール ウィンドウを開き、Angular サンプルが含まれるディレクトリに移動します。 次に例を示します。
cd ms-identity-javascript-angular-tutorial-main/3-Authorization-II/2-call-api-b2c/SPA
次のコマンドを実行します。
npm install && npm update npm start
コンソール ウィンドウには、アプリケーションがホストされている場所のポート番号が表示されます。
Listening on port 4200...
アプリケーションを表示するには、ブラウザーで
http://localhost:4200
に移動します。[ログイン] を選択します。
サインインアップまたはサインイン プロセスを完了します。
サインインが成功すると、プロファイルが表示されます。 メニューの [TodoList] を選択します。
[追加] を選択して新しい項目を一覧に追加するか、アイコンを使用して項目を削除または編集します。
アプリケーションをデプロイする
運用アプリケーションでは、通常、アプリ登録のリダイレクト URI は、アプリが実行されているパブリックにアクセス可能なエンドポイント (https://contoso.com
など) です。
お使いの登録済みアプリケーションでは、いつでもリダイレクト URI を追加したり、変更したりすることができます。 リダイレクト URI には、次の制限があります。
- 応答 URL は、スキーム
https
で始まる必要があります。 - 応答 URL では大文字と小文字が区別されます。 大文字と小文字の区別は、実行中のアプリケーションの URL パスの場合と一致している必要があります。