Server API
Configure the AuthInGo Go engine, mount email-password auth routes, and protect handlers with sessions.
Server API
The Go package is the source of truth for authentication. It owns user creation, password checks, session creation, cookies, and route protection.
Create an Auth instance
authingo.New requires a Store. The built-in PostgreSQL adapter is the quickest path.
db, err := sql.Open("pgx", os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}
auth := authingo.New(authingo.Options{
Store: postgres.NewAdapter(db),
})AuthInGo defaults to secure, host-only cookies: SameSite=Lax for the access
session cookie and SameSite=Strict for the refresh cookie. Embedded demos or
other truly cross-site deployments can override this explicitly:
secure := true
auth := authingo.New(authingo.Options{
Store: postgres.NewAdapter(db),
Cookies: authingo.CookieOptions{
Secure: &secure,
SessionSameSite: http.SameSiteNoneMode,
RefreshSameSite: http.SameSiteNoneMode,
},
})Mount built-in routes
Mount the handler anywhere in your app. Most examples use /api/auth.
mux := http.NewServeMux()
mux.Handle("/api/auth/", http.StripPrefix("/api/auth", auth.Handler()))This exposes:
| Method | Path | Body | Response |
|---|---|---|---|
POST | /sign-up | { "email": string, "password": string, "name": string } | { "user": User } |
POST | /sign-in | { "email": string, "password": string } | { "user": User } |
GET | /session | none | { "user": User, "session": Session } |
POST | /refresh | none | { "user": User } |
POST | /sign-out | none | { "success": true } |
All built-in POST routes require X-Authingo-Client: true. The React SDK
adds this header automatically.
Protect routes
Wrap private handlers with RequireAuth.
mux.Handle("/api/me", auth.RequireAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(authingo.UserContextKey).(*authingo.User)
if !ok {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{
"user": user,
})
})))Protected requests must include:
X-Authingo-Client: trueWhy the extra header?
Cookies are sent automatically by browsers. The X-Authingo-Client header gives your server a simple additional signal that the request came from code intentionally using AuthInGo.
CORS for a separate frontend
If your frontend and backend run on different origins, allow credentials and the AuthInGo header.
func cors(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, X-Authingo-Client")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}Full example
Connect storage
db, err := sql.Open("pgx", os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}Initialize AuthInGo
auth := authingo.New(authingo.Options{
Store: postgres.NewAdapter(db),
})Mount public and private routes
mux := http.NewServeMux()
mux.Handle("/api/auth/", http.StripPrefix("/api/auth", auth.Handler()))
mux.Handle("/api/me", auth.RequireAuth(http.HandlerFunc(meHandler)))Session cleanup
authingo.New starts a daily cleanup loop and calls Store.CleanupExpiredSessions with a short timeout. The PostgreSQL adapter deletes expired sessions in bounded batches and session lookups only authenticate rows where both expires_at and refresh_expires_at are still in the future.