3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

アプリ(Node.js)の認証(OIDC)をALBにやってもらうやつ

Last updated at Posted at 2018-08-23

今さら感ありますがApplication Load Balancerでのユーザー認証機能を試してみました。
JWTの検証で意外にハマってしまったのでメモしておきます。

IdPの設定

今回はOneLoginを利用しました。

用意されている「OpenId Connect app」をCompany Appとして追加すれば終わりと高を括っていたところ、ALBがHTTP 561を返し続け大分ハマりました。

トークンエンドポイントへのリクエストを「Basic」ではなく「POST」に設定しないといけないのでした。1

ALBの設定

AWSのドキュメントとブログを頼りに設定できました。

個人的なポイントとしては以下。

  • ALBはHTTPSでアクセスされるように設定する
  • 認証アクションで入力を求められる各エンドポイントは/.well-known/openid-configurationから確認する2
  • リダイレクトURLにはhttps://<ALBのドメイン名>/oauth2/idpresponseを設定する

アプリケーション実装

上で挙げたブログ曰く、

しかしながら、対象リクエストが改ざんされていないことを担保する JWT ヘッダー上の署名を検証するためのアプリケーションを実装することは依然として重要です。

ということなので、Auth0のnode-jsonwebtokenを利用して検証を行うことにしました。が、ダメ。デコードすらできず。IDトークンがbase64urlエンコードされていないっぽい。

Base64エンコードした後、以下の変換を施したものがbase64urlエンコードらしい3のですがIDトークンに「=」が入ってしまっていました。削除するとデコードできるようになりましたがverifyは失敗します。

対象の文字 変換後
= 削除する
+ -
/ _

そこでjwt.ioにて他のライブラリがないか探しjsrsasignというライブラリを使わせてもらうことにしました。

これで検証とデコードが問題なくできるようになり、あとはAWSのドキュメントに載っているPythonで書かれたサンプルをJavaScriptに移植すれば、出来上がりっ

index.js
const express = require('express');
const fetch = require('node-fetch');
const rs = require('jsrsasign');

const app = express();

app.get('/activate', (req, res) => {
    // IDトークンを取得
    const token = req.header('x-amzn-oidc-data');

    // ヘッダーからkey idを取得
    const decodedJwt = rs.KJUR.jws.JWS.parse(token);
    const kid = decodedJwt.headerObj.kid;

    // 検証用の公開鍵を取得
    fetch(`https://public-keys.auth.elb.ap-northeast-1.amazonaws.com/${kid}`).then(response => {
        return response.text();
    }).then(pem => {
        // トークンを検証
        const pubKey = rs.KEYUTIL.getKey(pem);
        const isValid = rs.KJUR.jws.JWS.verify(token, pubKey, ["ES256"]);
        if (isValid) {
            res.send('valid');
        } else {
            res.status(400).send('invalid');
        }
    });
});

app.get('/', (req, res) => {
    res.send('arrived!');
});

app.listen(3000);
  1. https://dev.classmethod.jp/cloud/aws/onelogin-oidc-alb-auth/

  2. https://developers.onelogin.com/openid-connect/api/provider-config

  3. https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#appendix-C

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?