idproxy

package module
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: MIT Imports: 28 Imported by: 0

README

English | 日本語

idproxy

OIDC authentication reverse proxy + MCP OAuth 2.1 Authorization Server.

idproxy sits in front of any HTTP backend and transparently provides OIDC browser authentication and OAuth 2.1 Bearer Token validation. It also acts as an OAuth 2.1 Authorization Server to protect MCP (Model Context Protocol) servers, with support for Dynamic Client Registration (RFC 7591).

Features

  • OIDC-based browser authentication (Google, Microsoft Entra ID, etc.)
  • OAuth 2.1 Authorization Server (PKCE required, Bearer Token issuance, refresh_token rotation)
  • Dynamic Client Registration (RFC 7591)
  • SSE (Server-Sent Events) transparent proxy
  • Optimized for protecting MCP servers
  • Zero-dependency in-memory session store (replaceable for production)

Installation

Go
go install github.com/youyo/idproxy/cmd/idproxy@latest
Docker
docker pull ghcr.io/youyo/idproxy:latest

Quick Start

Configure and run
export UPSTREAM_URL=http://localhost:3000
export EXTERNAL_URL=https://mcp-auth.example.com
export COOKIE_SECRET=$(openssl rand -hex 32)
export OIDC_ISSUER=https://accounts.google.com
export OIDC_CLIENT_ID=your-client-id
export OIDC_CLIENT_SECRET=your-client-secret

idproxy
Docker Compose
version: "3.8"
services:
  idproxy:
    image: ghcr.io/youyo/idproxy:latest
    ports:
      - "8080:8080"
    environment:
      UPSTREAM_URL: http://backend:3000
      EXTERNAL_URL: https://mcp-auth.example.com
      COOKIE_SECRET: "${COOKIE_SECRET}"
      OIDC_ISSUER: https://accounts.google.com
      OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}"
      OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}"
    depends_on:
      - backend

  backend:
    image: your-backend:latest
    expose:
      - "3000"

Environment Variables

Required
Variable Description Example
UPSTREAM_URL Backend URL to proxy to http://localhost:3000
EXTERNAL_URL External URL of this service https://mcp-auth.example.com
COOKIE_SECRET Cookie encryption key (hex-encoded, 32+ bytes) Generate with openssl rand -hex 32
OIDC_ISSUER OIDC Issuer URL (comma-separated for multiple) https://accounts.google.com
OIDC_CLIENT_ID OAuth Client ID (comma-separated for multiple) your-client-id
Optional
Variable Description Default
OIDC_CLIENT_SECRET OAuth Client Secret (comma-separated for multiple) none
OIDC_PROVIDER_NAME Provider display name (comma-separated for multiple) Auto-generated from Issuer
ALLOWED_DOMAINS Allowed email domains (comma-separated) no restriction
ALLOWED_EMAILS Allowed email addresses (comma-separated) no restriction
PATH_PREFIX OAuth 2.1 AS endpoint path prefix none
PORT Listen port 8080

Provider Setup

Provider OIDC_ISSUER
Microsoft Entra ID https://login.microsoftonline.com/{tenant-id}/v2.0
Google https://accounts.google.com
Amazon Cognito https://cognito-idp.{region}.amazonaws.com/{user-pool-id}

When registering idproxy as a client in your OIDC provider, set the redirect URI to:

{EXTERNAL_URL}/callback

Instead of configuring Entra ID manually through the Azure Portal, you can use the built-in setup command:

Prerequisites

  • Azure CLI installed (brew install azure-cli on macOS)
  • Logged in to Azure CLI:
az login
# If running in a headless environment (no browser):
az login --use-device-code

Run the setup command

idproxy setup entra-id \
  --instance-name my-idproxy \
  --external-url https://proxy.example.com

The command will:

  1. Create (or reuse) an Entra ID app registration named idproxy-{instance-name}
  2. Generate a client secret
  3. Register {external-url}/callback as a redirect URI
  4. Print the environment variables to set

If PATH_PREFIX is configured, pass --path-prefix /auth to generate the correct callback URL.

To use a custom app name prefix (instead of idproxy-), add --name-prefix "my-company-".

Non-interactive mode (for CI/CD):

idproxy setup entra-id \
  --instance-name my-idproxy \
  --external-url https://proxy.example.com \
  --non-interactive

The manual steps below describe the equivalent portal workflow if you prefer to configure Entra ID by hand.

Microsoft Entra ID
1. Register an application

Azure PortalMicrosoft Entra IDApp registrationsNew registration

  • Supported account types: Accounts in this organizational directory only
  • Redirect URI: set after your deployment URL is known (see below)

From the Overview page, collect:

  • Application (client) IDOIDC_CLIENT_ID
  • Directory (tenant) ID → use in OIDC_ISSUER: https://login.microsoftonline.com/{tenant-id}/v2.0
2. Create a client secret

Certificates & secretsClient secretsNew client secret → copy the Value immediately.

This is OIDC_CLIENT_SECRET.

3. Add API permissions

API permissionsAdd a permissionMicrosoft GraphDelegated permissions → add:

  • openid
  • email
  • profile

Then click Grant admin consent to avoid per-user consent prompts.

4. Add optional claims to the ID token

Token configurationAdd optional claimToken type: ID → check emailAdd.

name (display name) is included automatically with the profile scope. family_name and given_name are not required.

5. Set the redirect URI

AuthenticationAdd a platformWeb → set:

{EXTERNAL_URL}/callback

If PATH_PREFIX is set (e.g. PATH_PREFIX=/auth), append the prefix: {EXTERNAL_URL}/auth/callback.

Amazon Cognito

Request scopes openid email profile on the App Client. Cognito ID tokens may omit the name claim depending on user pool configuration; idproxy automatically falls back to cognito:username (and then preferred_username) for the user's display name.

Library Usage

idproxy can also be used as a Go library.

Basic Reverse Proxy
package main

import (
	"context"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"

	idproxy "github.com/youyo/idproxy"
	"github.com/youyo/idproxy/store"
)

func main() {
	cfg := idproxy.Config{
		Providers: []idproxy.OIDCProvider{
			{
				Issuer:       "https://accounts.google.com",
				ClientID:     "your-client-id",
				ClientSecret: "your-client-secret",
			},
		},
		ExternalURL:  "https://mcp-auth.example.com",
		CookieSecret: []byte("32-byte-secret-key-here-1234567"),
		Store:        store.NewMemoryStore(),
	}

	auth, err := idproxy.New(context.Background(), cfg)
	if err != nil {
		log.Fatal(err)
	}

	upstream, _ := url.Parse("http://localhost:3000")
	proxy := httputil.NewSingleHostReverseProxy(upstream)

	http.Handle("/", auth.Wrap(proxy))
	log.Fatal(http.ListenAndServe(":8080", nil))
}
Post-Login Redirect Behavior

After authentication, idproxy redirects users back to the URL they originally requested. The destination is chosen in this order:

  1. The redirect_to query parameter passed to /login, if supplied.
  2. Config.DefaultPostLoginPath, if set (e.g. "/dashboard").
  3. "/" (legacy default).

If your application doesn't mount a handler at "/", set DefaultPostLoginPath to point at a real route, or use the OnAuthenticated hook (below). Without one of these, a fresh login lands on a 404. (See kintone#5 for the bug this section prevents.)

Config.OnAuthenticated hook

OnAuthenticated runs once, right after the session cookie is issued. Return values control the next step:

handled redirectTo Behavior
true "" Hook already wrote the response; idproxy does nothing.
true non-empty redirectTo is ignored (hook is considered authoritative).
false non-empty idproxy validates redirectTo and redirects (302).
false "" Fallback to the original redirect_to or DefaultPostLoginPath.
cfg := idproxy.Config{
    // ...
    DefaultPostLoginPath: "/dashboard",
    OnAuthenticated: func(w http.ResponseWriter, r *http.Request, user *idproxy.User) (string, bool) {
        log.Printf("user %q logged in", user.Email)
        return "", false // use the default redirect chain
    },
}

Panic inside the hook is recovered and surfaces as 500. If you return handled=false but already wrote to the ResponseWriter, idproxy logs a warning and skips its own redirect.

Securing redirect_to with StrictPostLoginRedirectValidator

By default idproxy accepts any redirect_to value (legacy behavior). To turn on the strict open-redirect validator, opt in:

cfg.UseStrictPostLoginRedirectValidator()

This rejects javascript:, data:, protocol-relative (//evil), non-NFKC, backslash, and control-character inputs. Allowed:

  • Relative paths starting with / (but not //).
  • HTTPS URLs whose host equals Config.ExternalURL's host (same-origin absolute redirect).

The validator runs at every redirect entry point: LoginHandler, SelectionHandler, Auth.Wrap's unauthenticated browser path, OAuthServer.redirectToLogin, and the redirectTo returned by the OnAuthenticated hook. Rejections produce 400 (for user input) or 500 (for hook output).

Cascade OAuth pattern

The OnAuthenticated hook is how idproxy applications layer a second OAuth flow (Slack / Backlog / kintone) on top of OIDC login. See examples/cascade-oauth for a minimal walkthrough and docs/cascade-oauth-pattern.md for state management, token persistence, and failure-mode discussion.

Migration: from middleware pattern to OnAuthenticated

Many apps historically wrap their own middleware around Auth.Wrap to enforce cascade OAuth on every request. The hook lets you do the same in one place, at the right time:

// Before — runs on every request, easy to miss adding around new mounts.
http.ListenAndServe(":8080", MyOAuthMiddleware(tokenStore, auth.Wrap(mux)))

// After — runs once, right after login, registered with Config.
cfg.OnAuthenticated = func(w http.ResponseWriter, r *http.Request, user *idproxy.User) (string, bool) {
    if !tokenStore.HasToken(user.Email) {
        return "/oauth/external/start?return_to=" + r.URL.Query().Get("redirect_to"), false
    }
    return "", false
}
http.ListenAndServe(":8080", auth.Wrap(mux))

Real-world adoption: logvalet — Backlog MCP server.

MCP Server Protection (OAuth 2.1 AS)

Setting Config.OAuth enables automatic OAuthServer initialization in Auth.New().

package main

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"

	idproxy "github.com/youyo/idproxy"
	"github.com/youyo/idproxy/store"
)

func main() {
	// Generate ECDSA P-256 key for JWT signing
	// Use a persisted key in production
	signingKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

	cfg := idproxy.Config{
		Providers: []idproxy.OIDCProvider{
			{
				Issuer:       "https://accounts.google.com",
				ClientID:     "your-client-id",
				ClientSecret: "your-client-secret",
			},
		},
		ExternalURL:     "https://mcp-auth.example.com",
		CookieSecret:    []byte("32-byte-secret-key-here-1234567"),
		Store:           store.NewMemoryStore(),
		AccessTokenTTL:  time.Hour,
		RefreshTokenTTL: 30 * 24 * time.Hour, // 30 days
		OAuth: &idproxy.OAuthConfig{
			SigningKey: signingKey,
		},
	}

	// OAuthServer is automatically initialized when Config.OAuth is set
	auth, err := idproxy.New(context.Background(), cfg)
	if err != nil {
		log.Fatal(err)
	}

	upstream, _ := url.Parse("http://localhost:3000")
	proxy := httputil.NewSingleHostReverseProxy(upstream)

	http.Handle("/", auth.Wrap(proxy))
	log.Fatal(http.ListenAndServe(":8080", nil))
}

Refresh Token Rotation Design

idproxy implements OAuth 2.1 §4.3.2 refresh_token rotation with the following design:

  • When a refresh_token is consumed, the old record is marked as used=true instead of being deleted.
  • A new refresh_token is issued and linked to the same family_id.
  • If an already-used refresh_token is presented again (replay), the entire family is revoked via a familyrevoked:<family_id> tombstone.
Why keep the old record instead of deleting it?

OAuth 2.1 §4.3.2 requires the AS to "invalidate" the old refresh_token, not literally "delete" it. Keeping the record with used=true:

  • Lets ConsumeRefreshToken reject reuse (satisfying the spec).
  • Retains the family_id so replay detection can revoke the whole family.
  • Expires automatically via TTL (30 days by default).
Observability

Two structured log events cover the rotation lifecycle:

Event Level When
oauth refresh rotation Info Successful rotation (new token issued)
oauth refresh replay detected Warn Reused token detected (family revoked)

Both include family_id, client_id, and scope — never the refresh_token string itself.

Observing rotation in production (DynamoDB)

When inspecting refreshtoken:* records, include the used attribute to distinguish live vs. already-rotated tokens:

aws dynamodb scan \
  --table-name my-idproxy-table \
  --filter-expression 'begins_with(pk, :prefix)' \
  --expression-attribute-values '{":prefix":{"S":"refreshtoken:"}}' \
  --projection-expression 'pk, #u, #t' \
  --expression-attribute-names '{"#u":"used","#t":"ttl"}'

used=true indicates the token has been rotated; it will be deleted by TTL.

Store Backends

idproxy persists sessions, authorization codes, access/refresh tokens and dynamically registered clients via the Store interface. Several implementations are bundled:

Backend Package Use case TTL strategy CAS for refresh rotation
Memory store (NewMemoryStore) Single-instance / dev / tests In-process timer + Cleanup goroutine Mutex
DynamoDB store (NewDynamoDBStore) AWS multi-container (Lambda) DynamoDB TTL ConditionExpression
SQLite store/sqlite (sqlite.New) Single-node file-based persistence (CGO-free) Per-row expires_at + 5-min Cleanup goroutine BEGIN IMMEDIATE + used=0 CAS
Redis store/redis (redis.New) General-purpose distributed KV Native EX Embedded Lua script (consume.lua)

When using the idproxy standalone binary, select a backend via the STORE_BACKEND environment variable. See the binary's --help or the cmd/idproxy sources for required env vars per backend.

Client / DB ownership (cheat sheet)

When you inject your own client / db into a Store via *WithClient / *WithDB, ownership at Close() differs:

Backend Default How to opt out
DynamoDB never closes the injected client (AWS SDK v2 convention) n/a
Redis closes (client.Close()) redisstore.NewWithClient(client, prefix, redisstore.WithClientOwnership(false))
SQLite closes (db.Close()) not yet exposed; NewWithDB is on the roadmap

This means it is always safe to share a single *dynamodb.Client between idproxy and your application code. For Redis, opt out of ownership if you want to keep using the client after idproxy is shut down. Full discussion in docs/store-coexistence.md.

Selecting from the binary
# SQLite
STORE_BACKEND=sqlite SQLITE_PATH=/var/lib/idproxy/state.db idproxy

# Redis
STORE_BACKEND=redis REDIS_ADDR=redis.internal:6379 idproxy

# DynamoDB
STORE_BACKEND=dynamodb DYNAMODB_TABLE_NAME=my-idproxy-table AWS_REGION=ap-northeast-1 idproxy

DynamoDB Store

For multi-instance deployments (e.g., AWS Lambda with multiple concurrent containers), use DynamoDBStore to share state across instances.

Usage
import "github.com/youyo/idproxy/store"

s, err := store.NewDynamoDBStore("my-idproxy-table", "ap-northeast-1")
if err != nil {
    log.Fatal(err)
}
defer s.Close()

cfg := idproxy.Config{
    Store: s,
    // ...
}
Create DynamoDB Table
aws dynamodb create-table \
  --table-name my-idproxy-table \
  --attribute-definitions AttributeName=pk,AttributeType=S \
  --key-schema AttributeName=pk,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region ap-northeast-1

# Enable TTL on the "ttl" attribute
aws dynamodb update-time-to-live \
  --table-name my-idproxy-table \
  --time-to-live-specification "Enabled=true,AttributeName=ttl" \
  --region ap-northeast-1
IAM Permissions (Minimum)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:DeleteItem"
      ],
      "Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/my-idproxy-table"
    }
  ]
}

Security: The data attribute contains sensitive information (session data, access tokens). Enable DynamoDB server-side encryption with AWS KMS (SSE-KMS) for production use.

Coexistence with user-owned tables / GSIs

idproxy is designed to share a DynamoDB table with your application data. Reserved PK prefixes (lowercase): session:, authcode:, accesstoken:, client:, refreshtoken:, familyrevoked:. idproxy never queries a GSI, so you can add your own freely. See examples/dynamodb-coexist for a runnable example and docs/store-coexistence.md for the full guide (TTL sharing, hot partitions, attribute-name conflicts).

Note: Cleanup() is a no-op — expired items are removed automatically by DynamoDB TTL. DynamoDB TTL may have up to 48 hours of lag; DynamoDBStore compensates by checking the ttl attribute on every Get and returning nil for expired items.

License

MIT License

Documentation

Overview

Package idproxy provides OIDC authentication middleware and MCP OAuth 2.1 Authorization Server functionality as a single Go library.

idproxy can be used as:

  • An http.Handler middleware via Auth.Wrap() for any Go HTTP server
  • A standalone reverse proxy binary (cmd/idproxy) for non-Go upstream servers

Features

  • Multiple OIDC provider support (EntraID, Google, Amazon Cognito, etc.)
  • MCP OAuth 2.1 Authorization Server with PKCE (S256 only)
  • SSE / Streamable HTTP transparent passthrough
  • Cookie-based session management with encrypted JWT (gorilla/securecookie)
  • Pluggable Store interface for session/token persistence (memory / DynamoDB / Redis / SQLite implementations)
  • Dynamic Client Registration (RFC 7591)
  • OAuth 2.1 refresh_token rotation with family revocation

Authentication flow (browser session)

  1. Client request hits Auth.Wrap().
  2. If the request matches a BrowserAuth path (/login, /callback, /select), the corresponding handler is invoked.
  3. If the request has an Authorization: Bearer <jwt> header, the JWT is validated against the configured signing key and the user is injected into the request context.
  4. If the request has a session cookie, the cookie is decrypted and the session is fetched from Store; on success the user is injected.
  5. Otherwise: browser requests (Accept: text/html) are redirected to /login, API requests get 401 Unauthorized.

Post-login redirect behavior (v0.5.0+)

After authentication completes, BrowserAuth redirects the user back to:

  • The redirect_to query parameter passed to /login, if supplied.
  • Otherwise Config.DefaultPostLoginPath, if non-empty.
  • Otherwise "/" (legacy default).

Embedding applications that previously relied on the default "/" should either keep a handler mounted at "/", or set DefaultPostLoginPath. To run arbitrary post-authentication logic (e.g. cascade OAuth, account provisioning, audit logging), use the Config.OnAuthenticated hook. The hook is called once, right after the session cookie is issued.

See the README and examples/cascade-oauth for details.

Open redirect protection (opt-in, v0.5.0+)

idproxy accepts arbitrary redirect_to values by default (legacy behavior). To prevent open-redirect attacks, opt in with (*Config).UseStrictPostLoginRedirectValidator() or by setting Config.PostLoginRedirectValidator manually.

The strict validator allows only:

  • Relative paths starting with "/" (but not "//")
  • Absolute HTTPS URLs whose host equals Config.ExternalURL's host

All other inputs (javascript:, data:, protocol-relative, backslashes, non-NFKC characters, control / format characters) are rejected with 400.

Store backend selection

Pick the Store implementation based on deployment topology:

  • store.NewMemoryStore() — single instance, no persistence
  • store.NewDynamoDBStore(...) — Lambda / multi-instance / multi-AZ
  • redis (store/redis package) — distributed cache, low-latency sessions
  • sqlite (store/sqlite package)— single node with disk persistence

All implementations share the same Store interface. Refresh-token rotation is implemented with backend-specific atomicity primitives (Lua script for Redis, transaction CAS for SQLite, conditional update for DynamoDB).

Client ownership in Store implementations

When you pass an externally-constructed client / db to a Store, ownership of that resource determines what happens at Close():

  • DynamoDB: never closes the injected client (AWS SDK v2 convention).
  • Redis: closes the injected client by default; opt out with redisstore.WithClientOwnership(false).
  • SQLite: closes the injected db by default (NewWithDB is not yet exposed in v0.5.0; see roadmap).

See docs/store-coexistence.md for the full coexistence guide.

Index

Constants

This section is empty.

Variables

View Source
var DefaultConfig = Config{
	SessionMaxAge:   24 * time.Hour,
	AccessTokenTTL:  1 * time.Hour,
	RefreshTokenTTL: 30 * 24 * time.Hour,
	AuthCodeTTL:     10 * time.Minute,
	PathPrefix:      "",
}

DefaultConfig は Config のデフォルト値を保持する。

View Source
var DefaultScopes = []string{"openid", "email", "profile", "offline_access"}

DefaultScopes は OIDCProvider のデフォルトスコープ。 offline_access を含むことで IdP が refresh_token を返すようになる(IdP refresh_token 保存に必要)。

View Source
var ErrRefreshTokenAlreadyConsumed = errors.New("refresh token already consumed")

ErrRefreshTokenAlreadyConsumed はリフレッシュトークンが既に消費済みの場合に返されるエラー。 replay 検知時は data と共に返される(familyID の取得に使用)。

View Source
var ErrUnsafePostLoginRedirect = errors.New("idproxy: unsafe post-login redirect")

ErrUnsafePostLoginRedirect は PostLoginRedirectValidator がリダイレクト先を 拒否した時に返される sentinel エラー。利用側で errors.Is で判定できる。

Functions

func S256Challenge

func S256Challenge(verifier string) string

S256Challenge は RFC 7636 S256 メソッドでコードチャレンジを生成する。 code_verifier を SHA-256 ハッシュし、base64url(パディングなし)でエンコードして返す。

OAuth 2.1 では S256 のみが必須であり、plain メソッドは禁止されている。

func StrictPostLoginRedirectValidator added in v0.5.0

func StrictPostLoginRedirectValidator(externalURL string) func(string) error

StrictPostLoginRedirectValidator は post-login redirect 先を厳格に検査する `func(string) error` を返す。利用側が opt-in で安全側に切り替えるための helper。

externalURL は Config.ExternalURL と同一の値を渡す(同一 origin の絶対 URL 許可判定に使用する)。空文字列を渡した場合は「相対パスのみ許可」モードになる。

許可条件(多段検査、順番に評価する):

  1. `strings.TrimSpace` 後の入力に `unicode.IsControl` を含むなら reject
  2. backslash や HTML 構造文字 `\<>"'` を含むなら reject
  3. NFKC 正規化後と元の入力で差分があるなら reject(同形異字攻撃排除)
  4. `url.Parse` で scheme/host を取得し、以下のいずれかに合致するなら通過: - 相対パス: scheme="" かつ host="" かつ "/" で始まり "//" で始まらない - 同一 origin の絶対 URL: scheme="https" かつ host==externalURL の host
  5. それ以外は reject(`javascript:`/`data:`/`vbscript:`/`file:`/protocol-relative も拒否)

拒否時は `ErrUnsafePostLoginRedirect` を wrap した error を返す。

func VerifyS256

func VerifyS256(verifier, challenge string) bool

VerifyS256 は RFC 7636 S256 メソッドでコードチャレンジを検証する。 SHA256(verifier) の base64url が challenge と一致する場合に true を返す。 verifier または challenge が空文字列の場合は false を返す。

タイミングサイドチャネル攻撃を防ぐため、crypto/subtle.ConstantTimeCompare で比較する。

Types

type AccessTokenData

type AccessTokenData struct {
	// JTI は JWT の一意識別子。
	JTI string

	// Subject はユーザーの OIDC sub クレーム。
	Subject string

	// Email はユーザーのメールアドレス。
	Email string

	// ClientID はトークンを発行した OAuth クライアントの ID。
	ClientID string

	// Scopes は付与されたスコープ。
	Scopes []string

	// IssuedAt はトークン発行日時。
	IssuedAt time.Time

	// ExpiresAt はトークン有効期限。
	ExpiresAt time.Time

	// Revoked はトークンがリボケーション済みかどうか。
	Revoked bool

	// IDToken は Config.StoreIDToken = true のとき、IdP が発行した生の ID Token 文字列。
	// bearer.go での Validate 時に User.IDToken に伝播される。
	// StoreIDToken = false(デフォルト)の場合は空文字列。
	IDToken string
}

AccessTokenData はアクセストークンのメタデータを保持する。 トークン自体は JWT として自己完結するが、 リボケーション用に Store にも記録する。

type Auth

type Auth struct {
	// contains filtered or unexported fields
}

Auth はリクエスト認証ミドルウェアのメインエントリポイント。 Wrap() で http.Handler をラップし、リクエストの種類に応じて OAuth AS / Bearer 検証 / セッション検証 / ブラウザリダイレクト / 401 を判定する。

func New

func New(ctx context.Context, cfg Config) (*Auth, error)

New は Auth を構築し、内部コンポーネント(ProviderManager, SessionManager, BrowserAuth)を初期化する。

func (*Auth) SetOAuthServer

func (a *Auth) SetOAuthServer(h http.Handler)

SetOAuthServer は OAuth 2.1 AS ハンドラーを設定する。 M14-M17 で構築した OAuthServer を Wrap() の前に設定する。

func (*Auth) Wrap

func (a *Auth) Wrap(next http.Handler) http.Handler

Wrap は認証ミドルウェアを返す。

リクエスト判定ロジック:

  1. BrowserAuth パス(/login, /callback, /select) → BrowserAuth に委譲
  2. OAuth AS パス(/.well-known/*, /register, /authorize, /token) → OAuthServer に委譲
  3. Authorization: Bearer ヘッダー → JWT 検証(M13 でスタブから本実装へ)
  4. セッション Cookie → SessionManager でセッション検証、User をコンテキストに注入
  5. Accept: text/html を含むブラウザリクエスト → ログインページへリダイレクト
  6. その他 API リクエスト → 401 Unauthorized

type AuthCodeData

type AuthCodeData struct {
	// Code は認可コード文字列(暗号論的乱数、32バイト hex)。
	Code string

	// ClientID は認可リクエストを送った OAuth クライアントの ID。
	ClientID string

	// RedirectURI は認可リクエストで指定されたリダイレクト URI。
	RedirectURI string

	// CodeChallenge は PKCE のコードチャレンジ(S256)。
	CodeChallenge string

	// CodeChallengeMethod は "S256" 固定。
	CodeChallengeMethod string

	// Scopes は認可されたスコープ。
	Scopes []string

	// User は認証済みユーザー情報。
	User *User

	// CreatedAt は認可コード発行日時。
	CreatedAt time.Time

	// ExpiresAt は認可コード有効期限(デフォルト10分)。
	ExpiresAt time.Time

	// Used は認可コードが既に使用済みかどうか。
	// OAuth 2.1 では認可コードは1回のみ使用可能。
	Used bool

	// IDToken は Config.StoreIDToken = true のとき、IdP が発行した生の ID Token 文字列。
	// authorization_code → access_token 発行時に AccessTokenData に伝播される。
	// StoreIDToken = false(デフォルト)の場合は空文字列。
	IDToken string

	// IDPRefreshToken は IdP が発行した refresh_token。
	// ブラウザ認証(OIDC コールバック)時に offline_access スコープ付きで取得した場合に保存される。
	// authorization_code 経路で RefreshTokenData に伝播され、rotation 時に新しい id_token を取得するために使用する。
	IDPRefreshToken string
}

AuthCodeData は OAuth 2.1 認可コードに紐づくデータを保持する。

type BearerValidator

type BearerValidator struct {
	// contains filtered or unexported fields
}

BearerValidator は Bearer JWT アクセストークンを検証する。 JWT の署名検証、クレーム検証、Store でのリボケーションチェックを行い、 認証済みの User を返す。

func NewBearerValidator

func NewBearerValidator(cfg Config, store Store) (*BearerValidator, error)

NewBearerValidator は BearerValidator を構築する。 Config.OAuth が nil の場合、または SigningKey が ECDSA でない場合はエラーを返す。

func (*BearerValidator) Validate

func (v *BearerValidator) Validate(ctx context.Context, tokenStr string) (*User, error)

Validate は Bearer トークン文字列を検証し、認証済み User を返す。 無効な場合は error を返す。

検証手順:

  1. JWT をパースし ES256 公開鍵で署名検証(exp, iss, aud は parser が自動検証)
  2. jti クレームの存在確認
  3. email クレームの存在確認
  4. Store でリボケーションチェック(jti で検索)
  5. 成功時: User を構築して返す

type BrowserAuth

type BrowserAuth struct {
	// contains filtered or unexported fields
}

BrowserAuth はブラウザベースの OIDC 認証フローを処理する。 LoginHandler で IdP へのリダイレクトを行い、 CallbackHandler で認可コードを ID Token に交換してセッションを発行する。

func NewBrowserAuth

func NewBrowserAuth(cfg Config, pm *ProviderManager, sm *SessionManager, store Store) *BrowserAuth

NewBrowserAuth は新しい BrowserAuth を生成する。

func (*BrowserAuth) CallbackHandler

func (ba *BrowserAuth) CallbackHandler() http.Handler

CallbackHandler は GET /callback を処理する。 IdP からの認可コードを ID Token に交換し、セッションを発行して元の URL にリダイレクトする。

func (*BrowserAuth) LoginHandler

func (ba *BrowserAuth) LoginHandler() http.Handler

LoginHandler は GET /login を処理し、IdP へのリダイレクトを行う。

クエリパラメータ:

  • provider: 使用する IdP の Issuer URL(複数プロバイダー時に必須)
  • redirect_to: 認証後のリダイレクト先 URL(デフォルト: "/")

単一プロバイダーの場合は provider パラメータを省略可能。

func (*BrowserAuth) SelectionHandler

func (ba *BrowserAuth) SelectionHandler() http.Handler

SelectionHandler は複数 IdP 時のプロバイダー選択ページを表示する。 単一プロバイダーの場合は /login に直接リダイレクトする。

type ClientData

type ClientData struct {
	// ClientID は自動生成されたクライアント識別子(UUID v4)。
	ClientID string `json:"client_id"`

	// ClientName はクライアントの表示名。
	ClientName string `json:"client_name,omitempty"`

	// RedirectURIs は許可されたリダイレクト URI のリスト。
	RedirectURIs []string `json:"redirect_uris"`

	// GrantTypes は許可された grant_type(デフォルト: ["authorization_code"])。
	GrantTypes []string `json:"grant_types"`

	// ResponseTypes は許可された response_type(デフォルト: ["code"])。
	ResponseTypes []string `json:"response_types"`

	// TokenEndpointAuthMethod はトークンエンドポイントの認証方式(デフォルト: "none")。
	TokenEndpointAuthMethod string `json:"token_endpoint_auth_method"`

	// Scope はスペース区切りのスコープ文字列。
	Scope string `json:"scope,omitempty"`

	// CreatedAt はクライアント登録日時。
	CreatedAt time.Time `json:"created_at"`
}

ClientData は動的登録されたクライアントの情報を保持する(RFC 7591)。

type Config

type Config struct {
	// Providers は OIDC プロバイダーのリスト(1つ以上必須)。
	Providers []OIDCProvider

	// AllowedDomains は許可するメールドメインのリスト。
	// 空の場合、ドメインによる制限なし。
	AllowedDomains []string

	// AllowedEmails は許可する個別メールアドレスのリスト。
	// AllowedDomains と OR 条件で評価される。
	AllowedEmails []string

	// ExternalURL はこのサービスの外部公開 URL。
	// OAuth コールバック URL やメタデータの issuer として使用される。
	// 例: "https://mcp-auth.example.com"
	ExternalURL string

	// CookieSecret は Cookie 暗号化用の秘密鍵(32バイト以上)。
	CookieSecret []byte

	// OAuth は OAuth 2.1 AS の設定。
	// nil の場合、OAuth 2.1 AS エンドポイントは無効化される
	//(ブラウザベース認証のみ)。
	OAuth *OAuthConfig

	// Store はセッション・トークン等の保存先。
	// nil の場合、デフォルトの MemoryStore が使用される。
	Store Store

	// SessionMaxAge はブラウザセッションの最大有効期間。
	// デフォルト: 24時間。
	SessionMaxAge time.Duration

	// AccessTokenTTL は OAuth 2.1 Access Token の有効期間。
	// デフォルト: 1時間。
	AccessTokenTTL time.Duration

	// RefreshTokenTTL は OAuth 2.1 Refresh Token の有効期間。デフォルト: 30日。
	RefreshTokenTTL time.Duration

	// AuthCodeTTL は認可コードの有効期間。
	// デフォルト: 10分。
	AuthCodeTTL time.Duration

	// Logger は slog.Logger インスタンス。
	// nil の場合、slog.Default() を使用。
	Logger *slog.Logger

	// PathPrefix は OAuth 2.1 AS エンドポイントのパスプレフィックス。
	// デフォルト: "" (ルート直下)。
	// 例: "/auth" → /auth/authorize, /auth/token 等
	PathPrefix string

	// DefaultPostLoginPath は認証完了後のデフォルトリダイレクト先。
	// 空文字列なら "/" を使用(現状互換)。
	// `LoginHandler` の `redirect_to` クエリが未指定の場合に使用される。
	// 先頭が "/" で始まる相対パスである必要があり、"//" で始まる
	// protocol-relative URL は禁止(Validate でエラー)。
	DefaultPostLoginPath string

	// OnAuthenticated は認証完了時(CallbackHandler 内の session 発行直後)に
	// 呼ばれるフック。
	//
	// 戻り値の解釈(4 状態):
	//   - handled=true, redirectTo=""    : フック側で ResponseWriter に応答済み。
	//                                       BrowserAuth はリダイレクトしない。
	//   - handled=true, redirectTo!=""   : フック側で応答済みと解釈し、redirectTo
	//                                       は無視される(godoc 上の契約)。
	//   - handled=false, redirectTo!=""  : PostLoginRedirectValidator を通してから
	//                                       redirectTo へ 302。Validator が nil なら
	//                                       直接 302、Validator がエラーを返すなら 500。
	//   - handled=false, redirectTo==""  : 現状通り state に保存された RedirectURI へ 302。
	//
	// 呼び出し前後で `r.Context().Err() != nil` を検出した場合、BrowserAuth は
	// それ以降 ResponseWriter に何も書かずハンドラーを終了する(client cancellation 伝播)。
	//
	// フックは認証完了に同期で呼ばれるため、長い処理は呼び出し側で goroutine 化すること。
	// フック内で panic が発生した場合、BrowserAuth は recover して 500 を返す
	// (`http.ErrAbortHandler` だけは再 panic)。
	OnAuthenticated func(w http.ResponseWriter, r *http.Request, user *User) (redirectTo string, handled bool)

	// PostLoginRedirectValidator は post-login redirect 先の安全性を検証する関数。
	//
	// 適用される箇所:
	//   - `LoginHandler` の `redirect_to` クエリ
	//   - `SelectionHandler` の `redirect_to` クエリ
	//   - `Auth.Wrap` の未認証ブラウザリクエストで生成される `redirect_to`
	//   - `OAuthServer.redirectToLogin` の `redirect_to`
	//   - `OnAuthenticated` フック戻り値の `redirectTo`
	//
	// nil なら検査しない(v0.4.2 までの動作互換、純粋 API 追加)。
	// `StrictPostLoginRedirectValidator(cfg.ExternalURL)` または
	// `(*Config).UseStrictPostLoginRedirectValidator()` を呼ぶことで opt-in できる。
	//
	// Validator が non-nil でエラーを返した場合、入力起因のため 400 を返す(500 ではない)。
	// Validator 内 panic は BrowserAuth 側で recover して 500 を返す。
	PostLoginRedirectValidator func(redirectTo string) error

	// StoreIDToken は、セッションに保存済みの生の ID Token を
	// UserFromContext(ctx).IDToken 経由でハンドラーに公開するかどうかを指定する。
	//
	// デフォルト: false(既存動作を維持)。
	//
	// 注意: ID Token はこの設定に関わらず常にセッションストアに保存される。
	// この設定は「保存するかどうか」ではなく「コンテキストへ露出するかどうか」を制御する。
	//
	// true にすると、OIDC コールバック(ブラウザ認証フロー)経由でログインしたとき、
	// UserFromContext(ctx).IDToken に IdP が発行した ID Token 文字列がセットされる。
	// Bearer Token フロー(セッションなし)では常に空文字列となる。
	//
	// 主な用途: AWS STS AssumeRoleWithWebIdentity など、
	// IdP が発行したトークンをそのままダウンストリームサービスに渡す必要がある場合。
	//
	// 注意:
	//   - ストアの暗号化が有効であることを確認すること。
	//   - ID Token の有効期限(exp クレーム)はセッション有効期限より短い場合がある(多くの
	//     IdP では約 1 時間)。IDToken を使用する際は呼び出し側で exp を確認すること。
	//     期限切れでも UserFromContext(ctx).IDToken は空でない文字列を返し続ける。
	StoreIDToken bool
}

Config は idproxy の設定を保持する。

func (*Config) UseStrictPostLoginRedirectValidator added in v0.5.0

func (c *Config) UseStrictPostLoginRedirectValidator()

UseStrictPostLoginRedirectValidator は Config.PostLoginRedirectValidator に `StrictPostLoginRedirectValidator(c.ExternalURL)` を設定するヘルパー。

呼び出すと Strict Validator が opt-in され、相対パスおよび同一 origin の 絶対 URL のみが許可される。`Config.ExternalURL` の渡し忘れを防ぐため、 利用側はこのメソッド経由でセットすることを推奨する。

func (*Config) Validate

func (c *Config) Validate() error

Validate は Config のバリデーションを行い、デフォルト値を適用する。 使用前に必ず呼び出すこと。

type OAuthConfig

type OAuthConfig struct {
	// SigningKey は JWT 署名用の秘密鍵。
	// *ecdsa.PrivateKey(ES256)または *rsa.PrivateKey(RS256)。
	SigningKey crypto.Signer

	// SigningMethod は JWT 署名アルゴリズム。
	// デフォルト: SigningKey の型から自動判定(ECDSA → ES256, RSA → RS256)。
	SigningMethod jwt.SigningMethod

	// ClientID は OAuth 2.1 クライアント ID。
	// 静的クライアント設定用(動的クライアント登録は Phase 3 で追加)。
	// 空の場合、/authorize エンドポイントは任意の client_id を受け付ける。
	ClientID string

	// AllowedRedirectURIs は許可するリダイレクト URI のリスト。
	// /authorize エンドポイントで redirect_uri の検証に使用する。
	// 空の場合、localhost の URI のみ許可する(開発用)。
	AllowedRedirectURIs []string
}

OAuthConfig は OAuth 2.1 Authorization Server の設定。

type OAuthServer

type OAuthServer struct {
	// contains filtered or unexported fields
}

OAuthServer は OAuth 2.1 Authorization Server エンドポイントを提供する。 RFC 8414 メタデータ、JWKS、および /authorize を処理する。

func NewOAuthServer

func NewOAuthServer(cfg Config, store Store, sm *SessionManager, pm *ProviderManager) (*OAuthServer, error)

NewOAuthServer は OAuthServer を構築する。 Config.OAuth が設定されている場合はその SigningKey(ECDSA P-256)を使用する。 Config.OAuth が nil の場合は ES256 鍵ペアを自動生成する。 sm は SessionManager(/authorize でユーザー認証確認に使用)。nil の場合もエラーにはしない。 pm は IdP refresh_token を使って id_token を更新するための ProviderManager。 nil の場合は IdP refresh をスキップして旧来の動作(古い IDToken を引き継ぐ)になる。

func (*OAuthServer) ServeHTTP

func (s *OAuthServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP はリクエストを適切なハンドラーにルーティングする。

type OIDCProvider

type OIDCProvider struct {
	// Issuer は OIDC Issuer URL。
	// 例: "https://accounts.google.com"
	// 例: "https://login.microsoftonline.com/{tenant-id}/v2.0"
	Issuer string

	// ClientID は OAuth Client ID。
	ClientID string

	// ClientSecret は OAuth Client Secret。
	ClientSecret string

	// Scopes は要求するスコープ。
	// デフォルト: ["openid", "email", "profile"]
	Scopes []string

	// Name はプロバイダーの表示名(ログイン画面等で使用)。
	// 空の場合、Issuer から自動生成。
	Name string
}

OIDCProvider は1つの OIDC プロバイダーの設定を保持する。

type ProviderManager

type ProviderManager struct {
	// contains filtered or unexported fields
}

ProviderManager は複数の OIDC プロバイダーを管理する。

func NewProviderManager

func NewProviderManager(ctx context.Context, cfg Config) (*ProviderManager, error)

NewProviderManager は Config.Providers から ProviderManager を生成する。 各プロバイダーに対して OIDC Discovery を取得し、初期化を行う。

func (*ProviderManager) Count

func (pm *ProviderManager) Count() int

Count はプロバイダー数を返す。

func (*ProviderManager) Get

func (pm *ProviderManager) Get(issuer string) (*providerEntry, bool)

Get は Issuer URL に対応するプロバイダー情報を返す。

func (*ProviderManager) List

func (pm *ProviderManager) List() []OIDCProvider

List は設定順序でプロバイダー一覧を返す。

func (*ProviderManager) OAuth2Config

func (pm *ProviderManager) OAuth2Config(issuer string) (*oauth2.Config, error)

OAuth2Config は指定プロバイダーの oauth2.Config を返す。

func (*ProviderManager) SelectionHTML

func (pm *ProviderManager) SelectionHTML() string

SelectionHTML は複数プロバイダー選択ページの HTML を生成する。

func (*ProviderManager) Single

func (pm *ProviderManager) Single() (*providerEntry, bool)

Single は単一プロバイダーの場合にそのプロバイダーを返す。 複数の場合は nil, false を返す。

func (*ProviderManager) Verifier

func (pm *ProviderManager) Verifier(issuer string) (*oidc.IDTokenVerifier, error)

Verifier は指定プロバイダーの IDTokenVerifier を返す。

type RefreshTokenData added in v0.3.0

type RefreshTokenData struct {
	// ID は opaque リフレッシュトークン文字列(32バイト base64url)。
	ID string

	// FamilyID は同一 authorization_code から派生した全リフレッシュトークンに共通の UUID v4。
	FamilyID string

	// ClientID は発行時の OAuth クライアントの ID。
	ClientID string

	// Subject はユーザーの OIDC sub クレーム。
	Subject string

	// OIDCIssuer は元の OIDC プロバイダの issuer URL。
	// Bearer アクセストークンの User.Issuer を復元するために使用する。
	// セッション経由の User.Issuer(OIDC issuer)と Bearer JWT の iss(ExternalURL)が
	// 異なるため、principal_id の一貫性を保つために明示的に保持する。
	OIDCIssuer string

	// Email はユーザーのメールアドレス(新 access_token 再発行用)。
	Email string

	// Name はユーザーの表示名(新 access_token 再発行用)。
	Name string

	// Scopes は付与されたスコープ。
	Scopes []string

	// IssuedAt はトークン発行日時。
	IssuedAt time.Time

	// ExpiresAt はトークン有効期限。
	ExpiresAt time.Time

	// Used は消費済みフラグ。ConsumeRefreshToken で true に更新される。
	Used bool

	// IDToken は Config.StoreIDToken = true のとき、IdP が発行した生の ID Token 文字列。
	// refresh_token グラント時に新 AccessTokenData.IDToken に引き継がれる。
	// StoreIDToken = false(デフォルト)の場合は空文字列。
	IDToken string

	// IDPRefreshToken は IdP が発行した refresh_token。
	// authorization_code グラント時に AuthCodeData.IDPRefreshToken から引き継がれ、
	// rotation 時に新しい id_token を取得するために使用する。
	// 一部の IdP(Entra ID 等)は refresh_token を毎回 rotate するため、rotation 後の新しいトークンで上書きする。
	IDPRefreshToken string
}

RefreshTokenData は OAuth 2.1 リフレッシュトークンに紐づくデータを保持する。 rotation + family tracking + replay detection に使用する。

注意(移行): IDToken フィールドの追加により、unkeyed struct literal (例: idproxy.RefreshTokenData{"id", "family", ...})を使用しているコードはコンパイルエラーになる。 keyed literal(例: idproxy.RefreshTokenData{ID: "...", FamilyID: "..."})に移行すること。

type Session

type Session struct {
	// ID はセッションの一意識別子(UUID v4)。
	ID string

	// User は認証済みユーザー情報。
	User *User

	// ProviderIssuer は認証に使用した IdP の Issuer URL。
	ProviderIssuer string

	// IDToken は IdP から取得した生の ID Token。
	// セッション復元時の検証やクレーム参照に使用。
	IDToken string

	// IDPRefreshToken は IdP が発行した refresh_token。
	// offline_access スコープ付きブラウザ認証時に保存される。
	// OAuth 2.1 refresh_token rotation 時に新しい id_token を取得するために使用する。
	IDPRefreshToken string

	// CreatedAt はセッション作成日時。
	CreatedAt time.Time

	// ExpiresAt はセッション有効期限。
	ExpiresAt time.Time
}

Session はブラウザセッションのデータを保持する。

type SessionManager

type SessionManager struct {
	// contains filtered or unexported fields
}

SessionManager は Cookie ベースのセッション管理を担当する。 gorilla/securecookie を使って Cookie を暗号化・署名し、 Store インターフェース経由でセッションデータを永続化する。

func NewSessionManager

func NewSessionManager(cfg Config) (*SessionManager, error)

NewSessionManager は新しい SessionManager を生成する。 cfg.CookieSecret は 32 バイト以上が必要。 cfg.Store が nil の場合はエラーを返す。

func (*SessionManager) DeleteSession

func (sm *SessionManager) DeleteSession(ctx context.Context, w http.ResponseWriter, r *http.Request) error

DeleteSession はセッションを削除し、Cookie を無効化する。 Cookie が存在しない場合は何もしない(冪等)。 Cookie の復号が失敗した場合でも、MaxAge=-1 の Cookie を必ず設定する。

func (*SessionManager) GetSessionFromRequest

func (sm *SessionManager) GetSessionFromRequest(ctx context.Context, r *http.Request) (*Session, error)

GetSessionFromRequest はリクエストの Cookie からセッションを取得する。 Cookie が存在しない場合は nil, nil を返す(エラーではない)。 Cookie が無効(改ざん等)の場合は nil, error を返す。 Store にセッションが存在しない(期限切れを含む)場合は nil, nil を返す。

func (*SessionManager) IssueSession

func (sm *SessionManager) IssueSession(ctx context.Context, user *User, providerIssuer, idToken, idpRefreshToken string) (*Session, error)

IssueSession は新しいセッションを発行し、Store に保存して返す。 セッション ID は UUID v4 で生成する。 idpRefreshToken は IdP が発行した refresh_token(offline_access スコープ取得時)。 取得できない場合(スコープ未設定等)は空文字列を渡す。

func (*SessionManager) SetCookie

func (sm *SessionManager) SetCookie(w http.ResponseWriter, sessionID string) error

SetCookie はセッション ID を暗号化して Set-Cookie ヘッダーを設定する。

type Store

type Store interface {
	// セッション操作
	SetSession(ctx context.Context, id string, session *Session, ttl time.Duration) error
	GetSession(ctx context.Context, id string) (*Session, error)
	DeleteSession(ctx context.Context, id string) error

	// 認可コード操作(OAuth 2.1 AS 用)
	SetAuthCode(ctx context.Context, code string, data *AuthCodeData, ttl time.Duration) error
	GetAuthCode(ctx context.Context, code string) (*AuthCodeData, error)
	DeleteAuthCode(ctx context.Context, code string) error

	// アクセストークン操作(リボケーション用)
	SetAccessToken(ctx context.Context, jti string, data *AccessTokenData, ttl time.Duration) error
	GetAccessToken(ctx context.Context, jti string) (*AccessTokenData, error)
	DeleteAccessToken(ctx context.Context, jti string) error

	// クライアント操作(Dynamic Client Registration: RFC 7591
	SetClient(ctx context.Context, clientID string, data *ClientData) error
	GetClient(ctx context.Context, clientID string) (*ClientData, error)
	DeleteClient(ctx context.Context, clientID string) error

	// リフレッシュトークン操作(OAuth 2.1 rotation + replay detection 用)
	SetRefreshToken(ctx context.Context, id string, data *RefreshTokenData, ttl time.Duration) error
	GetRefreshToken(ctx context.Context, id string) (*RefreshTokenData, error)
	// ConsumeRefreshToken はリフレッシュトークンを消費する。
	// 未登録または期限切れ: (nil, nil)
	// 初回消費: (data, nil) — Used フラグを true に更新
	// 2回目以降: (data, ErrRefreshTokenAlreadyConsumed) — familyID 取得のため data も返す
	ConsumeRefreshToken(ctx context.Context, id string) (*RefreshTokenData, error)
	SetFamilyRevocation(ctx context.Context, familyID string, ttl time.Duration) error
	IsFamilyRevoked(ctx context.Context, familyID string) (bool, error)

	// クリーンアップ
	Cleanup(ctx context.Context) error
	Close() error
}

Store はセッション、認可コード、アクセストークンの永続化インターフェース。

type User

type User struct {
	// Email はユーザーのメールアドレス。
	Email string

	// Name はユーザーの表示名。
	Name string

	// Subject は OIDC sub クレーム。
	Subject string

	// Issuer は認証に使用された IdP の Issuer URL。
	Issuer string

	// Claims は ID Token の全クレーム。
	Claims map[string]interface{}

	// IDToken は IdP が発行した生の ID Token 文字列。
	// Config.StoreIDToken = true の場合のみセットされる。
	// AWS STS AssumeRoleWithWebIdentity 等、IdP トークンが必要な用途に使用する。
	IDToken string
}

User は認証済みユーザーの情報を保持する。

注意(移行): IDToken フィールドの追加により、unkeyed struct literal (例: idproxy.User{"email", "name", ...})を使用しているコードはコンパイルエラーになる。 keyed literal(例: idproxy.User{Email: "...", Name: "..."})に移行すること。

func UserFromContext

func UserFromContext(ctx context.Context) *User

UserFromContext はリクエストコンテキストから認証済みユーザー情報を取得する。 認証されていない場合は nil を返す。

Directories

Path Synopsis
cmd
idproxy command
examples
basic command
Package main は idproxy ライブラリを使った基本的なリバースプロキシの例です。
Package main は idproxy ライブラリを使った基本的なリバースプロキシの例です。
cascade-oauth command
Package main は idproxy の OnAuthenticated フックを使った カスケード OAuth パターンの最小サンプルです。
Package main は idproxy の OnAuthenticated フックを使った カスケード OAuth パターンの最小サンプルです。
dynamodb-coexist command
Package main は idproxy DynamoDB Store と利用側独自データ(同テーブル + 独自 GSI)の 共存サンプルです。
Package main は idproxy DynamoDB Store と利用側独自データ(同テーブル + 独自 GSI)の 共存サンプルです。
mcp-server command
Package main は idproxy ライブラリを使った MCP サーバー保護の例です。
Package main は idproxy ライブラリを使った MCP サーバー保護の例です。
Package store provides implementations of the idproxy.Store interface for session, authorization code, and access token persistence.
Package store provides implementations of the idproxy.Store interface for session, authorization code, and access token persistence.
redis
Package redis は idproxy.Store の Redis 実装を提供する。
Package redis は idproxy.Store の Redis 実装を提供する。
sqlite
Package sqlite は idproxy.Store の SQLite 実装を提供する。
Package sqlite は idproxy.Store の SQLite 実装を提供する。
storetest
Package storetest は idproxy.Store 実装の適合性テストスイートを提供する。
Package storetest は idproxy.Store 実装の適合性テストスイートを提供する。
Package testutil provides test helpers for idproxy, including a mock OIDC Identity Provider server for integration testing.
Package testutil provides test helpers for idproxy, including a mock OIDC Identity Provider server for integration testing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL