Documentation
¶
Overview ¶
Package auth authenticates HTTP requests and carries the caller's identity on the request context.
JWTManager issues and validates this package's own tokens, but the middleware is written against the IdentityProvider interface, so a service that authenticates against an IAM service or an opaque session store reuses the same middleware and helpers with its own resolver.
Index ¶
- Constants
- func Authenticate(provider IdentityProvider) func(http.Handler) http.Handler
- func BearerToken(r *http.Request) (string, bool)
- func GetUserFromContext(ctx context.Context) (string, []string, bool)deprecated
- func RequireRole(role string) func(http.Handler) http.Handler
- func Roles(ctx context.Context) ([]string, bool)
- func SetUserContext(ctx context.Context, userID string, roles []string) context.Contextdeprecated
- func UserID(ctx context.Context) (string, bool)
- func WithIdentity(ctx context.Context, identity Identity) context.Context
- type Claims
- type ContextKeydeprecated
- type Identity
- type IdentityProvider
- type IdentityProviderFunc
- type JWTManager
Examples ¶
Constants ¶
const AdminRole = "admin"
AdminRole is the role that satisfies every RequireRole check.
Variables ¶
This section is empty.
Functions ¶
func Authenticate ¶
func Authenticate(provider IdentityProvider) func(http.Handler) http.Handler
Authenticate returns a middleware that resolves the request's bearer token through provider and publishes the resulting Identity on the request context. Requests without a usable token, or whose token the provider rejects, are answered 401 and never reach the handler.
Example ¶
The middleware authenticates a bearer token and publishes the caller on the request context, where handlers read it through a typed accessor.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"time"
"github.com/dobrevit/svckit/auth"
)
func main() {
manager := auth.NewJWTManager("a-signing-secret", time.Hour)
token, _ := manager.GenerateToken("u-1", []string{"editor"})
handler := auth.Authenticate(manager)(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
id, _ := auth.UserID(r.Context())
fmt.Println("authenticated:", id)
}))
r := httptest.NewRequest(http.MethodGet, "/orders", nil)
r.Header.Set("Authorization", "Bearer "+token)
handler.ServeHTTP(httptest.NewRecorder(), r)
}
Output: authenticated: u-1
func BearerToken ¶
BearerToken returns the token from r's Authorization header, and whether the header carried a bearer token at all.
func RequireRole ¶
RequireRole returns a middleware that rejects an authenticated caller lacking role. AdminRole satisfies every check. It must run after Authenticate.
Types ¶
type Claims ¶
type Claims struct {
UserID string `json:"user_id"`
Roles []string `json:"roles"`
jwt.RegisteredClaims
}
Claims represents the JWT claims
type ContextKey
deprecated
type ContextKey string
ContextKey is the legacy string key type used by SetUserContext.
Deprecated: use WithIdentity and IdentityFromContext, which use an unexported key type that cannot collide with keys set by other packages.
const ( UserIDContextKey ContextKey = "user_id" RolesContextKey ContextKey = "roles" )
Legacy context keys.
Deprecated: see ContextKey.
type Identity ¶
Identity is the authenticated caller a middleware publishes on the request context.
func IdentityFromContext ¶
IdentityFromContext returns the identity carried by ctx, if any.
type IdentityProvider ¶
IdentityProvider turns a bearer token into an Identity, or reports why it could not. Implementing it lets a service authenticate against something other than this package's JWTs — an IAM service, an opaque session store — while reusing the middleware and helpers here.
type IdentityProviderFunc ¶
IdentityProviderFunc adapts a function to IdentityProvider.
Example ¶
A service that authenticates against something other than this package's JWTs supplies its own IdentityProvider and keeps the same middleware.
package main
import (
"context"
"errors"
"fmt"
"net/http"
"net/http/httptest"
"github.com/dobrevit/svckit/auth"
)
func main() {
sessions := map[string]string{"session-abc": "u-9"}
provider := auth.IdentityProviderFunc(
func(_ context.Context, token string) (auth.Identity, error) {
userID, ok := sessions[token]
if !ok {
return auth.Identity{}, errors.New("unknown session")
}
return auth.Identity{UserID: userID, Roles: []string{"viewer"}}, nil
})
handler := auth.Authenticate(provider)(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
id, _ := auth.UserID(r.Context())
fmt.Println("authenticated:", id)
}))
r := httptest.NewRequest(http.MethodGet, "/orders", nil)
r.Header.Set("Authorization", "Bearer session-abc")
handler.ServeHTTP(httptest.NewRecorder(), r)
}
Output: authenticated: u-9
type JWTManager ¶
type JWTManager struct {
// contains filtered or unexported fields
}
JWTManager handles JWT token operations
func NewJWTManager ¶
func NewJWTManager(secretKey string, expiry time.Duration) *JWTManager
NewJWTManager creates a new JWT manager
func (*JWTManager) GenerateToken ¶
func (j *JWTManager) GenerateToken(userID string, roles []string) (string, error)
GenerateToken generates a JWT token for the given user
func (*JWTManager) ValidateToken ¶
func (j *JWTManager) ValidateToken(tokenString string) (*Claims, error)
ValidateToken validates and parses a JWT token