Ponz Dev Log

ソース派のシステムエンジニアの開発日記

IBM Cloud AppIDを使ってSPAに認証を組み込む

About

IBM Cloud アドベントカレンダー2019 1日目です!

qiita.com

このアドベントカレンダーのトップバッターということで、アプリ作成で最初に手をつける認証・認可にフォーカスしてSPA with AppIDを取りあげます。

今年の11月末にSPAでAppIDの認証を簡単に組み込めるようになったというアナウンスがありました。(以下記事参照)

www.ibm.com

上記のアナウンスは3行だけの簡素すぎる説明ですし、リンク先のドキュメントも英語のみであまり充実しているとは言えません。 このアドベントカレンダー記事は、SPAにAppIDを使った認証の組み込み実装例を提示します。

雰囲気だけ掴みたい人向けに、サンプルアプリを作りました↓

ログインするとQiitaの最新投稿表示するだけのやつです。 - サンプルアプリ (ユーザーは誰も登録していないので、投稿表示はできませんが...)

イメージとして以下のようなログインボタン、プロフィール表示ボタンを実装してみます。

f:id:accelerk:20191201163521p:plain
ログインボタンとプロフィールボタンを実装

この記事で説明しないこと

  • OpenID Connect / OAuth2.0の説明 ... 別資料をご参照ください。個人的にはAuth屋さんのOAuth/OIDCシリーズがオススメです。
  • ソースコードのAppID以外の実装・解説 ... AppIDに関係のある箇所しか解説しません。Angular CLIの説明は リファレンスをご参照ください。

何ができるようになったのか?

実装...の前に「え、今までSPAにAppIDの認証を組み込めなかったの?」と疑問に思われる方向けに補足します。

これまでもSPAにAppIDの認証を組み込むことはできていました。しかし、SPA "だけ" ではできなかったのです。 具体的には静的コンテンツを配信するバックエンドのWebアプリ(Node.jsで言えばExpressとか)を立ててバックエンド側にサーバーSDKを組み込むことで機能的に実現していました。

今回のアナウンスでは、新しく JavaScript Client SDK が登場しています。 このSDKにより バックエンドアプリ不要でSPA単体に AppIDの認証を組み込めるようになりました!!

SPAを動かす環境にバックエンドが必須ではなくなったため、SPAを開発するチームは静的Webサイトホスティングも使えるようになります。 (上記のサンプルアプリもNetlifyで動かしています)

実装例

ここからがこの記事の本題です。SPAのフレームワークとしてAngularを使って認証の組み込みを進めます。 事前にIBM Cloudのアカウント(FreeアカウントでOK)とAppIDインスタンスを作成しておいてください。

AppIDにアプリケーションを登録

SPAからAppIDに接続するために必要な資格情報を払い出します。

IBM CloudのAppID管理画面からアプリケーションタブを選択して「アプリケーションを追加」から登録しましょう。

AppID

f:id:accelerk:20191201164818p:plain
AppIDにアプリケーションを登録して資格情報を払い出す

タイプは必ず「単一ページ・アプリケーション(英語表示だとsinglepage application)」を選択してください。保存ボタンを押せば資格情報を取り出せます。

f:id:accelerk:20191201165106p:plain
AppIDにアプリケーションを追加

AppID Client SDKを利用してSPAを実装 (Service編)

まずはSDKをインストールしましょう。ドキュメント通りNPMでインストールします。

npm install ibmcloud-appid-js

次にAppIDとやり取りする部品を実装します。 認証のような他のコンポーネントでも共通で利用できる機能は、AngularのServiceとして切り出すと取り回しやすいです。さっそくAppID Client SDKを使ったAuthServiceを作成しましょう。

実装例は認証・認可のSaaSであるAuth0SDK実装サンプルを参考にしています。

IBM Cloud AppID service in Angular

appId.signin() でサインイン用のモーダル表示、 appId.getUserInfo(accessToken) でAppIDで管理しているユーザープロフィールを取得します。 認証周りの実装はたったこれだけ!!

AppID Client SDKを利用してSPAを実装 (表示コンポーネント編)

続いてAuthServiceを使って認証画面の表示と認証ステータスの状態を取得してみましょう。

Using IBM Cloud AppID in Angular Components

HTMLのクリックイベントに onLoginPressed 関数を設定し、TypeScriptのコンポーネントにAppIDのサインインを呼び出す同名の関数を実装しています。 また、ログイン済みのみ isAuthenticated に値が入るので表示の制御ができます。

AppIDにWebリダイレクトURLを設定する。

1つ前のステップまで完了した状態だと、ログインボタンを押してもモーダルに redirect_uri が不正というメッセージが表示されます。 これはリクエストパラメータ redirect_uri と同じ値がAppIDに設定されていないからです。

f:id:accelerk:20191202092942p:plain
redirect_uriが未登録の場合

ここからがハマりポイントです。メッセージと一緒に書かれているドキュメントを辿ると {アプリURL}/appid_callback を指定すれば良さそうに見えますが、2019/12/01現在はその限りではありません。 正解はモーダルのURLに埋め込まれた値を使います。 URLをエディタにコピペして、 redirect_uri クエリパラメータの値をAppIDにセットしてあげましょう。

f:id:accelerk:20191201181559p:plain
リダイレクトURIの追加

完成です🎉

これでAppIDの認証を組み込んだSPAの完成です。動かしてみましょう!

"Login with AppID" ボタンを押してモーダルにEmail / Password入力画面が表示されたらOKです。 モーダルに表示される画像やヘッダーの色はお好きなものをAppID管理画面から設定できます。

f:id:accelerk:20191201163257p:plain
AppID認証画面モーダル

総括

ドキュメントは少ないですが、実装は数時間でできてしまいました。モーダル部品も用意されているので上記のように数十行あれば組み込めるのは簡単ですね。(Client SDK様様だ)

SPAでAppIDを利用したい方の参考になれば幸いです。

Appendix

参考資料

※ リンク切れの場合は、クエリパラメータに locale=en をつけると通る場合があります。

JavaScript Client SDKの正体は?

JavaScript Client SDKの中身は、OAuth2.0のAuthorization Code Grant + PKCE のフローをAppIDのREST APIを叩いて実現しているライブラリです。

SDKなのでOIDC/OAuth2.0の仕組みを知らずとも容易に実装できますが、興味のある方はどのようなAPIを叩いているのかAppendixのSwagger定義を参照ください。

また、AppIDではSPAの認証認可方法としてWeb検索でよく出てくるOIDC/OAuth2.0のImplicit Grant Flowは 使えません 。 公式のドキュメントでも触れられていますが、Implicit Grant Flowには既知の脆弱性が指摘されています。 Swaggerの認可エンドポイント GET /oauth/v4/{tenantId}/authorization にも フローの種別を表すリクエストパラメータ response_typetoken (Implicit Grant Flow)が含まれないので意図的に塞いでいるものと筆者は推測しています。


以上。2日目以降のアドベントカレンダー楽しみ :)