No need to renew token for IAP

This commit is contained in:
branchmispredictor 2021-05-18 18:25:29 -04:00
parent 911dffd8b3
commit 575414b329
2 changed files with 18 additions and 57 deletions

View File

@ -79,7 +79,6 @@ type AuthClaims struct {
// but an outside source is the final source-of-truth for auth (e.g. Identity-Aware Proxy auth)
type AuthProvider interface {
GetUser(echo.Context, *AuthClaims) (*user.User, error)
RenewToken(echo.Context, *AuthClaims) (string, error)
}
var authProviders = map[AuthType]AuthProvider{}
@ -230,11 +229,7 @@ func RenewToken(s *xorm.Session, c echo.Context) (token string, err error) {
return NewUserJWTAuthtoken(u)
}
if authProvider, ok := authProviders[claims.Type]; ok {
token, err := authProvider.RenewToken(c, claims)
if err != nil {
return "", err
}
return token, nil
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "External auth types do not use JWT tokens."}
}
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."})
}

View File

@ -48,33 +48,7 @@ func Init() {
auth.RegisterAuthMiddleware(auth.AuthTypeIAPUser, Middleware())
}
// NewIAPUserJWTAuthtoken generates and signes a new jwt token for a user
// These are intentionally short lived because they can be regenerated at
// any time from the IAP authn information. They are not related to
// session length and are only used to provide user info to the frontend
// and a hint to auth.go to retrieve auth data from the IAP.
func NewIAPUserJWTAuthtoken(u *user.User) (token string, err error) {
// Set claims
claims := newIAPUserJWTAuthClaims(u)
t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Generate encoded token and send it as response.
return t.SignedString([]byte(config.ServiceJWTSecret.GetString()))
}
func newIAPUserJWTAuthClaims(u *user.User) (claims *auth.AuthClaims) {
return &auth.AuthClaims{
Type: auth.AuthTypeIAPUser,
UserID: u.ID,
UserUsername: u.Username,
UserEmail: u.Email,
UserName: u.Name,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Minute * 5).Unix(),
},
}
}
// Get or generate a new user for the claims made by the IAP
func userForIAPClaims(cl *IAPClaims) (u *user.User, err error) {
s := db.NewSession()
defer s.Close()
@ -94,39 +68,31 @@ func userForIAPClaims(cl *IAPClaims) (u *user.User, err error) {
return u, nil
}
func (p IAPAuthProvider) RenewToken(c echo.Context, authClaims *auth.AuthClaims) (string, error) {
// Get user
u, err := p.GetUser(c, authClaims)
if err != nil {
return "", nil
// Create an AuthClaims object for a user dervived from an IAP identity
func newIAPUserJWTAuthClaims(u *user.User) (claims *auth.AuthClaims) {
return &auth.AuthClaims{
Type: auth.AuthTypeIAPUser,
UserID: u.ID,
UserUsername: u.Username,
UserEmail: u.Email,
UserName: u.Name,
}
// Create token
return NewIAPUserJWTAuthtoken(u)
}
// Get a web.Auth object from the identity that the IAP provides
func (p IAPAuthProvider) GetUser(c echo.Context, authClaims *auth.AuthClaims) (*user.User, error) {
s := db.NewSession()
defer s.Close()
// Get the user from the IAP identity
cl := c.Get(IAPClaimsContextKey).(*IAPClaims)
u, err := userForIAPClaims(cl)
if err != nil {
return nil, err
// The IAP middleware already checked and created a user if needed, no need to regenerate them
// Just use the authClaims provided by the middleware
u = &user.User{
ID: authClaims.UserID,
Email: authClaims.UserEmail,
Username: authClaims.UserUsername,
Name: authClaims.UserName,
}
// Sanity check that the user the frontend thinks it has (the authClaims from the JWT it passed in)
// is the same as the user provided by the IAP.
if authClaims.UserID != u.ID {
return nil, ErrIAPUserFrontendMismatch{}
}
return u, nil
}
// Validates the claims in the jwt
// Validates the claims in the IAP jwt
// Matches the jwt-go Claims interface
func (c *IAPClaims) Valid() error {
// Validate that expiresAt and issuedAt are set and valid (with up to 1 minute of skew)