auth

package
v0.4.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AccessTokenDuration  = 15 * time.Minute
	RefreshTokenDuration = 7 * 24 * time.Hour
)

Variables

This section is empty.

Functions

func AgentIDFromContext

func AgentIDFromContext(ctx interface{ Value(any) any }) uuid.UUID

AgentIDFromContext returns the agent UUID from context, set by AgentMiddleware.

func AgentMiddleware

func AgentMiddleware(jwtSecret string) func(http.Handler) http.Handler

AgentMiddleware validates the agent JWT Bearer token and injects AgentClaims into context.

func AudienceContains

func AudienceContains(aud jwt.ClaimStrings, target string) bool

AudienceContains reports whether `target` is one of the audience values in the claim. Helper for the MCP endpoint's audience check.

func CheckPassword

func CheckPassword(hash, password string) error

CheckPassword compares a plaintext password with a bcrypt hash. Returns nil on success, error on mismatch.

func HashPassword

func HashPassword(password string) (string, error)

HashPassword hashes a plaintext password using bcrypt.

func IssueAgentToken

func IssueAgentToken(secret string, agentID uuid.UUID) (string, error)

IssueAgentToken creates a signed JWT for an agent container (100-year expiry).

func IssueOAuthAccessToken added in v0.4.0

func IssueOAuthAccessToken(secret string, userID uuid.UUID, email, tenantRole, clientID, scope, audience string) (string, error)

IssueOAuthAccessToken mints a JWT with the OAuth-side claims set (ClientID + Scope + Audience). 15-min lifetime, same HS256 secret as the web-login tokens.

This is the SOLE call site in the codebase that sets ClientID. Anything else producing a JWT must not — the MCP endpoint uses ClientID's presence to decide whether the audience check should run. The web-login IssueToken / IssueTokenWithDuration paths deliberately keep ClientID empty.

audience is the canonical resource URL, e.g. "https://airlock.example.com/api/agent/<uuid>/mcp". scope is the space-delimited scope string ("mcp" in v1).

func IssueRefreshToken

func IssueRefreshToken(secret string, userID uuid.UUID, email, tenantRole string) (string, error)

IssueRefreshToken creates a signed refresh token (7 days).

func IssueToken

func IssueToken(secret string, userID uuid.UUID, email, tenantRole string) (string, error)

IssueToken creates a signed access token (15 min).

func IssueTokenWithDuration

func IssueTokenWithDuration(secret string, userID uuid.UUID, email, tenantRole string, duration time.Duration) (string, error)

IssueTokenWithDuration creates a signed token with a custom duration.

func Middleware

func Middleware(jwtSecret string) func(http.Handler) http.Handler

Middleware validates the JWT Bearer token and injects claims into context. It returns 401 for missing, invalid, or expired tokens.

func RequireTenantRole

func RequireTenantRole(minRole Role) func(http.Handler) http.Handler

RequireTenantRole returns middleware that checks the user has at least the given role. Uses hierarchy: admin > manager > user. Returns 403 if not authorized.

func ScopeContains added in v0.4.0

func ScopeContains(scope, required string) bool

ScopeContains reports whether `required` is present in a space-delimited scope string. OAuth 2.0 scopes are case-sensitive (RFC 6749 §3.3); we match exactly.

func UserIDFromContext

func UserIDFromContext(ctx context.Context) uuid.UUID

UserIDFromContext returns the user ID from the JWT claims.

Types

type AgentClaims

type AgentClaims struct {
	jwt.RegisteredClaims
	AgentID string `json:"agent_id"`
}

AgentClaims are the JWT claims for agent tokens.

func ValidateAgentToken

func ValidateAgentToken(secret, tokenString string) (*AgentClaims, error)

ValidateAgentToken validates a JWT and returns the agent claims. Rejects tokens that do not have an AgentID claim.

type Claims

type Claims struct {
	jwt.RegisteredClaims
	Email      string `json:"email"`
	TenantRole string `json:"tenant_role"`
	ClientID   string `json:"client_id,omitempty"`
	Scope      string `json:"scope,omitempty"`
}

Claims are the JWT claims for Airlock tokens.

ClientID and Scope are populated ONLY by IssueOAuthAccessToken (the MCP server-side OAuth flow). Web-login tokens never carry them — the presence of ClientID is the discriminator the MCP endpoint uses to branch between "OAuth access token, verify aud+scope+client" and "web-login JWT, accept as-is". Anything else in this codebase that sets ClientID would break that discrimination — see the Test_UserJWTHasNoClientID invariant in jwt_test.go.

Audience comes from jwt.RegisteredClaims and binds an OAuth access token to a specific agent's MCP URL (RFC 8707 resource indicators).

func ClaimsFromContext

func ClaimsFromContext(ctx context.Context) *Claims

ClaimsFromContext retrieves the JWT claims from the context.

func ValidateToken

func ValidateToken(secret, tokenString string) (*Claims, error)

ValidateToken validates a JWT and returns the claims.

type Role added in v0.4.0

type Role string

Role is a tenant role — what a user can do in Airlock as a platform, independent of any per-agent access. Mirrors agentsdk.Access (the per-agent axis) so the two gates read the same way.

const (
	RoleAdmin   Role = "admin"
	RoleManager Role = "manager"
	RoleUser    Role = "user"
)

func (Role) AtLeast added in v0.4.0

func (r Role) AtLeast(min Role) bool

AtLeast reports whether r ranks at or above min. An unknown role (including the empty string) ranks below everything.

Directories

Path Synopsis
Package lockout implements per-(email, ip) login throttling for the airlock auth path.
Package lockout implements per-(email, ip) login throttling for the airlock auth path.

Jump to

Keyboard shortcuts

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