Code Examples
A runnable example for every feature Cryden ships, using the public package facade.
The examples below use the public package facade of Cryden. Every call takes a context and an engine built by cryden.New. The engine ships no email, magic-link, webhook, or geolocation implementation, so a few of these examples define minimal host implementations of the relevant notify and security interfaces. Imports are shown in full in the quickstart and are representative for the rest.
Quickstart with the in-memory store
package main
import (
"context"
"os"
"github.com/crydensync/cryden/v2"
"github.com/crydensync/cryden/v2/store/memory"
)
func main() {
ctx := context.Background()
engine, err := cryden.New(cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: memory.NewUserStore(),
Sessions: memory.NewSessionStore(),
Audit: memory.NewAuditStore(),
})
if err != nil {
panic(err)
}
user, err := cryden.SignUp(ctx, engine, "proguy@example.com", "Pass@2026", "1.2.3.4")
if err != nil {
panic(err)
}
tokens, err := cryden.Login(ctx, engine, "proguy@example.com", "Pass@2026", "1.2.3.4", "some-user-agent")
if err != nil {
panic(err)
}
userID, err := cryden.VerifyToken(engine, tokens.AccessToken)
_ = user.ID
_ = userID
}Postgres
import (
"database/sql"
"os"
_ "github.com/lib/pq"
"github.com/crydensync/cryden/v2"
"github.com/crydensync/cryden/v2/store/postgres"
)
func newPostgresEngine(ctx context.Context) (*cryden.Engine, error) {
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
return nil, err
}
return cryden.New(cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: postgres.NewUserStore(db),
Sessions: postgres.NewSessionStore(db),
Audit: postgres.NewAuditStore(db),
})
}Run the migrations in store/postgres/migrations in order (0001 through 0007) before use.
SQLite
import (
"database/sql"
"os"
_ "modernc.org/sqlite"
"github.com/crydensync/cryden/v2"
"github.com/crydensync/cryden/v2/store/sqlite"
)
func newSQLiteEngine(ctx context.Context) (*cryden.Engine, error) {
db, err := sql.Open("sqlite", "file:auth.db?_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)")
if err != nil {
return nil, err
}
if err := sqlite.Migrate(ctx, db); err != nil {
return nil, err
}
if err := sqlite.CheckPragmas(ctx, db); err != nil {
return nil, err
}
return cryden.New(cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: sqlite.NewUserStore(db),
Sessions: sqlite.NewSessionStore(db),
Audit: sqlite.NewAuditStore(db),
})
}Refresh tokens and reading claims
tokens, err := cryden.RefreshToken(ctx, engine, tokens.RefreshToken)
if err != nil {
panic(err)
}
userID, claims, err := cryden.VerifyTokenWithClaims(engine, tokens.AccessToken)
_ = userID
_ = claimsSessions
userID := "user-123"
sessions, err := cryden.ListSessions(ctx, engine, userID)
public, err := cryden.ListPublicSessions(ctx, engine, userID)
named, err := cryden.ListNamedSessions(ctx, engine, userID)
for _, s := range named {
fmt.Println(s.Label)
}
err = cryden.RevokeSession(ctx, engine, sessions[0].ID, userID)
err = cryden.Logout(ctx, engine, sessions[0].ID, userID)
err = cryden.LogoutAll(ctx, engine, userID)Named sessions with a geolocator
type geolocator struct{}
func (geolocator) Locate(ctx context.Context, ip string) (security.Location, error) {
return security.Location{City: "San Francisco", Region: "CA"}, nil
}
cfg := cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: memory.NewUserStore(),
Sessions: memory.NewSessionStore(),
Audit: memory.NewAuditStore(),
Geolocator: geolocator{},
}
engine, err := cryden.New(cfg)Account management
err := cryden.ChangePassword(ctx, engine, userID, "Pass@2026", "New-Pass@2026")
err = cryden.DeleteAccount(ctx, engine, userID, "New-Pass@2026")
user, err := cryden.GetUser(ctx, engine, "proguy@example.com")Email change
type emailSender struct{}
func (emailSender) SendVerification(ctx context.Context, to, rawToken string) error {
link := "https://yourapp.com/verify?token=" + url.QueryEscape(rawToken)
fmt.Printf("email to %s: %s\n", to, link)
return nil
}
engine, err := cryden.New(cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: memory.NewUserStore(),
Sessions: memory.NewSessionStore(),
Audit: memory.NewAuditStore(),
Verifications: memory.NewVerificationStore(),
EmailSender: emailSender{},
})
err = cryden.RequestEmailChange(ctx, engine, userID, "new@example.com")
err = cryden.ConfirmEmailChange(ctx, engine, rawTokenFromTheLink)OAuth login and linking
tokens, err := cryden.LoginWithOAuth(ctx, engine, "google", externalID, email, ip, agent)
// doubles as signup when no account matches yet
var conflict *auth.ErrOAuthEmailConflict
if errors.As(err, &conflict) {
// the email matches an existing password account that is not linked yet;
// have the user log in with the password, then link explicitly
if err := cryden.LinkOAuthIdentity(ctx, engine, userID, "google", externalID, email, ip); err != nil {
panic(err)
}
}TOTP enrollment
otpauthURL, err := cryden.EnrollTOTP(ctx, engine, userID)
// render otpauthURL as a QR code for the user to scan
err = cryden.ConfirmTOTP(ctx, engine, userID, codeFromTheApp)
// only after ConfirmTOTP succeeds does the account require a code
tokens, err := cryden.Login(ctx, engine, email, password, ip, agent)
var secondFactor *auth.ErrSecondFactorRequired
if errors.As(err, &secondFactor) {
fmt.Println("enrolled methods:", secondFactor.Methods)
tokens, err = cryden.CompleteLoginWithTOTP(ctx, engine, secondFactor.PendingToken, codeFromTheApp, ip, agent)
}
err = cryden.DisableTOTP(ctx, engine, userID, password)Passkeys (WebAuthn)
optionsJSON, ceremonyToken, err := cryden.BeginRegisterPasskey(ctx, engine, userID)
// forward optionsJSON to navigator.credentials.create()
err = cryden.FinishRegisterPasskey(ctx, engine, userID, ceremonyToken, clientResponseJSON, "MacBook Touch ID")
passkeys, err := cryden.ListPasskeys(ctx, engine, userID)
err = cryden.DeletePasskey(ctx, engine, userID, passkeys[0].CredentialID, password)Sign in with a passkey as the second factor:
assertionJSON, ceremonyToken, err := cryden.BeginWebAuthnLogin(ctx, engine, secondFactor.PendingToken)
// forward assertionJSON to navigator.credentials.get()
tokens, err = cryden.CompleteLoginWithWebAuthn(ctx, engine, secondFactor.PendingToken, ceremonyToken, clientResponseJSON, ip, agent)Magic-link login
type magicLinkSender struct{}
func (magicLinkSender) SendMagicLink(ctx context.Context, to, rawToken string) error {
link := "https://yourapp.com/login?token=" + url.QueryEscape(rawToken)
fmt.Printf("magic link for %s: %s\n", to, link)
return nil
}
engine, err := cryden.New(cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: memory.NewUserStore(),
Sessions: memory.NewSessionStore(),
Audit: memory.NewAuditStore(),
Verifications: memory.NewVerificationStore(),
MagicLinkSender: magicLinkSender{},
})
err = cryden.RequestMagicLink(ctx, engine, "proguy@example.com", ip)
// nil even when the email does not exist, to avoid leaking registrations
tokens, err = cryden.CompleteMagicLink(ctx, engine, rawTokenFromTheLink, ip, agent)Recovery codes
codes, err := cryden.GenerateRecoveryCodes(ctx, engine, userID)
// show the codes exactly once; only their hashes are stored
tokens, err = cryden.CompleteLoginWithRecoveryCode(ctx, engine, secondFactor.PendingToken, codes[0], ip, agent)API keys
rawKey, key, err := cryden.GenerateAPIKey(ctx, engine, userID, "CI deploy bot", []string{"read", "deploy"}, 0)
// ttl 0 means the key never expires; show rawKey exactly once
identity, err := cryden.AuthenticateAPIKey(ctx, engine, rawKey)
if identity.HasScope("deploy") {
// allow the machine to deploy
}
keys, err := cryden.ListAPIKeys(ctx, engine, userID)
err = cryden.RevokeAPIKey(ctx, engine, userID, key.ID)Custom access token claims
import "github.com/crydensync/cryden/v2/token"
cfg.AccessTokenClaims = token.ClaimsFunc(func(ctx context.Context, userID string) (map[string]any, error) {
return map[string]any{"role": "admin", "tenant_id": "acme"}, nil
})
userID, claims, err := cryden.VerifyTokenWithClaims(engine, tokens.AccessToken)
fmt.Println(claims["role"])Webhooks
type webhookSender struct{}
func (webhookSender) SendWebhook(ctx context.Context, event notify.WebhookEvent) error {
fmt.Printf("event %s: type=%s user=%s\n", event.ID, event.Type, event.UserID)
return nil
}
cfg.Webhooks = webhookSender{}
cfg.WebhookEvents = append(cryden.DefaultWebhookEvents(), store.EventLoginSuccess)Weekly digest
text, err := cryden.WeeklyDigest(ctx, engine)
fmt.Println(text)
since := time.Now().Add(-24 * time.Hour)
text, err = cryden.DigestSince(ctx, engine, since)
fmt.Println(text)Support-ticket assistant
text, err := cryden.DiagnoseLoginIssue(ctx, engine, "proguy@example.com")
fmt.Println(text)Config tuning advisor
text, err := cryden.ConfigTuningReport(ctx, engine)
fmt.Println(text)
since = time.Now().Add(-7 * 24 * time.Hour)
text, err = cryden.TuningReportSince(ctx, engine, since)
fmt.Println(text)Ask-AI widget
import "github.com/crydensync/cryden/v2/ai"
import "github.com/crydensync/cryden/v2/widget"
answer, err := widget.Ask(ctx, widget.Config{
Provider: myLLMProvider,
Store: myQueryableStore,
}, currentUserID, "what sessions do I have open?")
fmt.Println(answer.Text)myLLMProvider implements ai.LLMProvider, which parses natural language into an ai.QueryIntent. myQueryableStore implements ai.QueryableStore against a read-only database role. currentUserID must come from the host's own authentication, never from the question; every parsed query is force-scoped to it before validation, so a prompt injection cannot make the query read another user's rows.
Advanced configuration
import (
"github.com/redis/go-redis/v9"
"github.com/crydensync/cryden/v2/security"
)
hasher, err := security.NewArgon2idHasher(security.DefaultArgon2idParams)
redisClient := redis.NewClient(&redis.Options{Addr: os.Getenv("REDIS_ADDR")})
limiter, err := security.NewRedisRateLimiter(redisClient, 100, time.Minute)
engine, err := cryden.New(cryden.Config{
JWTSecret: os.Getenv("JWT_SECRET"),
Users: postgres.NewUserStore(db),
Sessions: postgres.NewSessionStore(db),
Audit: postgres.NewAuditStore(db),
Hasher: hasher,
RateLimiter: limiter,
Anomalies: postgres.NewAnomalyStore(db),
PasswordPolicy: security.PasswordPolicy{MinLength: 12, RequireUppercase: true},
})The zero-valued PasswordPolicy applies security.DefaultPasswordPolicy, and the same convention applies to AnomalyThresholds and CredentialStuffingThresholds. Detection features are report-only and never block a login.
Logging toolkit
import "github.com/crydensync/cryden/v2/logger"
cfg.Logger = logger.NewMultiLogger(
logger.NewConsoleJSONLogger(),
logger.NewLevelFilter(
logger.NewMaskingRedactor(vendorSink),
logger.LevelInfo,
),
)Full detail stays on stdout while a redacted, level-filtered copy leaves the infrastructure.