プログラミング
Go-dev-auth: Go言語向けの依存関係ゼロの認証ライブラリ
How HN: Go-dev-auth zero-dependency authentication library for Go (github.com)
要約
Go-dev-authは、Go言語で構築された、外部依存関係を一切持たないフレームワーク非依存の認証ライブラリです。メール/パスワード認証、ソーシャルログイン、セッション管理、二要素認証、パスキー、マジックリンクなど、豊富な機能を標準ライブラリのみで提供します。本番環境での利用実績があり、v1.0リリースに向けて開発が進められています。
全文翻訳
go-dev-auth CIバッジはプッシュごとにマトリックス全体をカバーします。最古のサポートバージョンと現在のGoでのビルドとテスト、レース検出器、リンター、攻撃者側のパーサーに対するファズパス、そして実際のSQLite、PostgreSQL、MySQLサーバーに対するストレージ準拠スイートを実行します。
better-authに倣った、Go言語向けの包括的でフレームワークに依存しない認証ライブラリです。メールとパスワード、ソーシャルサインオン、セッション、アカウント連携、二要素認証、パスキー、マジックリンク、組織、SSO、管理者ツール、APIキー、JWTを、外部依存関係ゼロ(純粋な標準ライブラリ)で提供します。
go get github.com/go-dev-auth/go-dev-auth
ステータス: pre-1.0、本番利用中、v1.0へ移行中。このライブラリは、PostgreSQL上で実際の自動化プロジェクトでフル機能セットを使用して本番稼働しています。リリースはSemVerに従います。v1.0未満の間は、パブリックAPIがマイナーバージョン間で変更される可能性があります(正確なバージョンを指定してください)。v1.0でAPIは固定され、それ以降の破壊的変更にはメジャーバージョンが必要になります。v1.0の残りのゲートは、実行可能なサンプル、新しく自動化されたMySQLレッグでのフィールドマイレージ、およびサードパーティによるセキュリティレビューです。検証済みのバックエンドについてはストレージアダプターを参照し、脅威モデルについてはdocs/security-model.mdを参照してください。
機能
コア
* メールとパスワード認証(scryptハッシュ、better-authのハッシュ形式と互換性あり)
* OAuth 2.0 / OIDC(PKCE使用)によるソーシャルサインオン(Google、GitHub、Discord、Facebook、Microsoft、Apple、GitLab、LinkedIn、Spotify、Twitch、Xを内蔵、カスタムプロバイダー用の宣言的なoauth2.Specも利用可能)
* データベースバックエンドのセッション(スライディング有効期限、署名付きCookie、オプションのCookieキャッシュ、リスト/取り消しエンドポイント)
* メール検証、パスワードリセット、メール/パスワード変更、ユーザー削除フロー
* アカウント連携と解除(信頼されたプロバイダー、トークン更新、アカウント情報)
* CSRFオリジンチェック、ワイルドカードサブドメイン付きの信頼されたオリジン、IPベースのレート制限
* ストレージアダプターインターフェース(組み込みのdatabase/sql(Postgres、MySQL、SQLite)およびインメモリアダプター、スキーマ/マイグレーションSQL生成機能付き)
* リクエストフック、データベースフック、カスタムユーザー/セッションフィールド
プラグイン(better-authのプラグインシステムをミラーリング)
* twofactor — TOTP、メールOTP、バックアップコード
* passkey — WebAuthnパスキー、CBOR/COSE解析を含む(外部依存なし)
* magiclink — パスワードレスメールリンク
* organization — 組織、メンバー、ロール、招待、チーム
* sso — 独自のOIDCアイデンティティプロバイダー(メールドメインでマッチング)
* admin — ユーザー管理、禁止、ロール、なりすまし
* apikey — セッションのように認証されるスコープ付きハッシュ化APIキー
* jwt — EdDSA署名付きJWT + JWKSエンドポイント
* bearer — 非ブラウザクライアント向けのAuthorizationヘッダー認証
クイックスタート
package main
import (
"context"
"net/http"
"os"
"time"
godevauth "github.com/go-dev-auth/go-dev-auth"
"github.com/go-dev-auth/go-dev-auth/storage/memory"
)
func main() {
auth, err := godevauth.New(godevauth.Config{
BaseURL: "http://localhost:8080", // 必須
Secret: os.Getenv("AUTH_SECRET"), // 必須、32文字以上のランダムな文字列
Database: memory.New(), // 必須
EmailAndPassword: godevauth.EmailPasswordConfig{
Enabled: true,
},
// 本番環境で、これより前面に何か(ロードバランサー、インフラストラクチャ、CDNなど)がある場合は必須。
// 詳細については以下を参照。
Advanced: godevauth.AdvancedConfig{
TrustProxyHeaders: true,
TrustedProxies: []string{"10.0.0.0/8"},
},
})
if err != nil {
panic(err)
}
// 有効期限切れのワンタイムトークンとセッションをスイープ
defer auth.StartCleanup(context.Background(), time.Hour)()
mux := http.NewServeMux()
mux.Handle("/api/auth/", auth.Handler())
http.ListenAndServe(":8080", mux)
}
ハンドラーはプレーンなhttp.Handlerなので、chi、echo、gorilla、またはgin(gin.WrapH経由)に同じようにマウントできます。フロントエンドが異なるオリジンで実行されている場合は、auth.CORS(auth.Handler())でラップし、TrustedOriginsにそのオリジンをリストしてください。
Newは設定を検証し、安全でない状態で起動するのではなくエラーを返します。Secretの欠落/短さ、BaseURLの欠落または相対パス(Cookieのセキュリティ、信頼されたオリジン、リダイレクトターゲットを決定します)、Secure CookieなしのSameSite=none、またはTrustedProxiesなしのTrustProxyHeadersはすべて拒否されます。
デプロイメント要件:プロキシについて伝える
レート制限と記録されたすべてのセッションIPは、クライアントのアドレスを解決することに依存します。AWS ALB、nginx、Cloudflare、Kubernetesインフラストラクチャなど、このプロセスの前面で接続を終了するものが何かある場合は、それを伝える必要があります。なぜなら、両方のデフォルトは異なる方向で間違っているからです。
設定
何が起こるか
何も設定されていないが、プロキシの後ろで実行されている
すべてのリクエストはプロキシのアドレスに解決されるため、すべてのクライアントは1つのバケットを共有します。ドキュメント化された3回のサインイン/10秒という厳格なルールは、フリート全体で10秒あたり3回となり、リミッターはクローズ状態で失敗します。これは自己誘発的なダウンタイムです。
TrustProxyHeaders、TrustedProxiesなし
X-Forwarded-Forはクライアントによって供給されます。任意の呼び出し元が独自のバケットを選択するため、制限は何も制限しなくなります。
TrustProxyHeaders + TrustedProxies
正しい。フォワーディングヘッダーは、リストされたピアからのみ読み取られ、ヘッダーチェーンは信頼されたホップを右から左にウォークするため、クライアントが先頭に追加したアドレスは無視されます。
したがって:
Advanced: godevauth.AdvancedConfig{
TrustProxyHeaders: true,
// ロードバランサー/インフラストラクチャポッドのIPまたはCIDR。
TrustedProxies: []string{"10.0.0.0/8", "192.168.0.0/16"},
// または、プロバイダー固有のヘッダーの場合:
// IPAddressHeaders: []string{"CF-Connecting-IP"},
},
Newは、TrustedProxiesなしでTrustProxyHeaders(またはIPAddressHeaders)が設定されている場合、起動を拒否します。TrustedProxies: []string{"*"}を使用して任意のピアを信頼します。これは古い偽装可能な動作であり、ネットワークがサービスへの到達をプロキシがヘッダーを上書きする以外に保証しない場合にのみ安全です。反対の間違いは、トラフィックに依存するため、起動時に検出できません。プロキシヘッダーが信頼されていない状態でフォワーディングヘッダーを持つ最初のリクエストは、ヘッダーとピアの名前を付けたエラーをログに記録します。本番環境でこれを見た場合、あなたはテーブルの1行目です。直接インターネットに接続するデプロイメントでは、これらは何も必要ありません。すべて未設定のままにしてください。
ストレージアダプター
アダプター
インポート
ノート
インメモリストレージ/memory
テスト、サンプル、単一プロセス。一意性制約とインデックス付きフィールドを強制します。
SQLストレージ/sqlstore
database/sql経由のPostgreSQL、MySQL、SQLite。独自のドライバーを使用してください。
MongoDBストレージ/mongostore
公式mongo-go-driver。別のGoモジュール。
すべてのアダプターは、認証コアが依存するセマンティクス(一意性違反の報告、NULL対ゼロ、時系列ソート、句の折りたたみ、リテラルの大文字小文字を区別しない部分文字列マッチング、比較・設定更新カウント)をピン留めする同じ準拠スイート(storage/storagetest)に対して記述されています。
このリビジョンで実際に実行されたこと:
* SQLite — 完全な準拠スイートと、プッシュごとに実際のSQLiteデータベースに対して実行される完全なHTTP認証フロー。
* PostgreSQL — 本番稼働中(実際の自動化プロジェクトが実際のPostgreSQLでライブラリ全体を使用)、および準拠スイート、マイグレーションの冪等性、完全なHTTP認証フローが、プッシュごとに実際のPostgreSQLサーバーに対して実行されます。フィールドで実証済み、回帰保護済み。
* MySQL — 同じCIジョブが、プッシュごとに実際のMySQL 8サーバーに対して準拠スイート、マイグレーション、および完全な認証フローを実行します。CIで検証済み。フィールドマイレージはまだないため、ヒットしたものはすべて報告してください。
* MongoDB — 社内のワイヤープロトコルテストダブルに対して実行され、ライブのmongodではありません。ベータ版。
CIレッグは空しく通過できません。環境はREQUIRE_DSN=1を設定し、データベースの欠落はスキップではなくテストの失敗になります。
独自の Сustom アダプターを作成した場合は、そのスイートを実行してください:
func TestConformance(t *testing.T) {
storagetest.Run(t, func(t *testing.T) (storage.Adapter, func()) {
return myAdapter(storagetest.Schema()), func() {}
})
}
MongoDB
import (
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/go-dev-auth/go-dev-auth/storage/mongostore"
)
client, err := mongo.Connect(options.Client().ApplyURI(os.Getenv("MONGODB_URI")))
store := mongostore.New(clien