AnnouncementsIntroducing Arkoren

    Menu

    Authentication Overview

    Resolve credentials into your application's identity and choose which routes require it.

    What's on this page
    1. Use one application-owned identity type and reject invalid accounts before publishing it.
    2. Combine authenticators deliberately and distinguish optional identity from required access.
    3. Read the request identity and customize anonymous rejections without exposing sensitive diagnostics.
    On this page

    Authentication establishes who sent a request. Arkoren resolves a session or bearer credential into a Go value that your application owns; it supplies no user table, registration flow, or login screen. Authorization then decides what that identity may do.

    Use Session Login for passwords and browser sessions, API Tokens for application-issued keys, OAuth Login for external browser sign-in, or OIDC Tokens for provider-issued JWTs. All four use the same request identity model.

    Focused snippets keep error results visible but omit routine propagation. Checks remain where failure changes authentication or access. Handle all errors in your application.

    Define Identity

    Choose one identity type for handlers and policies. An invoice application might use this local account value:

    type User struct {
    	ID       int
    	Name     string
    	Disabled bool
    }

    No field or interface is required by Arkoren. Your verifier or loader must reject unknown and disabled accounts before returning success. Returning User{}, nil still authenticates a request; auth.Require checks presence, not whether fields are nonzero. The same applies to a typed nil pointer returned without an error.

    Identity lookup uses the exact Go type. User, *User, and a separately defined type with identical fields are different identities; Arkoren does not convert between them.

    Resolve Credentials

    An authenticator is a func(*http.Request) (User, error) that verifies credentials and returns your identity. Import auth from arkoren.dev/core/http/auth. Its result controls whether another authenticator can try:

    Result Middleware behavior
    User and nil error Store that user and stop trying authenticators.
    auth.ErrNoCredentials, including wrapped errors Try the next authenticator.
    Any other error Stop the request without calling its handler.

    Return ErrNoCredentials only when the request has no credentials that this authenticator handles. A presented invalid bearer token must return a different error. Do not trust a client-supplied user ID or header as proof of identity.

    For routes accepting both browser sessions and API keys, use your existing loadUser (func(context.Context, int) (User, error)) and verifyToken (func(context.Context, string) (User, error)):

    identity := auth.NewSessionIdentity(loadUser)
    r.Use(auth.Middleware(
    	identity.Authenticator(),
    	auth.Bearer(verifyToken),
    ))

    Here r is your existing router. This browser group already needs session and CSRF middleware before authentication. The first success wins: a valid session in this order prevents inspection of a simultaneously supplied bearer header. An error stops the chain; it does not trigger fallback. Prefer separate browser and API groups when they need different credential policies.

    Choose Route Access

    Authentication middleware permits anonymous requests when every authenticator returns ErrNoCredentials. This lets public pages optionally personalize their response. To require a user for private routes, add auth.Require after the authentication middleware:

    private := r.With(auth.Require[User]())
    private.Get("/invoices", listInvoices)

    listInvoices is your existing handler. An anonymous request receives a 401 Problem Details response with WWW-Authenticate: Bearer; an authenticated request reaches the handler. This proves identity presence, not permission to read every invoice. Apply your authorization rules separately.

    For browser pages, a 401 does not display a login form. If you want a login redirect, write middleware that checks auth.FromContext[User] and redirects to a fixed local login path. Validate any return target rather than redirecting to an arbitrary request parameter. See middleware scope for applying different behavior to different route groups.

    Read Identity

    Handlers retrieve the exact type stored by authentication. With request and response from their arkoren.dev/core/http/ packages and standard-library net/http, read the local user before returning a profile:

    user, err := request.User[User](r)
    if err != nil {
    	return err
    }
    
    return response.JSON(w, http.StatusOK, user)

    w and r are the handler’s response writer and request. Missing identities return auth.ErrUnauthenticated, including when a different identity type is present. In context-only code, auth.FromContext[User](ctx) returns the value and a presence boolean instead.

    Tests can use auth.NewContext(ctx, User{ID: 42}) without performing a login. That helper trusts the supplied value; keep it in trusted code, not in a path that copies unverified request input. Auth Tests also covers testing the actual authenticators.

    Handle Rejections

    To change the anonymous response, configure auth.Builder.ErrorResponse in auth.Require[User](...). It replaces the whole problem and its headers, so include the appropriate authentication challenge if you keep status 401. A zero response restores the default. This setting does not change the error returned by request.User or failures returned by an authenticator.

    If you need anonymous-rejection events, supply your existing event bus:

    private := r.With(auth.Require[User](func(required *auth.Builder) {
    	required.Events(app.Events())
    }))

    Every rejection publishes http.auth.rejected, even with a custom status. Its payload contains Method, not a request path, identity, query, or cause. HTTP methods and event context values can still be untrusted or sensitive; normal Problem Details rendering can include the request path as instance. Keep listeners cheap and apply rate limiting before the required-user middleware when needed. No event bus means no event.

    For all functions and options, see the auth API reference.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive