Help us shape the future of Go! Take the 2026 Go Developer Survey

auth

package
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package auth implements authentication: GitHub sign-in handlers, cookie sessions, and middleware that guards API routes, plus an OAuth 2.1 authorization server that lets agents (MCP clients) act for a signed-in user with bearer tokens.

Auth stores sessions, clients, and tokens through the small Store interface and reaches GitHub through OAuth, so neither storage nor the GitHub client is imported here beyond the github.User type.

Index

Constants

View Source
const ScopeRead = "read"

ScopeRead is the scope that grants read-only access to the MCP server.

Variables

View Source
var ErrReplayed = errors.New("auth: oauth credential replayed")

ErrReplayed is returned by an OAuthStore when an authorization code or a rotated refresh token is presented again. The store has revoked the grant by then.

Functions

func ScopesFrom

func ScopesFrom(ctx context.Context) []string

ScopesFrom returns the scopes of the access token that Auth.RequireBearer accepted for ctx.

Types

type Auth

type Auth struct {
	// contains filtered or unexported fields
}

Auth serves the sign-in endpoints and guards routes behind a session.

func New

func New(store Store, oauth func() (OAuth, bool), baseURL string, allowedUsers []string, log *slog.Logger) *Auth

New returns an Auth that keeps sessions in store. oauth reports the GitHub client, or false until the GitHub App has been configured. baseURL is the public dashboard URL; cookies are marked Secure when it is https. allowedUsers are the GitHub logins permitted to sign in, compared without regard to case.

func (*Auth) AuthorizationRequest

func (a *Auth) AuthorizationRequest(w http.ResponseWriter, r *http.Request)

AuthorizationRequest returns a pending authorization request of the signed-in user, for the consent page.

func (*Auth) AuthorizationServerMetadata

func (a *Auth) AuthorizationServerMetadata(w http.ResponseWriter, r *http.Request)

AuthorizationServerMetadata serves the RFC 8414 authorization server metadata.

func (*Auth) Authorize

func (a *Auth) Authorize(w http.ResponseWriter, r *http.Request)

Authorize starts an authorization: it validates the request, sends a user without a session to sign in first, and otherwise hands the request to the dashboard's consent page. Invalid requests get an error page, never a redirect to the client.

func (*Auth) Callback

func (a *Auth) Callback(w http.ResponseWriter, r *http.Request)

Callback completes GitHub sign-in. If the user is permitted it creates a session and redirects to the dashboard; otherwise it redirects to the login page with an error.

func (*Auth) DecideAuthorization

func (a *Auth) DecideAuthorization(w http.ResponseWriter, r *http.Request)

DecideAuthorization approves or denies a pending authorization request of the signed-in user and returns where to send the browser: the client's redirect URI with an authorization code or an access_denied error. A request can be decided once.

func (*Auth) Grants

func (a *Auth) Grants(w http.ResponseWriter, r *http.Request)

Grants lists the signed-in user's connected clients.

func (*Auth) Login

func (a *Auth) Login(w http.ResponseWriter, r *http.Request)

Login starts GitHub sign-in: it sets a short-lived state cookie and redirects to GitHub. A next query parameter holding a path on this server is where Callback sends the user after signing in; anything else is ignored.

func (*Auth) Logout

func (a *Auth) Logout(w http.ResponseWriter, r *http.Request)

Logout ends the current session.

func (*Auth) ProtectedResourceMetadata

func (a *Auth) ProtectedResourceMetadata(w http.ResponseWriter, r *http.Request)

ProtectedResourceMetadata serves the RFC 9728 metadata of the MCP endpoint.

func (*Auth) Register

func (a *Auth) Register(w http.ResponseWriter, r *http.Request)

Register implements RFC 7591 dynamic client registration for public clients.

func (*Auth) Require

func (a *Auth) Require(next http.Handler) http.Handler

Require returns a handler that serves next only for requests with a valid session, making the user available through UserFrom. Other requests get a 401 JSON error.

func (*Auth) RequireBearer

func (a *Auth) RequireBearer(resource string) func(http.Handler) http.Handler

RequireBearer returns middleware that serves next only for requests with an OAuth access token, in the Authorization header, that was issued for resource and belongs to a permitted user. It makes the user available through UserFrom and the token's scopes through ScopesFrom. Cookies are ignored. Other requests get a 401 whose WWW-Authenticate header points clients at the resource's metadata.

func (*Auth) Resource

func (a *Auth) Resource() string

Resource returns the URL of the resource that bearer tokens are issued for: the MCP endpoint.

func (*Auth) Revoke

func (a *Auth) Revoke(w http.ResponseWriter, r *http.Request)

Revoke implements RFC 7009 token revocation. Revoking an access or refresh token revokes its whole grant.

func (*Auth) RevokeDisallowedSessions

func (a *Auth) RevokeDisallowedSessions(ctx context.Context) error

RevokeDisallowedSessions permanently invalidates the sessions and OAuth grants of removed users, and removes expired OAuth codes and tokens. Call it on startup after loading the access policy.

func (*Auth) RevokeGrant

func (a *Auth) RevokeGrant(w http.ResponseWriter, r *http.Request)

RevokeGrant revokes one of the signed-in user's grants and all its tokens.

func (*Auth) Token

func (a *Auth) Token(w http.ResponseWriter, r *http.Request)

Token implements the token endpoint for the authorization_code and refresh_token grants.

type Client

type Client struct {
	ID           string
	Name         string
	URI          string
	RedirectURIs []string
	CreatedAt    time.Time
}

Client is an OAuth client registered through dynamic client registration. Every client is public: it has no secret.

type Code

type Code struct {
	Hash        string
	ClientID    string
	GitHubID    int64
	RedirectURI string
	Challenge   string // PKCE S256 code challenge
	Scope       string
	Resource    string
	ExpiresAt   time.Time
}

Code is an authorization code, keyed by the hash of its value.

type Grant

type Grant struct {
	ID          string
	ClientID    string
	ClientName  string
	GitHubID    int64
	RedirectURI string
	Scope       string // space-separated
	Resource    string // audience of its access tokens
	CreatedAt   time.Time
	LastUsedAt  *time.Time
}

Grant is an approved authorization: a user let a client act for them.

type OAuth

type OAuth interface {
	// AuthorizeURL returns the GitHub page that asks the user to sign in.
	AuthorizeURL(redirectURL, state string) string
	// ExchangeUser trades an authorization code for the signed-in user.
	ExchangeUser(ctx context.Context, code, redirectURL string) (github.User, error)
}

OAuth performs the GitHub sign-in handshake. *github.Client implements it.

type OAuthStore

type OAuthStore interface {
	// CreateClient stores a client and returns it with its ID and creation
	// time.
	CreateClient(ctx context.Context, c Client) (Client, error)
	// Client returns a registered client, and whether it exists.
	Client(ctx context.Context, id string) (Client, bool, error)
	// CountClients returns the number of registered clients.
	CountClients(ctx context.Context) (int, error)
	// CreateCode stores an authorization code.
	CreateCode(ctx context.Context, c Code) error
	// RedeemCode spends the unexpired code with the given hash. issue
	// validates it and returns the grant and tokens to create; its error is
	// returned and the code is spent anyway. It reports false if the code is
	// unknown or expired. Redeeming a code twice revokes the grant it
	// produced and returns ErrReplayed.
	RedeemCode(ctx context.Context, hash string, issue func(Code) (Grant, []Token, error)) (Grant, bool, error)
	// RotateRefreshToken spends the unexpired refresh token with the given
	// hash. issue validates its grant and user and returns the tokens that
	// replace it; if it fails, nothing changes. It reports false if the
	// token is unknown or expired. Presenting a rotated token revokes its
	// grant and returns ErrReplayed.
	RotateRefreshToken(ctx context.Context, hash string, issue func(Grant, User) ([]Token, error)) (Grant, bool, error)
	// AccessToken returns the grant and user of an unexpired access token,
	// and whether it exists.
	AccessToken(ctx context.Context, hash string) (Grant, User, bool, error)
	// TouchGrant records that a grant was used at the given time.
	TouchGrant(ctx context.Context, id string, at time.Time) error
	// Grants returns a user's live grants, newest first.
	Grants(ctx context.Context, githubID int64) ([]Grant, error)
	// DeleteGrant revokes a user's grant, reporting whether it existed.
	DeleteGrant(ctx context.Context, id string, githubID int64) (bool, error)
	// RevokeToken revokes the grant of a token, if the token was issued to
	// clientID or clientID is empty.
	RevokeToken(ctx context.Context, hash, clientID string) error
	// DeleteExpiredOAuth removes expired codes and tokens, dead grants, and
	// clients created before staleBefore that were never used.
	DeleteExpiredOAuth(ctx context.Context, staleBefore time.Time) error
	// DeleteDisallowedGrants revokes grants and codes of logins outside
	// allowed.
	DeleteDisallowedGrants(ctx context.Context, allowed []string) error
}

OAuthStore persists OAuth clients, codes, grants, and tokens.

type Store

type Store interface {
	// UpsertUser creates the user or updates its profile.
	UpsertUser(ctx context.Context, u User) error
	// CreateSession stores a session that expires at the given time.
	CreateSession(ctx context.Context, tokenHash string, githubID int64, expires time.Time) error
	// SessionUser returns the user of an unexpired session, and whether the
	// session exists.
	SessionUser(ctx context.Context, tokenHash string) (User, bool, error)
	// DeleteSession removes a session.
	DeleteSession(ctx context.Context, tokenHash string) error
	// DeleteDisallowedSessions removes sessions for logins outside allowed.
	DeleteDisallowedSessions(ctx context.Context, allowed []string) error

	OAuthStore
}

Store persists users, sessions, and OAuth state. Sessions, codes, and tokens are keyed by the hash of their value, never the value itself.

type Token

type Token struct {
	Hash      string
	Refresh   bool
	ExpiresAt time.Time
}

Token is an access or refresh token of a grant, keyed by the hash of its value.

type User

type User struct {
	GitHubID  int64
	Login     string
	Name      string
	AvatarURL string
}

User is a signed-in person.

func UserFrom

func UserFrom(ctx context.Context) (User, bool)

UserFrom returns the user that Auth.Require attached to ctx.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL