メインコンテンツへスキップ
このドキュメントは SPA + API アーキテクチャシナリオ の一部で、Angular 2 で SPA を実装する方法を説明します。実装されているソリューションの詳細については、このシナリオを参照してください。 SPA の Angular 2 実装の完全なソースコードは、この GitHub リポジトリで確認できます。

ステップ 1. Configuration

アプリケーションには、いくつかの設定情報が必要です。残りの実装に進む前に、各種設定値を格納する AuthConfig インターフェースを作成してください。このインターフェースは auth0-variables.ts というファイルに配置します。

ステップ 2. ユーザーの認可を行う

認可サービスを作成する

ユーザー認証に必要なタスクを管理し、調整する最適な方法は、再利用可能なサービスを作成することです。サービスを用意しておけば、アプリケーション全体でそのメソッドを呼び出せるようになります。サービス内では、auth0.jsWebAuth オブジェクトのインスタンスを作成できます。
このサービスには、認証を処理するためのメソッドがいくつかあります。
  • login: auth0.js の authorize を呼び出して、 を開始します
  • handleAuthentication: URL ハッシュ内の認証結果を確認し、auth0.js の parseHash メソッドで処理します
  • setSession: ユーザーの 、およびアクセストークンの有効期限を設定します
  • logout: ブラウザストレージからユーザーのトークンを削除します isAuthenticated: アクセストークンの有効期限が切れていないかどうかを確認します

認証結果を処理する

ユーザーが Universal Login を通じて認証され、その後アプリケーションにリダイレクトされると、認証情報は URL のハッシュフラグメントに含まれます。AuthServicehandleAuthentication メソッドは、このハッシュを処理します。 ユーザーのリダイレクト後にアプリが最初に読み込まれたときに認証ハッシュフラグメントを処理できるよう、アプリのルートコンポーネントで handleAuthentication を呼び出します。

Callback コンポーネントを追加する

Universal Login を使用すると、ユーザーはアプリケーションから離れ、Auth0 でホストされるページに移動します。認証に成功すると、ユーザーはアプリケーションに戻され、そこでクライアント側のセッションが設定されます。 ユーザーの戻り先はアプリケーション内の任意の URL にできますが、認証成功後にユーザーを戻す共通の場所として、専用の callback ルートを作成することをおすすめします。callback ルートを 1 つにまとめることには、主に次の 2 つの利点があります。
  • 複数の callback URL (場合によっては不明な URL を含む) を許可リストに追加する必要がなくなります
  • アプリケーションがユーザーのクライアント側セッションを設定している間、ローディングインジケーターを表示する場所として使えます
CallbackComponent という名前のコンポーネントを作成し、ローディングインジケーターを追加します。
この例では、何らかのローディングスピナーが assets ディレクトリ内にあることを前提としています。動作例については、ダウンロード可能なサンプルを参照してください。 認証後、ユーザーはいったん短時間 /callback ルートに遷移し、そこでローディングインジケーターが表示されます。この間にクライアント側のセッションが設定され、その後 /home ルートにリダイレクトされます。

ステップ 3. ユーザープロファイルを取得する

トークンから情報を取り出す

このセクションでは、アクセストークンと/userinfo エンドポイントを使用してユーザー情報を取得する方法を説明します。別の方法として、ライブラリを使用してIDトークンをデコードすることもできます (先に必ず検証してください) 。結果は同じです。追加のユーザー情報が必要な場合は、Management APIの使用を検討してください。
ユーザーのユーザープロファイルを取得するには、既存のAuthServiceクラスを更新します。getProfile関数を追加します。この関数では、ローカルストレージからユーザーのアクセストークンを取り出し、それをuserInfo関数に渡してユーザー情報を取得します。
これで、ユーザー情報を取得して表示したい任意のサービスから、この関数を簡単に呼び出せます。 たとえば、ユーザーのユーザープロファイル情報を表示するための新しいコンポーネントを作成できます。
このコンポーネントのテンプレートは次のとおりです。

ステップ 4. スコープに応じて UI 要素を条件付きで表示する

認可プロセス中に、ユーザーに付与された実際のスコープはすでにローカルストレージに保存されています。authResult で返された scope が空でない場合は、ユーザーに最初に要求したものとは異なるスコープのセットが発行されたことを意味します。そのため、ユーザーに付与されたスコープの判定には authResult.scope を使用する必要があります。 authResult で返された scope が空の場合は、要求したすべてのスコープがユーザーに付与されたことを意味します。そのため、ユーザーに付与されたスコープの判定には、要求したスコープを使用できます。 以下は、その確認を行うために先ほど作成した setSession 関数のコードです。
次に、ユーザーに特定のスコープが付与されているかどうかを判定するために呼び出せる関数を AuthService クラスに追加します。
このメソッドを呼び出すと、特定の UI 要素を表示するべきかどうかを判定できます。たとえば、ユーザーが approve:timesheets スコープを持っている場合にのみ、勤務表を承認 リンクを表示したいとします。以下のコードでは、そのリンクを表示するべきかどうかを判定するために、userHasScopes 関数の呼び出しを追加している点に注目してください。

ルートを保護する

ユーザーに適切なスコープが付与されていない場合にそのルートへ遷移できないよう、ルートも保護します。そのために、新しく ScopeGuardService サービスクラスを追加できます。
次に、ルートを設定する際にそれを使って、そのルートを有効化できるかどうかを判断します。以下の approval ルートの定義で、新しい ScopeGuardService が使われている点に注目してください。

ステップ 5. API を呼び出す

angular2-jwt モジュールを使用すると、API へのリクエストに を自動的に付与できます。これは、Angular の Http クラスをラップする AuthHttp クラスによって実現されます。 angular2-jwt をインストールします:
angular2-jwt 用の設定値を含むファクトリー関数を作成し、アプリケーションの @NgModuleproviders 配列に追加します。このファクトリー関数には、ローカルストレージから access_token を取得する tokenGetter 関数を含める必要があります。
angular2-jwt を設定すると、AuthHttp クラスを使用して、アプリケーション内のどこからでも API に安全にアクセスできます。そのためには、必要なコンポーネントまたはサービスに AuthHttp を注入し、Angular’s 通常の Http クラスと同じように使用します。

手順 6. アクセストークンを更新する

ユーザーのアクセストークンを更新するには、Angular SPA 側を更新する必要があります。AuthService に、auth0.js の checkSession メソッドを呼び出すメソッドを追加します。更新に成功したら、既存の setSession メソッドを使用して、新しいトークンをローカルストレージに保存します。
AuthService クラスに、認証をサイレントに更新するタイミングを設定する scheduleRenewal というメソッドを追加します。以下のサンプルでは、実際にトークンの有効期限が切れる 30 秒前に実行されるよう設定しています。また、Observable の購読を解除する unscheduleRenewal というメソッドも追加します。
最後に、スケジュールされた更新を開始する必要があります。これには、ページの読み込み時に実行される AppComponent 内で scheduleRenewal を呼び出します。これは、ユーザーが明示的にログインした場合でも、サイレント認証が行われた場合でも、各認証フローのたびに実行されます。

リフレッシュトークンのローテーション

近年のブラウザーにおけるユーザープライバシー制御の強化により、サードパーティ Cookie へアクセスできなくなり、ユーザーエクスペリエンスに悪影響が生じています。Auth0 では、Refresh Token Rotation の使用を推奨しています。これにより、SPA でリフレッシュトークンを安全に使用できるほか、ITP のようなブラウザーのプライバシー技術による UX の中断を避けつつ、エンドユーザーはリソースにシームレスにアクセスできます。