Authentication library for Go: Argon2id password hashing, EdDSA access and refresh tokens with rotation, opaque API keys, TOTP, OIDC and OAuth2 social login, and email and username validation. It runs in your process and needs no database or framework.
flowchart LR
App["Your app"] -->|init once| Core["authcore"]
Core -->|loads or generates| Keys[("Ed25519 key + HMAC secret<br/>in KeysDir")]
Core -->|Provider| M["password, jwt, apikey, oauth,<br/>email, username, totp,<br/>credential, field"]
M -->|hash, sign, verify| App
authcore ships no HTTP server of its own; you wire the modules into your own stack.
Each module is an independent package that takes the Provider and is usable on its own.
| Module | Does | |
|---|---|---|
| 🔑 | password | Hash + verify. Argon2id, policy-enforced, self-describing PHC format. |
| 🎫 | jwt | Access + refresh tokens. EdDSA / Ed25519, generic claims, refresh rotation, optional revocation through a denylist you implement. |
| 📧 | Validate + normalize. RFC 5321/5322, optional cached DNS MX check. | |
| 👤 | username | Validate + normalize. Reserved-name blocklist, character rules. |
| 🗝️ | apikey | Opaque API keys. Generate, keyed-hash for storage, constant-time verify. |
| 🔐 | totp | TOTP / RFC 6238 second factor. Enroll, verify, recovery codes; replay protection through a step recorder you implement. |
| ✉️ | credential | Tokens for password reset and account activation. Bound to a purpose and a subject, TTL enforced; your store makes them single-use. |
| 🛡️ | field | Column encryption. AES-256-GCM plus an HMAC blind index, so a value stays searchable by equality without being readable. |
| 🌐 | oauth | Social login: Google, Apple, Microsoft, Vercel (OIDC) and GitHub, Discord (OAuth2). Auth Code + PKCE, ID-token validation or userinfo. |
go get github.com/Glyndor/authcoreRequires Go 1.26.9+. On first run authcore writes an Ed25519 signing key and an HMAC refresh secret to KeysDir (default .authcore/); in production, point it at a mounted volume or provision the keys once with authcore-keygen. See Key management and Containers.
// One-time setup at startup. Keys are created on first run.
auth, _ := authcore.New(authcore.DefaultConfig())
pwd, _ := password.New(auth) // Argon2id, OWASP defaults
tokens, _ := jwt.New[UserClaims](auth, jwt.DefaultConfig())
// Register: store only the hash, never the plaintext.
hash, err := pwd.Hash("Str0ng-P@ssword!") // errors.Is(err, password.ErrWeakPassword) on a policy failure
// Log in: verify, then mint an access + refresh pair.
if ok, _ := pwd.Verify("Str0ng-P@ssword!", hash); ok {
pair, _ := tokens.CreateTokens(userID, UserClaims{Role: "admin"})
// pair.AccessToken → Authorization: Bearer …
// pair.RefreshTokenHash → store server-side (never the raw token)
// pair.SessionID → UUID v7, use as your session PK
}Tip
Full, runnable versions live in examples/: cd examples/jwt && go run ..
Wiring into a real HTTP stack: Fiber, Gin.
| Provider | Protocol | Build it with |
|---|---|---|
| OIDC | oauth.Google() |
|
| Apple | OIDC | oauth.Apple() with oauth.AppleClientSecret |
| Microsoft (Azure AD) | OIDC | oauth.Microsoft(tenantID), or a multi-tenant Provider |
| GitHub | OAuth2 | oauth.GitHub() |
| Discord | OAuth2 | oauth.Discord() |
| Vercel | OIDC | oauth.Vercel() |
| Any other OIDC provider (Okta, Auth0, GitLab, Keycloak, …) | OIDC | oauth.Discover(ctx, issuer, nil) |
Plain OAuth2 providers without OIDC take a hand-built Provider; see OIDC login.
| Group | Links |
|---|---|
| Start here | Secure login recipe, Configuration, FAQ |
| Operations | Key management, Containers, Testing & modules, Migrating from bcrypt |
| Reference | Errors, Versioning, pkg.go.dev |
MIT. Report vulnerabilities privately via the Security tab, never in a public issue.