🛡️

ALB OIDCを扱う go-amzn-oidc - fujiwara-ware 2024 day 14

2024/12/14に公開

この記事は fujiwara-ware advent calendar 2024 の14日目です。

go-amzn-oidc とは

https://github.com/fujiwara/go-amzn-oidc

go-amzn-oidc は、AWS ALB (Application Load Balancer) が提供する OpenID Connect (OIDC) 認証を行った場合に、ALB からバックエンドに送られる認証情報を検証するためのライブラリです。

ALB で OIDC 認証を行うと、認証が通った後にバックエンドには x-amzn-oidc-data というヘッダに JWT が渡されます。この JWT が正当なものであるかを検証し、claims に含まれる情報を取り出すためのライブラリ/サーバーです。

なぜ作ったか

認証後に ALB が送ってくる JWT は、かつては通常の JWT とは似て非なるものでした。JWT は base64 の padding (末尾の =) を付けないのが仕様ですが、ALB なぜか = を付けて来ていました。これは通常の JWT ライブラリでは検証することができません。[1]:

また、署名検証に必要な公開鍵は ALB のエンドポイント https://public-keys.auth.elb.{region}.amazonaws.com/{jwtに入っているkeyid} へHTTPSでアクセスして取得する必要があります。

公開鍵取得を ALB のリクエスト(署名検証が必要なタイミング)ごとに都度やるのは非効率なため、適宜キャッシュする必要があります。そのあたりを考慮したライブラリ兼サーバーを作りました。

JWT のようなものを検証する

JWT のようで JWT ではない値に対して、世間の JWT ライブラリを普通に使うと検証が通りません。

しかしたまたま、golang-jwt/jwt/v4 には DecodePaddingAllowed=true というオプションがあり、これを有効にすると padding があっても検証が通るようになります。よかったですね。

ライブラリとして使う

go-amzn-oidc は Go のライブラリとして使えます。OIDC 認証後の JWT を検証し、claims を取り出すのは以下のように簡単です。

import "github.com/fujiwara/go-amzn-oidc/validator"

claims, err := validator.Validate(r.Header.Get("x-amzn-oidc-data"))
if err != nil {
    // 署名検証エラー
    http.Error(w, "Unauthorized", http.StatusUnauthorized)
    return
}
fmt.Fprintln(w, claims.Email())

サーバーとして使う

go-amzn-oidc は単体のサーバーとして起動することもできます。ALB からのリクエストを受け取り、署名検証を行い、claims を取り出して返すサーバーが立ち上がります。

nginx の auth_request と組み合わせて使うことで、署名検証と claims の取り出しを go-amzn-oidc に任せることができます。

ユーザーが作るアプリケーションは、そこから渡されたヘッダを信用してアクセス制御ができます。アプリケーションは ALB で行われる OIDC 認証のことを知らなくてもよいですし、Go で実装されている必要もありません。

# go-amzn-oidc で x-amzn-oidc-data を検証する
location = /oidc_validate {
  proxy_pass http://127.0.0.1:8080;
  proxy_set_header X-Amzn-OIDC-Data $http_x_amzn_oidc_data;
  proxy_set_header Content-Length "";
  proxy_pass_request_body off;
  internal;
}

location / {
  # go-amzn-oidc にリクエストを投げて検証させる
  auth_request /oidc_validate;

  # go-amzn-oidc が検証に成功したら、claims を取り出して X-Email ヘッダにセットする
  auth_request_set $email $upstream_http_x_auth_request_email;
  proxy_set_header X-Email $email;
  
  # 実際のアプリケーションの処理 (proxy_pass など)
}

まとめ

go-amzn-oidc は、ALB の OIDC 認証を行った場合に、ALB からバックエンドに送られる認証情報を検証するためのライブラリです。ライブラリとして使うこともできますし、サーバーとして使うこともできます。

便利なので、ぜひ使ってみてください。

それでは、明日もお楽しみに!

脚注
  1. 現在はまともな JWT になっているようですが、当時はそうではなかった ↩︎

Discussion