Go で OpenID Connect(OIDC)のログイン(Authorization Code Flow + PKCE)を実装する流れを整理します。ライブラリは golang.org/x/oauth2 と github.com/coreos/go-oidc の組み合わせが定番です。
全体の流れ
- Discovery:
/.well-known/openid-configurationからエンドポイントと JWKS を取得 - 認可リクエスト:
state・nonce・PKCE のcode_challengeを付けて IdP へリダイレクト - コールバック:
stateを検証し、codeを受け取る - トークン交換:
code+code_verifierをトークンエンドポイントへ送り、IDトークンを取得 - IDトークン検証:署名(JWKS)・
iss・aud・exp・nonceを検証 - ログインセッション確立
押さえるべきポイント
state(CSRF対策)
ランダム値を生成し、Cookie/セッションに保存。コールバックで一致を検証します。リダイレクト先 URL もここに紐づけると安全です。
nonce(リプレイ対策)
認可リクエストで生成した nonce を、IDトークンの nonce クレームと突き合わせます。
PKCE
code_verifier(ランダム)から code_challenge(S256ハッシュ)を作って認可リクエストに付与。コールバックで code_verifier をトークン交換に渡します。公開クライアントでも機密クライアントでも付けるのが現在の標準です。
IDトークン検証
go-oidc の Verifier を使い、JWKS による署名検証・aud(自分の client_id)・iss・exp を必ず検証します。手動検証の落とし穴は JWT検証の落とし穴 を参照。
実装スケッチ
provider, _ := oidc.NewProvider(ctx, issuerURL) // Discovery
oauth2cfg := oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
Endpoint: provider.Endpoint(),
RedirectURL: redirectURL,
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
}
verifier := provider.Verifier(&oidc.Config{ClientID: clientID})
// 認可リクエスト(state / nonce / PKCE を付与)
url := oauth2cfg.AuthCodeURL(state,
oidc.Nonce(nonce),
oauth2.S256ChallengeOption(codeVerifier),
)
// コールバック:code 交換 → IDトークン検証
tok, _ := oauth2cfg.Exchange(ctx, code, oauth2.VerifierOption(codeVerifier))
rawID := tok.Extra("id_token").(string)
idToken, _ := verifier.Verify(ctx, rawID) // 署名・aud・iss・exp を検証
まとめ
OIDC 実装の肝は「state / nonce / PKCE を省略しない」「IDトークンを必ず検証する」の2点です。仕組みの背景は OpenID Connect とは を、運用は 企業SSO完全ガイド を参照してください。