SDKsGo SDKGuides
HTTP Middleware
Build authentication and authorization middleware for Go HTTP servers using the Go SDK.
HTTP Middleware
Protect your Go HTTP APIs with authentication and authorization middleware.
Token validation middleware
package middleware
import (
"context"
"net/http"
"strings"
avnologyid "github.com/avnology/sdk-go"
)
type contextKey string
const (
UserIDKey contextKey = "userID"
ScopesKey contextKey = "scopes"
OrgIDKey contextKey = "orgID"
)
func RequireAuth(client *avnologyid.Client) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if !strings.HasPrefix(authHeader, "Bearer ") {
http.Error(w, `{"error":"missing_token"}`, http.StatusUnauthorized)
return
}
token := strings.TrimPrefix(authHeader, "Bearer ")
result, err := client.OAuth.IntrospectToken(r.Context(), &avnologyid.IntrospectTokenParams{
Token: token,
})
if err != nil || !result.Active {
http.Error(w, `{"error":"invalid_token"}`, http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), UserIDKey, result.Sub)
ctx = context.WithValue(ctx, ScopesKey, strings.Split(result.Scope, " "))
if result.OrgID != "" {
ctx = context.WithValue(ctx, OrgIDKey, result.OrgID)
}
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}Scope checking middleware
func RequireScope(scopes ...string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userScopes, _ := r.Context().Value(ScopesKey).([]string)
scopeSet := make(map[string]bool, len(userScopes))
for _, s := range userScopes {
scopeSet[s] = true
}
for _, required := range scopes {
if !scopeSet[required] {
http.Error(w, `{"error":"insufficient_scope"}`, http.StatusForbidden)
return
}
}
next.ServeHTTP(w, r)
})
}
}Permission checking middleware
func RequirePermission(client *avnologyid.Client, relation string, objectFn func(*http.Request) string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userID, _ := r.Context().Value(UserIDKey).(string)
object := objectFn(r)
allowed, err := client.Permissions.Check(r.Context(), &avnologyid.CheckPermissionParams{
Subject: "user:" + userID,
Relation: relation,
Object: object,
})
if err != nil || !allowed {
http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
}Composing middleware with net/http
mux := http.NewServeMux()
// Public routes
mux.HandleFunc("GET /health", healthHandler)
// Protected routes
authMux := http.NewServeMux()
authMux.HandleFunc("GET /api/profile", profileHandler)
authMux.HandleFunc("GET /api/projects/{id}", projectHandler)
mux.Handle("/api/", RequireAuth(client)(authMux))See also
- gRPC interceptors -- gRPC integration
- Testing -- Testing middleware