Quick start
This guide walks through a complete minimal app: GitHub OAuth, session cookie, and a protected route.
1. Create the auth handler
package main
import (
"log"
"net/http"
"github.com/izetmolla/goauth"
"github.com/izetmolla/goauth/providers/github"
)
func main() {
auth, err := goauth.New(goauth.Config{
Secret: []string{"replace-with-32+-byte-random-secret"},
TrustHost: true, // OK for local dev; set URL + TrustHost:false in production
Providers: []goauth.Provider{
github.New("GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET"),
},
})
if err != nil {
log.Fatal(err)
}
mux := http.NewServeMux()
mux.Handle("/auth/", auth)
mux.HandleFunc("/api/me", func(w http.ResponseWriter, r *http.Request) {
session, err := auth.GetSession(w, r)
if err != nil || session == nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"email":"` + session.User.Email + `"}`))
})
log.Println("listening on :3000 — open http://localhost:3000/auth/signin/github")
log.Fatal(http.ListenAndServe(":3000", mux))
}
2. OAuth app settings
In GitHub → Settings → Developer settings → OAuth App:
| Field | Value |
|---|---|
| Authorization callback URL | http://localhost:3000/auth/callback/github |
3. Sign in flow
sequenceDiagram
participant Browser
participant App as Your app
participant GH as GitHub
Browser->>App: GET /auth/signin/github
App->>Browser: 302 Location: github.com/authorize
Browser->>GH: User approves
GH->>Browser: 302 /auth/callback/github?code=...
Browser->>App: GET callback
App->>Browser: Set session cookie + redirect
Browser->>App: GET /api/me (cookie)
App->>Browser: 200 { email }
4. Check the session
# After sign-in, read session JSON
curl -s -b cookies.txt http://localhost:3000/auth/session | jq .
Unauthenticated requests return {}.
5. Sign out
curl -X POST -b cookies.txt http://localhost:3000/auth/signout
Advanced: database sessions + credentials
When you add an adapter, sessions are stored in the database by default (unless you use a credentials provider, which forces JWT).
import (
"database/sql"
_ "github.com/lib/pq"
"github.com/izetmolla/goauth/adapters/postgres"
"github.com/izetmolla/goauth/providers/credentials"
)
db, _ := sql.Open("postgres", dsn)
adapter := postgres.New(db)
auth, _ := goauth.New(goauth.Config{
Secret: []string{secret},
URL: "https://app.example.com",
Adapter: adapter, // tables created on New() if adapter implements Migrator
Providers: []goauth.Provider{
credentials.New(credentials.Options{
Authorize: func(ctx context.Context, creds map[string]string, r *http.Request) (*goauth.User, error) {
// validate password, return user or nil
return lookupUser(creds["email"], creds["password"])
},
}),
},
})
Sign in with POST /auth/callback/credentials and form fields email, password.
See Session strategies and Credentials for details.