forked from vikunja/vikunja
No need to renew token for IAP
This commit is contained in:
parent
911dffd8b3
commit
575414b329
|
@ -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)
|
// but an outside source is the final source-of-truth for auth (e.g. Identity-Aware Proxy auth)
|
||||||
type AuthProvider interface {
|
type AuthProvider interface {
|
||||||
GetUser(echo.Context, *AuthClaims) (*user.User, error)
|
GetUser(echo.Context, *AuthClaims) (*user.User, error)
|
||||||
RenewToken(echo.Context, *AuthClaims) (string, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var authProviders = map[AuthType]AuthProvider{}
|
var authProviders = map[AuthType]AuthProvider{}
|
||||||
|
@ -230,11 +229,7 @@ func RenewToken(s *xorm.Session, c echo.Context) (token string, err error) {
|
||||||
return NewUserJWTAuthtoken(u)
|
return NewUserJWTAuthtoken(u)
|
||||||
}
|
}
|
||||||
if authProvider, ok := authProviders[claims.Type]; ok {
|
if authProvider, ok := authProviders[claims.Type]; ok {
|
||||||
token, err := authProvider.RenewToken(c, claims)
|
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "External auth types do not use JWT tokens."}
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
}
|
||||||
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."})
|
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."})
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,33 +48,7 @@ func Init() {
|
||||||
auth.RegisterAuthMiddleware(auth.AuthTypeIAPUser, Middleware())
|
auth.RegisterAuthMiddleware(auth.AuthTypeIAPUser, Middleware())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIAPUserJWTAuthtoken generates and signes a new jwt token for a user
|
// Get or generate a new user for the claims made by the IAP
|
||||||
// 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(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func userForIAPClaims(cl *IAPClaims) (u *user.User, err error) {
|
func userForIAPClaims(cl *IAPClaims) (u *user.User, err error) {
|
||||||
s := db.NewSession()
|
s := db.NewSession()
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
@ -94,39 +68,31 @@ func userForIAPClaims(cl *IAPClaims) (u *user.User, err error) {
|
||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p IAPAuthProvider) RenewToken(c echo.Context, authClaims *auth.AuthClaims) (string, error) {
|
// Create an AuthClaims object for a user dervived from an IAP identity
|
||||||
// Get user
|
func newIAPUserJWTAuthClaims(u *user.User) (claims *auth.AuthClaims) {
|
||||||
u, err := p.GetUser(c, authClaims)
|
return &auth.AuthClaims{
|
||||||
if err != nil {
|
Type: auth.AuthTypeIAPUser,
|
||||||
return "", nil
|
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
|
// 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) {
|
func (p IAPAuthProvider) GetUser(c echo.Context, authClaims *auth.AuthClaims) (*user.User, error) {
|
||||||
s := db.NewSession()
|
// The IAP middleware already checked and created a user if needed, no need to regenerate them
|
||||||
defer s.Close()
|
// Just use the authClaims provided by the middleware
|
||||||
|
u = &user.User{
|
||||||
// Get the user from the IAP identity
|
ID: authClaims.UserID,
|
||||||
cl := c.Get(IAPClaimsContextKey).(*IAPClaims)
|
Email: authClaims.UserEmail,
|
||||||
u, err := userForIAPClaims(cl)
|
Username: authClaims.UserUsername,
|
||||||
if err != nil {
|
Name: authClaims.UserName,
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates the claims in the jwt
|
// Validates the claims in the IAP jwt
|
||||||
// Matches the jwt-go Claims interface
|
// Matches the jwt-go Claims interface
|
||||||
func (c *IAPClaims) Valid() error {
|
func (c *IAPClaims) Valid() error {
|
||||||
// Validate that expiresAt and issuedAt are set and valid (with up to 1 minute of skew)
|
// Validate that expiresAt and issuedAt are set and valid (with up to 1 minute of skew)
|
||||||
|
|
Loading…
Reference in New Issue