package application import ( "fmt" "net/http" "time" "goauthentik.io/internal/outpost/proxyv2/constants" ) // checkAuth Get claims which are currently in session // Returns an error if the session can't be loaded or the claims can't be parsed/type-cast func (a *Application) checkAuth(rw http.ResponseWriter, r *http.Request) (*Claims, error) { c := a.getClaimsFromSession(r) if c != nil { return c, nil } if rw == nil { return nil, fmt.Errorf("no response writer") } // Check TTL cache c = a.getClaimsFromCache(r) if c != nil { return c, nil } // Check bearer token if set bearer := a.checkAuthHeaderBearer(r) if bearer != "" { a.log.Trace("checking bearer token") tc := a.attemptBearerAuth(bearer) if tc != nil { return a.saveAndCacheClaims(rw, r, tc.Claims) } a.log.Trace("no/invalid bearer token") } // Check basic auth if set username, password, basicSet := r.BasicAuth() if basicSet { a.log.Trace("checking basic auth") tc := a.attemptBasicAuth(username, password) if tc != nil { return a.saveAndCacheClaims(rw, r, *tc) } a.log.Trace("no/invalid basic auth") } return nil, fmt.Errorf("failed to get claims from session") } func (a *Application) getClaimsFromSession(r *http.Request) *Claims { s, err := a.sessions.Get(r, a.SessionName()) if err != nil { // err == user has no session/session is not valid, reject return nil } claims, ok := s.Values[constants.SessionClaims] if claims == nil || !ok { // no claims saved, reject return nil } c, ok := claims.(Claims) if !ok { return nil } return &c } func (a *Application) getClaimsFromCache(r *http.Request) *Claims { key := r.Header.Get(constants.HeaderAuthorization) item := a.authHeaderCache.Get(key) if item != nil && !item.IsExpired() { v := item.Value() return &v } return nil } func (a *Application) saveAndCacheClaims(rw http.ResponseWriter, r *http.Request, claims Claims) (*Claims, error) { s, _ := a.sessions.Get(r, a.SessionName()) s.Values[constants.SessionClaims] = claims err := s.Save(r, rw) if err != nil { return nil, err } key := r.Header.Get(constants.HeaderAuthorization) item := a.authHeaderCache.Get(key) // Don't set when the key is already found if item == nil { a.authHeaderCache.Set(key, claims, time.Second*60) } r.Header.Del(constants.HeaderAuthorization) return &claims, nil }