Help us shape the future of Go! Take the 2026 Go Developer Survey

authengine

package module
v0.0.0-...-e29b97a Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

auth-engine

Go 製のヘッドレスな OAuth 2.0 / OpenID Connect 認可サーバー「Protocol Engine」。

ログイン・同意 UI とユーザー管理は外部アプリケーション(Interaction App)の責務とし、本体はプロトコル処理(/authorize, /token, /userinfo, /revoke, /introspect, /jwks, Discovery)と Authorization Transaction・Grant・トークンの状態管理に専念する。 ロジックがわかりやすく、他者の参考実装になる品質を目指す。

状態

M3 まで完了(2026-10-25)。API は安定していない。

  • M1: Authorization Code + PKCE、Opaque Access Token、SQLite Adapter、Interaction API
  • M2: OIDC Basic OP(ID Token、/jwks、/userinfo、OpenID Discovery)、Refresh Token Rotation、 client_credentials、Revocation(RFC 7009)、Introspection(RFC 7662)、Grant 管理 API、 PostgreSQL Adapter。OpenID Conformance Suite(Basic OP)はローカルで実行済みだが、PKCE 必須の設計と プランの前提が合わず大半のモジュールは評価できていない(docs/conformance.md)
  • M3: MCP 連携。Resource Indicators(RFC 8707)と Audience、MCP Client Profile と CIMD(事前登録なしのクライアント)、 JWT Access Token(RFC 9068、resource ごとに選択)、Resource Server 用ミドルウェア resourceserver(RFC 9728)。 MCP Inspector との相互運用を確認済み(docs/mcp-interop.md)。Dynamic Client Registration は実装しない(ADR-0008 §8)
  • 次は M4(Token Exchange、DPoP、PAR、private_key_jwt、RAR)

試す

# エンジン + Interaction API + デモのログイン画面を 1 プロセスで起動
cd examples/standalone && go run ./cmd/server -db ./auth.db

# 別の端末で、Native クライアントとしてフローを実行(URL をブラウザで開く)
cd examples/standalone && go run ./cmd/cli-client

詳細は examples/standalone/README.md。

組み込む

自分のサービスに載せる手順(Store の選択、Client 登録、2 つの Handler の公開、鍵の保管、監査ログ、本番前の確認)は 組み込みガイド にまとめてある。コード例は各パッケージの Example テスト(example_test.go)にあり、go test で動作を確かめている。フロー全体を 1 プロセス内で通す例は httpapi/example_test.go の Example_authorizationCodeFlow。

go doc -all github.com/u-masato/auth-engine/httpapi   # Example を含むパッケージ文書を端末で読む
go test -run Example -v ./...                      # Example を実行する

モジュール構成

モジュール 内容 外部依存
github.com/u-masato/auth-engine コア。client / authorization / grant / token / oidc / keys / httpapi / storage / resource / cimd と、配線の入口 Engine。Resource Server 側に組み込む resourceserver も同じモジュール go-jose/v4 のみ
.../adapters/sqlite SQLite Store Adapter modernc.org/sqlite, goose
.../adapters/postgres PostgreSQL Store Adapter pgx/v5, goose(テストに Testcontainers)
.../examples/standalone デモサーバー、デモ Interaction App、サンプルクライアント、開発者コンソール、デモ MCP サーバー、CIMD 文書の配信 —
.../tests E2E テスト(SQLite + HTTP + Interaction App) go-jose/v4(RP 側の ID Token 検証)

Interaction App(ログイン・同意画面)を実装するには docs/interaction-api.md を読む。

設計

意図した制約

  • PKCE(S256)を使わない Authorization Code Grant は受け付けない。Implicit / Password Grant は提供しない。
  • Client の設定は Client Profile(Web / Native・CLI / M2M / MCP)で固定し、RFC の個別設定は開放しない。MCP クライアントは CIMD 文書の HTTPS URL を client_id とし、事前登録なしで接続できる(Config.CIMD で有効化)。Dynamic Client Registration は提供しない。
  • Access Token は既定で Opaque。Resource Server は Introspection(または同一プロセスなら Go API Engine.Token.Inspect)で検証し、応答の aud に自分の resource URI が含まれることを確認する。Config.Resources で JWT(RFC 9068、typ: at+jwt)を選んだ resource には JWT を発行し、/jwks でローカル検証できる。ただし失効は JWT の exp まで伝播しないので、JWT を選ぶ resource は短い AccessTokenTTL の Client と組み合わせる。
  • Refresh Token は Rotation 必須。再利用を検知したら Token Family 全体を失効させる。
  • resource(RFC 8707)は Config.Resources に設定した Resource Server だけを受理し、それ以外は invalid_target。設定が空なら resource 付きの要求はすべて失敗する(意図したフェイルクローズ。M1 / M2 では黙って受理していた)。
  • 永続化は Store Port 経由。コアモジュールは DB ドライバーを参照しない。

開発

make test   # 全モジュールで go vet + go test -race
make lint   # staticcheck + govulncheck + コア依存の検査

Go 1.26 以上。モジュールは go.work で束ねている。PostgreSQL Adapter のテストは Docker(Testcontainers)が必要で、なければ Skip する。AUTH_ENGINE_POSTGRES_DSN で既存の DB を指すこともできる。

ライセンス

Apache License 2.0

Documentation

Overview

Package authengine は、ヘッドレスな OAuth 2.0 / OpenID Connect 認可サーバー 「Protocol Engine」のルートパッケージである。

エンジンはプロトコル処理(/authorize, /token, /userinfo, /jwks, Discovery)と Authorization Transaction・Grant・トークンの状態管理だけを担う。 ログイン・同意 UI とユーザー管理は外部の Interaction App の責務である (docs/adr/0003-interaction-contract.md)。

パッケージ構成と依存方向は docs/adr/0007-package-layout.md に従う。 このルートパッケージは各文脈パッケージの Store インターフェースを合成した Store と、全 Service を配線する Engine を提供する。

使い方

組み込む側が用意するものは 4 つある。

  • Store: 永続化 Adapter。adapters/sqlite か adapters/postgres(別モジュール)。 storage/memory はテスト専用。
  • Keys: 署名鍵セット(keys パッケージ)。RS256 の署名鍵を含め、再起動後も同じ鍵を使えるよう保存する。
  • Client の登録: client.NewWeb / NewNative / NewMachine で作り、Store.CreateClient で登録する。
  • Interaction App: ログイン・同意画面。docs/interaction-api.md の契約に従って実装する。

MCP 連携(docs/adr/0008-mcp-integration.md)を使うときは、さらに Config.Resources に Resource Server(resource パッケージ)を列挙し、事前登録なしの MCP クライアントを受け入れるなら Config.CIMD(cimd パッケージ)を与える。Resource Server 側には resourceserver パッケージを組み込む。

New で Engine を組み立て、httpapi.New に渡すと、公開エンドポイント(PublicHandler)と Interaction App 向けのバックチャネル(InteractionHandler)の 2 つの http.Handler が得られる。 期限切れデータの削除(Store.Purge)は利用者のスケジューラから呼ぶ。

各パッケージの Example と、組み込みの手順・本番の注意点をまとめた docs/embedding.md も参照すること。フロー全体を 1 プロセス内で通す例は httpapi パッケージの Example (AuthorizationCodeFlow) にある。

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ValidateIssuer

func ValidateIssuer(issuer string) error

ValidateIssuer は Issuer の形式を検証する。http は localhost / loopback に限る。

Types

type Config

type Config struct {
	// Issuer は認可サーバーの識別子(RFC 8414 の issuer)。https の絶対 URL で、
	// クエリとフラグメントを含まない。開発用に http://localhost / loopback も許す。
	// パスを含まないこと(エンドポイントは Issuer 直下に配置する)。
	Issuer string

	// AllowInsecureIssuer は localhost 以外の http Issuer を許す開発用の緩和
	// (例: Docker 内の Conformance Suite から http://host.docker.internal:8080 で到達させる)。
	// 既定 false。true のとき起動時に警告ログを出す。本番では使わない。
	AllowInsecureIssuer bool

	// Store は永続化 Adapter。必須。
	Store Store

	// Keys は ID Token の署名鍵セット。必須。RS256 の署名鍵を含むこと
	// (OIDC Core §15.1、Client の既定アルゴリズム)。
	Keys *keys.Set

	// Resources は Resource Server(RFC 8707 の resource indicator)の静的設定(ADR-0008 §1)。
	// 認可要求の resource はこの一覧にあるものだけを受理し、それ以外は invalid_target になる。
	// 空なら resource 付きの要求はすべて invalid_target(意図したフェイルクローズ)。
	Resources []resource.Resource

	// CIMD は Client ID Metadata Document(URL 形式の client_id)による MCP クライアントの解決を有効にする
	// (ADR-0008 §5)。nil なら無効で、Store に登録された Client だけを解決し、Discovery に
	// client_id_metadata_document_supported を載せない。cimd.Config の Now と Logger が nil なら Engine の値を使う。
	CIMD *cimd.Config

	// Now は現在時刻の取得関数。nil なら time.Now。テストで固定時刻を注入する。
	Now func() time.Time

	// Logger は監査イベントの出力先。nil なら slog.Default()。
	Logger *slog.Logger

	// TransactionTTL は Authorization Transaction の期限。0 なら 10 分、上限 1 時間。
	TransactionTTL time.Duration
	// CodeTTL は Authorization Code の期限。0 なら 60 秒、上限 10 分(RFC 6749 §4.1.2)。
	CodeTTL time.Duration
	// IDTokenTTL は ID Token の有効期間。0 なら 1 時間、上限 24 時間。
	IDTokenTTL time.Duration
	// RefreshTokenTTL は Refresh Token の絶対期限(Token Family の寿命)。0 なら 30 日。
	// RefreshTokenIdleTTL は最終使用からのスライド期限。0 なら 14 日。絶対期限を超えないこと。
	RefreshTokenTTL     time.Duration
	RefreshTokenIdleTTL time.Duration
}

Config は Engine の設定。環境変数や設定ファイルの解釈は利用者側で行い、構造体で渡す(ADR-0002)。

type Engine

type Engine struct {
	Issuer string
	Store  Store
	Keys   *keys.Set
	Logger *slog.Logger
	Clock  clock.Clock
	// Resources は検証・正規化済みの Resource Server 設定。
	Resources *resource.Set
	// Clients は client_id の解決経路。Store だけ、または Store → CIMD の ChainResolver(Config.CIMD を与えたとき)。
	// Interaction API など、Store ではなくこちらで Client を引くこと(CIMD Client は Store にない)。
	Clients client.Resolver
	// CIMD は Config.CIMD から組み立てた Resolver。無効なら nil。
	CIMD *cimd.Resolver

	Authorization *authorization.Service
	Token         *token.Service
	// Grants は Grant の管理操作(一覧・連携解除)。Go API と Interaction API の GET /grants が使う。
	Grants   *grant.Service
	IDTokens *oidc.IDTokenIssuer
	UserInfo *oidc.UserInfoService
}

Engine は全 Service を配線した本体。HTTP 層(httpapi)はこれを受け取る。

func New

func New(cfg Config) (*Engine, error)

New は Config を検証して Engine を組み立てる。

Example

ExampleNew は Engine を組み立てる最小の構成を示す。必須は Issuer・Store・Keys(RS256 の署名鍵を含む)の 3 つで、 TTL などは 0 のままなら既定値になる。HTTP への公開は httpapi.New に Engine を渡して行う。

package main

import (
	"fmt"
	"log"
	"time"

	authengine "github.com/u-masato/auth-engine"
	"github.com/u-masato/auth-engine/keys"
	"github.com/u-masato/auth-engine/resource"
	"github.com/u-masato/auth-engine/storage/memory"
)

func main() {
	ks := keys.NewSet()
	k, err := keys.Generate(keys.AlgRS256, time.Now()) // OIDC Core §15.1: RS256 は必須
	if err != nil {
		log.Fatal(err)
	}
	if err := ks.AddSigning(k); err != nil {
		log.Fatal(err)
	}

	engine, err := authengine.New(authengine.Config{
		Issuer: "https://as.example.com",
		Store:  memory.New(), // テスト用。本番では adapters/sqlite か adapters/postgres を使う
		Keys:   ks,
		// resource パラメータ(RFC 8707)で指定できる Resource Server。空なら resource 付きの要求はすべて invalid_target。
		Resources: []resource.Resource{{URI: "https://API.example.com/v1", Scopes: []string{"read", "write"}}},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(engine.Issuer)
	fmt.Println(engine.Resources.URIs())

}
Output:
https://as.example.com
[https://api.example.com/v1]
Example (Cimd)

ExampleNew_cimd は MCP クライアントを事前登録なしに受け入れる構成を示す。Config.CIMD を与えると、 https の URL 形式の client_id を CIMD(Client ID Metadata Document)として取得・検証する Resolver が Store の後ろに配線され、Discovery に client_id_metadata_document_supported: true が載る(ADR-0008 §5)。

package main

import (
	"fmt"
	"log"
	"time"

	authengine "github.com/u-masato/auth-engine"
	"github.com/u-masato/auth-engine/cimd"
	"github.com/u-masato/auth-engine/keys"
	"github.com/u-masato/auth-engine/resource"
	"github.com/u-masato/auth-engine/storage/memory"
)

func main() {
	ks := keys.NewSet()
	k, err := keys.Generate(keys.AlgRS256, time.Now())
	if err != nil {
		log.Fatal(err)
	}
	if err := ks.AddSigning(k); err != nil {
		log.Fatal(err)
	}

	engine, err := authengine.New(authengine.Config{
		Issuer: "https://as.example.com",
		Store:  memory.New(),
		Keys:   ks,
		// MCP クライアントは resource を必ず送るので、受け手の MCP サーバーを列挙しておく
		Resources: []resource.Resource{{URI: "https://mcp.example.com", Name: "Example MCP Server"}},
		CIMD: &cimd.Config{
			// 既定は全ドメインを信頼する。許可リストで絞るなら TrustPolicy を与える(CIMD §8.9)
			TrustPolicy: cimd.HostAllowlist{"*.example", "mcp-client.example"},
			// AllowLoopback は開発用。本番では false のまま(CIMD §8.6)
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("cimd enabled:", engine.CIMD != nil)

}
Output:
cimd enabled: true

type Store

type Store interface {
	client.Store
	authorization.Store
	grant.Store
	token.Store

	// Purge は now 時点で期限切れの Transaction、Authorization Code、Access Token、
	// Refresh Token を削除する。呼び出し頻度は利用者のスケジューラに委ねる。
	Purge(ctx context.Context, now time.Time) error
}

Store は Adapter が実装する永続化 Port の全体。

各文脈パッケージが自分に必要なメソッドだけを定義した Store インターフェースを、 ここで合成する(docs/adr/0007-package-layout.md §2)。エンジン内部の各 Service は 自分の文脈の Store だけを受け取り、この合成型を参照しない。

契約: 各メソッドは単体で原子的であること(docs/adr/0005-storage-port.md)。 全 Adapter は storage/storagetest の契約テストを通さなければならない。

Directories

Path Synopsis
adapters
postgres module
sqlite module
Package authorization は認可エンドポイント(/authorize)の処理を担う。
Package authorization は認可エンドポイント(/authorize)の処理を担う。
Package cimd は、CIMD(Client ID Metadata Document)の URL を client_id とする MCP クライアントを 事前登録なしに解決する client.Resolver 実装である(docs/adr/0008-mcp-integration.md §5)。
Package cimd は、CIMD(Client ID Metadata Document)の URL を client_id とする MCP クライアントを 事前登録なしに解決する client.Resolver 実装である(docs/adr/0008-mcp-integration.md §5)。
Package client は OAuth 2.0 クライアントの登録情報と、用途別に方針を固定する Client Profile を提供する(docs/adr/0004-client-profiles.md)。
Package client は OAuth 2.0 クライアントの登録情報と、用途別に方針を固定する Client Profile を提供する(docs/adr/0004-client-profiles.md)。
Package grant は Grant(ある Client に対してある subject が与えた認可の記録)を扱う。
Package grant は Grant(ある Client に対してある subject が与えた認可の記録)を扱う。
Package httpapi は Engine を net/http に載せる。
Package httpapi は Engine を net/http に載せる。
internal
clock
Package clock は、現在時刻の取得を差し替え可能にする。
Package clock は、現在時刻の取得を差し替え可能にする。
rand
Package rand は、トークン・識別子として使う暗号学的乱数の生成と、 保存用ハッシュの計算を提供する。
Package rand は、トークン・識別子として使う暗号学的乱数の生成と、 保存用ハッシュの計算を提供する。
Package keys は ID Token と JWT Access Token(RFC 9068)の署名鍵セットを管理する。
Package keys は ID Token と JWT Access Token(RFC 9068)の署名鍵セットを管理する。
Package oidc は OpenID Connect Core 1.0 のうち、エンジンが担う部分を実装する。
Package oidc は OpenID Connect Core 1.0 のうち、エンジンが担う部分を実装する。
Package resource は Resource Server(RFC 8707 の resource indicator で識別される保護リソース)の 静的設定と、認可要求・トークン要求の resource パラメータの正規化を担う (docs/adr/0008-mcp-integration.md §1〜§3)。
Package resource は Resource Server(RFC 8707 の resource indicator で識別される保護リソース)の 静的設定と、認可要求・トークン要求の resource パラメータの正規化を担う (docs/adr/0008-mcp-integration.md §1〜§3)。
Package resourceserver は、MCP サーバーなどの Resource Server に組み込む net/http ミドルウェアである (docs/adr/0008-mcp-integration.md §7)。
Package resourceserver は、MCP サーバーなどの Resource Server に組み込む net/http ミドルウェアである (docs/adr/0008-mcp-integration.md §7)。
Package storage は、Store Port の実装(Adapter)が返すセンチネルエラーを定義する葉パッケージである。
Package storage は、Store Port の実装(Adapter)が返すセンチネルエラーを定義する葉パッケージである。
memory
Package memory は、エンジンの単体テスト用の In-Memory Store である。
Package memory は、エンジンの単体テスト用の In-Memory Store である。
storagetest
Package storagetest は、全 Store Adapter が通すべき契約テストを提供する。
Package storagetest は、全 Store Adapter が通すべき契約テストを提供する。
Package token は Access Token / Refresh Token の発行・交換・Rotation と、 それらをまとめる Token Family を扱う。
Package token は Access Token / Refresh Token の発行・交換・Rotation と、 それらをまとめる Token Family を扱う。

Jump to

Keyboard shortcuts

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