Documentation
¶
Index ¶
- Constants
- Variables
- func Authenticate(ctx context.Context, sessionID, userAgent, method, path string) (modeliamsession.Session, error)
- func BuildAuthenticatedSessionRsp(sessionData modeliamsession.Session, user *modeliamuser.User, email string, ...) *modeliamsession.AuthenticatedSessionRsp
- func ClearCookie(ctx *gst.ServiceContext)
- func CookieSessionID(ctx *gst.ServiceContext) (string, error)
- func CurrentSession(ctx *gst.ServiceContext) (string, modeliamsession.Session, error)
- func GetSessionExpiration() time.Duration
- func GetSessionUserStateTTL() time.Duration
- func MustChangePasswordExempt(method, path string) bool
- func NewSessionID() (string, error)
- func SetCookie(ctx *gst.ServiceContext, sessionID string, maxAge time.Duration)
- func SetSessionExpiration(expiration time.Duration)
- func ValidateSession(sessionID string, sessionData modeliamsession.Session) error
- func ValidateSessionUserState(ctx context.Context, session modeliamsession.Session) (modeliamsession.Session, error)
- func WithCurrentSession(ctx context.Context, sessionID string, session modeliamsession.Session) context.Context
- type AdminSessionDeleteService
- type AdminSessionGetService
- type AdminSessionListService
- type AdminUserSessionDeleteService
- type AdminUserSessionListService
- type CurrentDeleteService
- type CurrentGetService
- type SessionDeleteAllService
- type SessionDeleteService
- type SessionGetService
- type SessionListService
- type UserState
Constants ¶
const (
// SessionCookieName is the HTTP cookie carrying the opaque IAM session id.
SessionCookieName = "session_id"
)
Variables ¶
var Store = store{}
Store is the only path from IAM to Redis.
Every session key, every index, and the user-state cache are reached through the methods below, and the key layout they use is private to this file. A caller therefore cannot address storage in a way the store does not offer, which is what lets the layout change without every call site agreeing to it — the previous arrangement, with exported key builders and Redis calls spread across a dozen files, could promise neither.
The methods speak in sessions rather than in Redis commands. A caller asks to delete a session, not to delete a string and remove three sorted-set members, and the invariant that those happen together lives here rather than in each caller's memory.
Functions ¶
func Authenticate ¶
func Authenticate(ctx context.Context, sessionID, userAgent, method, path string) (modeliamsession.Session, error)
Authenticate resolves the session sessionID names for a request or call that arrived with userAgent for the action at the HTTP method and path: the one path both the HTTP middleware and the gRPC interceptor of the module take, so a session is admitted or refused the same way over both listeners. The snapshot is loaded and validated; the device the session was established from — operating system, platform, browser engine and browser, as the user agent names them — has to be the one calling, which is what keeps a stolen session id from being used elsewhere, over either listener; the mutable state of the session's user is refreshed; while the user must change the password, only the actions for that are admitted (see MustChangePasswordExempt); and the session is touched.
A refusal is a service error carrying the status and the one fixed message the client is answered with: 401 "no session" with no session id, 401 "session invalid" for a snapshot the store no longer has, one that failed validation or one bound to another device, the user state's own service error or 403 "session invalid" for any other failure of it, and 403 "password change required before using this resource". The reasons are graded — a snapshot storage no longer has, one that expired, one issued to another browser or another OS — and answering each in its own words would hand the bearer of a stolen session id a probe: it could vary one component of the request at a time and read back which one the server objected to. The holder of a live session is told nothing by the distinction either, since every one of these is answered by logging in again, so only the log keeps it. A store that does not answer is the server's failure, answered 500 "failed to load session" (see loadSession); so is a user state that could not be read, answered with its own 500.
A snapshot that fails validation is deleted on the way out, and so are one whose user is refused — gone, disabled or locked — and a stored value that is not a snapshot: none can serve another request, and leaving them would let every later request pay to load and reject them again. A session the store did not answer for, or whose user's state could not be read, is kept for the next request to read it once the store is back.
func BuildAuthenticatedSessionRsp ¶
func BuildAuthenticatedSessionRsp( sessionData modeliamsession.Session, user *modeliamuser.User, email string, now time.Time, systemRoot bool, ) *modeliamsession.AuthenticatedSessionRsp
BuildAuthenticatedSessionRsp builds the shared login/current response contract.
systemRoot is taken as an argument rather than resolved here. This builder runs once the response is already decided — for login, after the session is stored and the cookie is written — so an authorization lookup failing at this point would fail a request that has otherwise succeeded. Each caller resolves it while it can still refuse.
func ClearCookie ¶
func ClearCookie(ctx *gst.ServiceContext)
ClearCookie removes the session cookie using the same path and security attributes SetCookie wrote it with, which is what makes the browser drop the cookie rather than keep a second one.
func CookieSessionID ¶
func CookieSessionID(ctx *gst.ServiceContext) (string, error)
CookieSessionID returns the session id carried by the request cookie.
A request without one is not an anonymous request this layer can shrug at: every caller of this function is already inside an authenticated route, so a missing cookie is an unauthenticated caller and is reported as one.
func CurrentSession ¶
func CurrentSession(ctx *gst.ServiceContext) (string, modeliamsession.Session, error)
CurrentSession returns the authenticated session of the request or call.
The session the middleware or interceptor admitted is on the context (see WithCurrentSession) and answers first, on either listener: a gRPC call has no cookie to read, and asking its context for one is a call the listener refuses once the action returns. The cookie is read for a request reached without the middleware, whose session is then loaded through loadSession: a store that does not answer is 500, not 401, and a stored value that is not a snapshot is deleted and 401.
A snapshot that fails validation is deleted on the way out. It cannot serve another request, and leaving it would let every later request pay to load and reject it again.
func GetSessionExpiration ¶
GetSessionExpiration returns the configured session expiration time. If not configured, it reads IAM_SESSION_EXPIRATION before falling back to 8 hours.
func GetSessionUserStateTTL ¶
GetSessionUserStateTTL returns the configured mutable user-state cache TTL. If not configured, it reads IAM_SESSION_USER_STATE_TTL before falling back to 30 seconds.
func MustChangePasswordExempt ¶
MustChangePasswordExempt reports whether the action at the HTTP method and path may proceed while the session's MustChangePassword flag is set: the ones a user needs to get out of that state, changing the password, logging out and reading or ending the current session. Authenticate asks it for both the HTTP middleware and the gRPC interceptor of the module, the gRPC one with the HTTP method and route its call's action is served at.
func NewSessionID ¶
NewSessionID returns an opaque random session identifier.
func SetCookie ¶
func SetCookie(ctx *gst.ServiceContext, sessionID string, maxAge time.Duration)
SetCookie writes the session cookie with hardened defaults.
func SetSessionExpiration ¶
SetSessionExpiration sets the session expiration time for iam module. This function should be called during module registration.
func ValidateSession ¶
func ValidateSession(sessionID string, sessionData modeliamsession.Session) error
ValidateSession reports whether a stored snapshot is usable as the session the given id names.
It answers from the snapshot alone. Whether the user behind it may still be authenticated is a separate question, asked of the database through ValidateSessionUserState, because the answer changes without the snapshot changing.
func ValidateSessionUserState ¶
func ValidateSessionUserState(ctx context.Context, session modeliamsession.Session) (modeliamsession.Session, error)
ValidateSessionUserState refreshes the mutable user state required to keep using a session.
func WithCurrentSession ¶
func WithCurrentSession(ctx context.Context, sessionID string, session modeliamsession.Session) context.Context
WithCurrentSession stores a validated session snapshot on the request context so the handlers behind the middleware do not each reload it.
Types ¶
type AdminSessionDeleteService ¶
type AdminSessionDeleteService struct {
service.Base[*modeliamsession.AdminSession, *modeliamsession.AdminSessionDeleteReq, *modeliamsession.AdminSessionDeleteRsp]
}
AdminSessionDeleteService handles invalidation of a specified session for privileged administrators.
func (*AdminSessionDeleteService) Delete ¶
func (a *AdminSessionDeleteService) Delete(ctx *gst.ServiceContext, req *modeliamsession.AdminSessionDeleteReq) (rsp *modeliamsession.AdminSessionDeleteRsp, err error)
Delete invalidates a specified session for a privileged administrator.
type AdminSessionGetService ¶
type AdminSessionGetService struct {
service.Base[*modeliamsession.AdminSession, *model.Empty, *modeliamsession.AdminSessionGetRsp]
}
AdminSessionGetService handles retrieval of a specified session for privileged administrators.
func (*AdminSessionGetService) Get ¶
func (a *AdminSessionGetService) Get(ctx *gst.ServiceContext, req *model.Empty) (rsp *modeliamsession.AdminSessionGetRsp, err error)
Get returns the detail of a specified session for a privileged administrator.
type AdminSessionListService ¶
type AdminSessionListService struct {
service.Base[*modeliamsession.AdminSession, *model.Empty, *modeliamsession.AdminSessionListRsp]
}
AdminSessionListService handles retrieval of all sessions grouped by user for privileged administrators.
func (*AdminSessionListService) List ¶
func (a *AdminSessionListService) List(ctx *gst.ServiceContext, req *model.Empty) (rsp *modeliamsession.AdminSessionListRsp, err error)
List returns all indexed sessions grouped by user for a privileged administrator.
type AdminUserSessionDeleteService ¶
type AdminUserSessionDeleteService struct {
service.Base[*modeliamsession.AdminUserSession, *modeliamsession.AdminUserSessionDeleteReq, *modeliamsession.AdminUserSessionDeleteRsp]
}
AdminUserSessionDeleteService handles invalidation of all sessions owned by a specified user for privileged administrators.
func (*AdminUserSessionDeleteService) Delete ¶
func (a *AdminUserSessionDeleteService) Delete(ctx *gst.ServiceContext, req *modeliamsession.AdminUserSessionDeleteReq) (rsp *modeliamsession.AdminUserSessionDeleteRsp, err error)
Delete invalidates all indexed sessions of a specified user for a privileged administrator.
type AdminUserSessionListService ¶
type AdminUserSessionListService struct {
service.Base[*modeliamsession.AdminUserSession, *model.Empty, *modeliamsession.AdminUserSessionListRsp]
}
AdminUserSessionListService handles retrieval of all sessions owned by a specified user for privileged administrators.
func (*AdminUserSessionListService) List ¶
func (a *AdminUserSessionListService) List(ctx *gst.ServiceContext, req *model.Empty) (rsp *modeliamsession.AdminUserSessionListRsp, err error)
List returns all indexed sessions of a specified user for a privileged administrator.
type CurrentDeleteService ¶
type CurrentDeleteService struct {
service.Base[*modeliamsession.Current, *modeliamsession.CurrentDeleteReq, *modeliamsession.CurrentDeleteRsp]
}
CurrentDeleteService handles invalidation of the current authenticated session.
func (*CurrentDeleteService) Delete ¶
func (c *CurrentDeleteService) Delete(ctx *gst.ServiceContext, req *modeliamsession.CurrentDeleteReq) (rsp *modeliamsession.CurrentDeleteRsp, err error)
Delete invalidates the current authenticated session and clears the session cookie.
type CurrentGetService ¶
type CurrentGetService struct {
service.Base[*modeliamsession.Current, *model.Empty, *modeliamsession.CurrentGetRsp]
}
CurrentGetService handles retrieval of the current authenticated session.
func (*CurrentGetService) Get ¶
func (c *CurrentGetService) Get(ctx *gst.ServiceContext, req *model.Empty) (rsp *modeliamsession.CurrentGetRsp, err error)
Get returns the current authenticated session together with the latest user snapshot.
type SessionDeleteAllService ¶
type SessionDeleteAllService struct {
service.Base[*modeliamsession.SelfSession, *modeliamsession.SessionDeleteAllReq, *modeliamsession.SessionDeleteAllRsp]
}
SessionDeleteAllService handles invalidation of all sessions for the current authenticated user.
func (*SessionDeleteAllService) Delete ¶
func (s *SessionDeleteAllService) Delete(ctx *gst.ServiceContext, req *modeliamsession.SessionDeleteAllReq) (rsp *modeliamsession.SessionDeleteAllRsp, err error)
Delete invalidates all sessions for the current authenticated user.
type SessionDeleteService ¶
type SessionDeleteService struct {
service.Base[*modeliamsession.SelfSession, *modeliamsession.SessionDeleteReq, *modeliamsession.SessionDeleteRsp]
}
SessionDeleteService handles invalidation of a specified session for the current authenticated user.
func (*SessionDeleteService) Delete ¶
func (s *SessionDeleteService) Delete(ctx *gst.ServiceContext, req *modeliamsession.SessionDeleteReq) (rsp *modeliamsession.SessionDeleteRsp, err error)
Delete invalidates a specified session for the current authenticated user. DELETE /api/iam/sessions/:id revokes the target session, while DELETE /api/iam/sessions/others revokes every other indexed session of the same user and keeps the current cookie-backed session active. The endpoint remains idempotent: deleting a missing session still returns success.
type SessionGetService ¶
type SessionGetService struct {
service.Base[*modeliamsession.SelfSession, *model.Empty, *modeliamsession.SessionGetRsp]
}
SessionGetService handles retrieval of a specified session for the current authenticated user.
func (*SessionGetService) Get ¶
func (s *SessionGetService) Get(ctx *gst.ServiceContext, req *model.Empty) (rsp *modeliamsession.SessionGetRsp, err error)
Get returns the detail of a specified session for the current authenticated user.
type SessionListService ¶
type SessionListService struct {
service.Base[*modeliamsession.SelfSession, *model.Empty, *modeliamsession.SessionListRsp]
}
SessionListService handles retrieval of all active sessions for the current authenticated user.
func (*SessionListService) List ¶
func (s *SessionListService) List(ctx *gst.ServiceContext, req *model.Empty) (rsp *modeliamsession.SessionListRsp, err error)
List returns all active sessions for the current authenticated user.
type UserState ¶
type UserState struct {
Status modeliamuser.UserStatus `json:"status"`
MustChangePassword bool `json:"must_change_password"`
}
UserState is the mutable user state an authenticated request has to confirm before a session may keep going.
It is cached separately from the session snapshot because it belongs to the user: one entry answers for every session that user holds, and it outlives any of them.
Source Files
¶
- admin_session_delete.go
- admin_session_get.go
- admin_session_list.go
- admin_user_session_delete.go
- admin_user_session_list.go
- authenticate.go
- authenticated.go
- cookie.go
- current.go
- current_delete.go
- current_get.go
- helper.go
- helper_admin.go
- helper_userstate.go
- session_delete.go
- session_delete_all.go
- session_get.go
- session_list.go
- store.go
- store_testseam.go
- types.go