ALBから渡される認証情報をexpressで取得する

7475 ワード

環境

node 16.13.1
express 4.17.3

やりたいこと

ALBとcognitoを連携させて認証認可を実現するケースって多いと思います。
ALBの認証を通過したHTTPアクセスについて、expressで認証済みユーザ情報を引き出したいと思いました。
ex. ALB後段のAPIサーバにて、POSTリクエストを行っているユーザの名前とemailを取得し、DBに合わせて登録する

構成例

実現方法

import { Request } from "express";

const getUserInfo = (req: Request): { name: string; email: string } => {
  const oidcData = req.headers["x-amzn-oidc-data"];
  if (oidcData && typeof oidcData === "string") {
    // JWT形式の文字列からpayloadを取得
    const payload = oidcData.split(".")[1];
    // payloadをdecodeしてjson形式に変換
    const decoded = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
    return { name: decoded.name || "", email: decoded.email || "" };
  } else {
    return { name: "", email: "" };
  }
};

解説

図中の9において、ALBはいくつかヘッダ情報を付加します。

x-amzn-oidc-dataにユーザ情報がJWT形式で含まれています。
JWTはJSONを単にbase64エンコードしただけのものなので、ペイロード部分をデコードしてあげれば簡単にユーザ情報を取得できます。

# デコード後のペイロード例
{
  sub: '3344-abcd',
  email_verified: 'false',
  email: '[email protected]',
  username: 'user_name',
  exp: 1651818337,
  iss: 'https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_AAAAA'
}

JWTについて

さいごに

cognitoに限らずAzureADなどのIdPとALBを連携させた場合でも同様に行えるはずです。
ちなみに、x-amzn-oidc-accesstokenもJWT形式で記述されており、デコードすると色々出てきます。
必要に応じて、適切な方から情報を引っ張ってみて下さい

# デコード後のx-amzn-oidc-accesstokenペイロードの例
{
  sub: '3344-abcd',
  'cognito:groups': [ 'ap-northeast-1_AAAA_pool' ],
  iss: 'https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_AAAAA',
  version: 2,
  client_id: 'clientid',
  origin_jti: 'aaaa-bb',
  token_use: 'access',
  scope: 'openid',
  auth_time: 1651813462,
  exp: 1651820813,
  iat: 1651817213,
  jti: 'aaaa-bbbbb',
  username: 'user-name'
}

また、こちらを応用して「良いね機能」を実現するコンテナベースのバックエンドを作りました。
良かったらこちらも眺めてみて下さい。