Skip to main content

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:

FieldValue
Authorization callback URLhttp://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.