diff --git a/server/api/apis.go b/server/api/apis.go index 59b354f..b4b6458 100644 --- a/server/api/apis.go +++ b/server/api/apis.go @@ -19,7 +19,7 @@ import ( func Routes( r *gin.RouterGroup, logger *logging.Logger, - auth *auth.Auth, + auth *auth.Service, sq *sse.Queue, accts *accounts.Store, unp *sse.UpdateNotificationPublisher, diff --git a/server/auth/auth.go b/server/auth/auth.go index b2d99b4..008c68c 100644 --- a/server/auth/auth.go +++ b/server/auth/auth.go @@ -19,12 +19,18 @@ import ( ) type ( - Auth struct { + Service struct { log *logging.Logger auth *authentication.Authenticator accts *accounts.Store } + Auth struct { + Identity Identity + Found bool + Valid bool // eg not expired + } + Identity struct { AccessToken string Claims authentication.AccessTokenClaims @@ -37,36 +43,40 @@ type ( AuthorizationAssertions = response.HandlerFunc ) -func NewAuth( +func NewService( logger *logging.Logger, auth *authentication.Authenticator, accts *accounts.Store, -) *Auth { - return &Auth{ +) *Service { + return &Service{ log: logger, auth: auth, accts: accts, } } -func (a *Auth) GetAuthenticator() *authentication.Authenticator { +func (a *Service) GetAuthenticator() *authentication.Authenticator { return a.auth } -// Identify will add an Identity to the context that can then be retrieved via GetIdentity. -func (a *Auth) Identify(c *gin.Context) { - if err := a.addIdentity(c); err != nil { +// Identify will add an Auth to the context that can then be retrieved via GetAuth. +func (a *Service) Identify(c *gin.Context) { + auth, err := a.getAuthFromRequest(c) + if auth != nil { + c.Request = c.Request.WithContext(SetAuth(c, *auth)) + } + if err != nil { c.Error(err) c.Abort() } } -func (a *Auth) addIdentity(c *gin.Context) error { +func (a *Service) getAuthFromRequest(c *gin.Context) (*Auth, error) { r := c.Request ck, err := r.Cookie("access_token") if err != nil { - return nil + return nil, nil } ctx := r.Context() @@ -76,50 +86,61 @@ func (a *Auth) addIdentity(c *gin.Context) error { claims, err := a.auth.GetAccessTokenClaimsAndExpiration(ctx, accessToken) if err != nil { if errors.Is(err, consts.ErrNotFound) { - return nil + // need to log in, in order to access privilege pages/apis + return &Auth{}, nil } - return response.Errorf("failed to load authentication details: %w", err) + return nil, response.Errorf("failed to load authentication details: %w", err) } expiration := claims.Expiration if expiration.Before(time.Now()) { - return nil + // need to log in, in order to access privilege pages/apis + return &Auth{ + Found: true, + }, nil } user, acct, err := a.accts.GetUserAndAccountByAccessToken(ctx, accessToken) if err != nil { - return response.Errorf("failed to load user and account defails: %w", err) + return nil, response.Errorf("failed to load user and account defails: %w", err) } - c.Request = r.WithContext(SetIdentity(c, Identity{ - AccessToken: accessToken, - Claims: claims, - User: user, - Account: acct, - })) - - return nil + return &Auth{ + Found: true, + Valid: true, + Identity: Identity{ + AccessToken: accessToken, + Claims: claims, + User: user, + Account: acct, + }, + }, nil } // Authenticate should only be used along with and after Identify // Typically used with response.Handler to make a gin.HandlerFunc. -func (a *Auth) Authenticate(assertions ...AuthorizationAssertions) func(c *gin.Context) { +func (a *Service) Authenticate(assertions ...AuthorizationAssertions) func(c *gin.Context) { return response.Handler(a.AuthenticateHandler(assertions...)) } // See Authenticate. -func (a *Auth) AuthenticateHandler(assertions ...AuthorizationAssertions) func(c *gin.Context) (response.Response, error) { +func (a *Service) AuthenticateHandler(assertions ...AuthorizationAssertions) func(c *gin.Context) (response.Response, error) { return func(c *gin.Context) (response.Response, error) { - id, ok := getIdentity(c) - if !ok { - return nil, response.Unauthorized(). - HTML([]byte(` -