Ponz Dev Log

ゆるくてマイペースな開発日記

IBM Cloud AppIDで独自の認証画面を使用する

IBM Cloudマネージドの認証サービス IBM Cloud AppID (以下AppID) には標準で認証画面が作られています。 OpenID Connectのプロトコルで認証を通すだけであれば標準画面で十分なのですが、時として独自の認証画面を使う場面が出てきます。

この記事では、WebアプリケーションとAppIDで認証する時に独自の認証画面を使う方法を記載します。

実装方法

この記事では以下の構成のWebアプリケーションを想定します。

実装方法は驚くほど簡単で、 SDKで提供された WebAppStrategy を実装したエンドポイントに対して、画面からPOSTメソッドでユーザー名とパスワードを投げつけるだけです。

以下のサンプルの通り、実は標準画面との違いはほとんどありません。 独自画面からPOSTでパラメータを投げるか、標準画面に遷移するか。たったこれだけです。

// 認証エンドポイントの定義 サンプル
// Passport.jsやAppIDのSDKの宣言は省略

// 独自画面のログイン処理
app.post(
    '/login/rop',
    bodyParser.urlencoded({ extended: false }),
    passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
        successRedirect: SUCCESS_PAGE_URL,
        failureRedirect: '/login.html',
        failureFlash : true, // 認証失敗時にフラッシュ・メッセージを送り返す
    }),
    (req, res) => {
        console.log('successfully logged in!');
        res.redirect('/success.html');
    });

// 標準画面のログイン処理
app.get('/login/standard', passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
    successRedirect: SUCCESS_PAGE_URL,
    forceLogin: true
}));

// 標準画面のログイン後のコールバック処理
app.get('/login/callback', passport.authenticate(WebAppStrategy.STRATEGY_NAME));
<!-- 独自実装のログイン画面 サンプル -->

<form action="/login/rop" method="post">
  <div>
    <label for="username-form">ユーザー名</label>
    <div>
      <input id="username-form" type="text" name="username" required />
    </div>
  </div>
  <div>
    <label for="password-form">パスワード</label>
    <div>
      <input id="password-form" type="password" name="password" required />
    </div>
  </div>
  <div>
    <button type="submit">ログイン</button>
  </div>
</form>

SDKが裏でやっていること

上記のソースコードでは、独自画面の両方をSDKで処理していましたが、SDKの中ではいったい何をしているのでしょうか。

SDKは独自画面からの認証処理では、OpenID ConnectのResource Owner Password Credential Grant Flowを実装・実行しています。 実態としては、AppIDのトークンエンドポイントを呼び出しているだけです。

トークンエンドポイントは仕様が公開されているので、SDKではなくてもサーバサイドで実装可能です。

参考