Documentation
¶
Overview ¶
Package identity derives per-app identity keys, sanitizes group lists for header transport, and mints the signed identity token the proxy forwards to app processes. See docs/identity.md for the trust model.
Index ¶
Constants ¶
const ( HeaderUser = "X-Shinyhub-User" HeaderUserID = "X-Shinyhub-User-Id" HeaderRole = "X-Shinyhub-Role" HeaderAppRole = "X-Shinyhub-App-Role" HeaderEmail = "X-Shinyhub-Email" HeaderName = "X-Shinyhub-Name" HeaderGroups = "X-Shinyhub-Groups" HeaderGroupsTruncated = "X-Shinyhub-Groups-Truncated" HeaderToken = "X-Shinyhub-Identity-Token" // HeaderPrefix is the reserved platform prefix: every inbound request // header matching it is deleted unconditionally before forwarding. HeaderPrefix = "X-Shinyhub-" )
Header names injected by the proxy. The X-Shinyhub- prefix is stripped from every inbound request before injection, so apps can trust these arrived from the proxy (and verify the token for anything security-sensitive).
const Issuer = "shinyhub"
Issuer is the iss claim of every identity token.
const MaxGroups = 100
MaxGroups caps the group list in both the plain header and the JWT claim, bounding per-request header size (enterprise users can carry hundreds of groups; unbounded forwarding blows typical 8-16 KB backend header limits).
const TokenTTL = 5 * time.Minute
TokenTTL bounds replay of a captured token. Apps verify exp with leeway.
Variables ¶
This section is empty.
Functions ¶
func DeriveKey ¶
DeriveKey derives the 32-byte per-app HMAC key from the auth secret. The derivation cannot fail in practice; the underlying helper panics if it ever does.
func MintToken ¶
func MintToken(key []byte, p TokenParams) (string, error)
MintToken signs a short-lived HS256 identity token with the app's key.
func SanitizeGroups ¶
SanitizeGroups prepares a group list for transport: sorts (deterministic cap), caps at MaxGroups, and joins for the plain header with comma-bearing names OMITTED (a group named "team,admins" must not forge membership for apps that split the header). The JWT claim slice keeps comma-bearing names. Returns (headerValue, claimGroups, truncated).
Types ¶
type GroupsSource ¶
GroupsSource is kept as the historical name for the groups half of Source.
type Payload ¶
type Payload struct {
Username string
UserID string
Role string
AppRole string
Email string
Name string
GroupsHeader string
GroupsTruncated bool
Token string
}
Payload is everything the proxy injects for one authenticated request.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider assembles identity payloads: it resolves the user's IdP groups and per-app role through small TTL caches (single-flight per key), sanitizes them, and mints the per-app token. One Provider serves the whole process.
func NewProvider ¶
func (*Provider) PayloadFor ¶
PayloadFor builds the identity payload for one request. It never fails: a groups lookup error yields an empty group list (the advisory payload must not take a request down), and a minting error yields a payload with an empty Token (logged).
type Source ¶ added in v0.10.0
type Source interface {
GetUserGroups(userID int64) ([]string, error)
// AppMembershipForUser reports whether the user owns the app and their
// effective member role ("manager"/"viewer"/"", the highest of the manual
// membership and any group rule).
AppMembershipForUser(slug string, userID int64) (isOwner bool, memberRole string, err error)
}
Source is the subset of the DB store the provider needs: the user's IdP group snapshot and their per-app membership (owner / member role).
type TokenClaims ¶
type TokenClaims struct {
Role string `json:"role"`
// AppRole is the caller's capability on THIS app: "owner", "manager"
// (global admin/operator or a manager-role member/group), or "viewer".
// Empty when the membership lookup was unavailable.
AppRole string `json:"app_role,omitempty"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
Groups []string `json:"groups"`
GroupsTruncated bool `json:"groups_truncated,omitempty"`
PreferredUsername string `json:"preferred_username"`
jwt.RegisteredClaims
}
TokenClaims is the identity token payload. Apps verify iss, aud (their own slug, injected as SHINYHUB_APP_SLUG), signature, and exp with ~30 s leeway.
type TokenParams ¶
type TokenParams struct {
UserID int64
Username string
Role string
AppRole string // per-app capability; empty = unavailable
Email string // empty when the upstream IdP provided none
Name string // display name; empty when the IdP provided none
Groups []string // pre-sanitized claim slice from SanitizeGroups
GroupsTruncated bool
Slug string // becomes aud
}
TokenParams carries everything MintToken stamps into the claims.