Make IAP middleware an optional follow-up to the JWT middleware

This commit is contained in:
branchmispredictor 2021-05-17 23:09:32 -04:00
parent 440e0e2b27
commit 911dffd8b3
10 changed files with 178 additions and 100 deletions

View File

@ -27,6 +27,7 @@ import (
"code.vikunja.io/api/pkg/mail" "code.vikunja.io/api/pkg/mail"
"code.vikunja.io/api/pkg/migration" "code.vikunja.io/api/pkg/migration"
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/modules/auth/identityawareproxy"
"code.vikunja.io/api/pkg/modules/keyvalue" "code.vikunja.io/api/pkg/modules/keyvalue"
migrator "code.vikunja.io/api/pkg/modules/migration" migrator "code.vikunja.io/api/pkg/modules/migration"
"code.vikunja.io/api/pkg/notifications" "code.vikunja.io/api/pkg/notifications"
@ -95,6 +96,9 @@ func FullInit() {
models.RegisterReminderCron() models.RegisterReminderCron()
models.RegisterOverdueReminderCron() models.RegisterOverdueReminderCron()
// Setup
identityawareproxy.Init()
// Start processing events // Start processing events
go func() { go func() {
models.RegisterListeners() models.RegisterListeners()

View File

@ -29,7 +29,6 @@ import (
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
petname "github.com/dustinkirkland/golang-petname" petname "github.com/dustinkirkland/golang-petname"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
) )
// These are all valid auth types // These are all valid auth types
@ -42,7 +41,8 @@ const (
AuthTypeIAPUser AuthTypeIAPUser
) )
const authTokenContextKey string = "authToken" // Key used to store authClaims
const AuthClaimsContextKey string = "authClaims"
// Token represents an authentification token in signed string form // Token represents an authentification token in signed string form
type Token struct { type Token struct {
@ -78,7 +78,8 @@ type AuthClaims struct {
// In these cases, AuthClaims may contain hints to the user identity, // In these cases, AuthClaims may contain hints to the user identity,
// 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 {
GetWebAuth(echo.Context, *AuthClaims) (web.Auth, error) GetUser(echo.Context, *AuthClaims) (*user.User, error)
RenewToken(echo.Context, *AuthClaims) (string, error)
} }
var authProviders = map[AuthType]AuthProvider{} var authProviders = map[AuthType]AuthProvider{}
@ -147,8 +148,7 @@ func NewLinkShareJWTAuthtoken(share *models.LinkSharing) (token string, err erro
// GetAuthFromClaims returns a web.Auth object from jwt claims or from an // GetAuthFromClaims returns a web.Auth object from jwt claims or from an
// alternative authProvider // alternative authProvider
func GetAuthFromClaims(c echo.Context) (a web.Auth, err error) { func GetAuthFromClaims(c echo.Context) (a web.Auth, err error) {
jwtinf := c.Get(authTokenContextKey).(*jwt.Token) claims := c.Get(AuthClaimsContextKey).(*AuthClaims)
claims := jwtinf.Claims.(*AuthClaims)
if claims.Type == AuthTypeLinkShare && config.ServiceEnableLinkSharing.GetBool() { if claims.Type == AuthTypeLinkShare && config.ServiceEnableLinkSharing.GetBool() {
return getLinkShareFromClaims(claims) return getLinkShareFromClaims(claims)
} }
@ -156,7 +156,7 @@ func GetAuthFromClaims(c echo.Context) (a web.Auth, err error) {
return getUserFromClaims(claims), nil return getUserFromClaims(claims), nil
} }
if authProvider, ok := authProviders[claims.Type]; ok { if authProvider, ok := authProviders[claims.Type]; ok {
return authProvider.GetWebAuth(c, claims) return authProvider.GetUser(c, claims)
} }
return nil, echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."}) return nil, echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."})
} }
@ -206,8 +206,7 @@ func GetCurrentUser(c echo.Context) (u *user.User, err error) {
// Generates a new jwt token for the types AuthTypeLinkShare and AuthTypeUser // Generates a new jwt token for the types AuthTypeLinkShare and AuthTypeUser
func RenewToken(s *xorm.Session, c echo.Context) (token string, err error) { func RenewToken(s *xorm.Session, c echo.Context) (token string, err error) {
jwtinf := c.Get(authTokenContextKey).(*jwt.Token) claims := c.Get(AuthClaimsContextKey).(*AuthClaims)
claims := jwtinf.Claims.(*AuthClaims)
if claims.Type == AuthTypeLinkShare { if claims.Type == AuthTypeLinkShare {
oldShare, err := getLinkShareFromClaims(claims) oldShare, err := getLinkShareFromClaims(claims)
@ -230,17 +229,14 @@ func RenewToken(s *xorm.Session, c echo.Context) (token string, err error) {
} }
return NewUserJWTAuthtoken(u) return NewUserJWTAuthtoken(u)
} }
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."}) if authProvider, ok := authProviders[claims.Type]; ok {
} token, err := authProvider.RenewToken(c, claims)
if err != nil {
// GetJWTConfig returns the config for the default JWT middleware return "", err
func GetJWTConfig() middleware.JWTConfig { }
return middleware.JWTConfig{ return token, nil
SigningKey: []byte(config.ServiceJWTSecret.GetString()),
SigningMethod: middleware.AlgorithmHS256,
ContextKey: authTokenContextKey,
Claims: &AuthClaims{},
} }
return "", echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."})
} }
// GetOrCreateUserFromExternalAuth returns a user after finding or creating a matching user for the provided details // GetOrCreateUserFromExternalAuth returns a user after finding or creating a matching user for the provided details

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life. // Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved. // Copyright 2018-2021 Vikunja and contributors. All rights reserved.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU Affero General Public Licensee for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package identityawareproxy package identityawareproxy

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life. // Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved. // Copyright 2018-2021 Vikunja and contributors. All rights reserved.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU Affero General Public Licensee for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package identityawareproxy package identityawareproxy
@ -25,7 +25,6 @@ import (
"code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/modules/auth" "code.vikunja.io/api/pkg/modules/auth"
"code.vikunja.io/api/pkg/user" "code.vikunja.io/api/pkg/user"
"code.vikunja.io/web"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -44,8 +43,9 @@ type IAPClaims struct {
// Auth provider used to allow auth to get a web.Auth from the IAP provided identity // Auth provider used to allow auth to get a web.Auth from the IAP provided identity
type IAPAuthProvider struct{} type IAPAuthProvider struct{}
func init() { func Init() {
auth.RegisterAuthProvider(auth.AuthTypeIAPUser, IAPAuthProvider{}) auth.RegisterAuthProvider(auth.AuthTypeIAPUser, IAPAuthProvider{})
auth.RegisterAuthMiddleware(auth.AuthTypeIAPUser, Middleware())
} }
// NewIAPUserJWTAuthtoken generates and signes a new jwt token for a user // NewIAPUserJWTAuthtoken generates and signes a new jwt token for a user
@ -55,7 +55,15 @@ func init() {
// and a hint to auth.go to retrieve auth data from the IAP. // and a hint to auth.go to retrieve auth data from the IAP.
func NewIAPUserJWTAuthtoken(u *user.User) (token string, err error) { func NewIAPUserJWTAuthtoken(u *user.User) (token string, err error) {
// Set claims // Set claims
claims := &auth.AuthClaims{ 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, Type: auth.AuthTypeIAPUser,
UserID: u.ID, UserID: u.ID,
UserUsername: u.Username, UserUsername: u.Username,
@ -65,57 +73,14 @@ func NewIAPUserJWTAuthtoken(u *user.User) (token string, err error) {
ExpiresAt: time.Now().Add(time.Minute * 5).Unix(), ExpiresAt: time.Now().Add(time.Minute * 5).Unix(),
}, },
} }
t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Generate encoded token and send it as response.
return t.SignedString([]byte(config.ServiceJWTSecret.GetString()))
} }
// Token generates a local, short-lived JWT based on the identity from the identity-aware proxy. func userForIAPClaims(cl *IAPClaims) (u *user.User, err error) {
// See also the docs for NewIAPUserJWTAuthtoken
// @Summary Authenticate a user from the Identity-Aware Proxy
// @Description Generates a short-lived JWT based on the identity from the identity-aware proxy in order to provide the front-end with user id and username info
// @tags auth
// @Accept N/A
// @Produce json
// @Success 200 {object} auth.Token
// @Failure 500 {object} models.Message "Internal error"
// @Router /auth/identityawareproxy/token [get]
func GetToken(c echo.Context) error {
cl := c.Get(IAPClaimsContextKey).(*IAPClaims)
s := db.NewSession() s := db.NewSession()
defer s.Close() defer s.Close()
// Check if we have seen this user before // Check if we have seen this user before
u, err := auth.GetOrCreateUserFromExternalAuth(s, cl.Issuer, cl.Subject, cl.Email, cl.Name, cl.PreferredUsername) u, err = auth.GetOrCreateUserFromExternalAuth(s, cl.Issuer, cl.Subject, cl.Email, cl.Name, cl.PreferredUsername)
if err != nil {
_ = s.Rollback()
return err
}
err = s.Commit()
if err != nil {
return err
}
// Create token
userToken, err := NewIAPUserJWTAuthtoken(u)
if err != nil {
return err
}
return auth.NewTokenResponse(userToken, c)
}
// Get a web.Auth object from the identity that the IAP provides
func (p IAPAuthProvider) GetWebAuth(c echo.Context, authClaims *auth.AuthClaims) (web.Auth, error) {
s := db.NewSession()
defer s.Close()
// Get the user from the IAP identity
cl := c.Get(IAPClaimsContextKey).(*IAPClaims)
u, err := auth.GetOrCreateUserFromExternalAuth(s, cl.Issuer, cl.Subject, cl.Email, cl.Name, cl.PreferredUsername)
if err != nil { if err != nil {
_ = s.Rollback() _ = s.Rollback()
return nil, err return nil, err
@ -126,6 +91,32 @@ func (p IAPAuthProvider) GetWebAuth(c echo.Context, authClaims *auth.AuthClaims)
return nil, err return nil, err
} }
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 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
}
// Sanity check that the user the frontend thinks it has (the authClaims from the JWT it passed in) // 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. // is the same as the user provided by the IAP.
if authClaims.UserID != u.ID { if authClaims.UserID != u.ID {

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life. // Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved. // Copyright 2018-2021 Vikunja and contributors. All rights reserved.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU Affero General Public Licensee for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package identityawareproxy package identityawareproxy

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life. // Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved. // Copyright 2018-2021 Vikunja and contributors. All rights reserved.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU Affero General Public Licensee for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package identityawareproxy package identityawareproxy
@ -23,6 +23,7 @@ import (
"code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/modules/auth"
"code.vikunja.io/web/handler" "code.vikunja.io/web/handler"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
@ -70,6 +71,12 @@ func Middleware() echo.MiddlewareFunc {
cache := &iapCache{} cache := &iapCache{}
return func(next echo.HandlerFunc) echo.HandlerFunc { return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
// Skip if IAP is not enabled
if !config.AuthIdentityAwareProxyEnabled.GetBool() {
return next(c)
}
// Get and validate claims from the IAP
token := c.Request().Header.Get(config.AuthIdentityAwareProxyJwtHeader.GetString()) token := c.Request().Header.Get(config.AuthIdentityAwareProxyJwtHeader.GetString())
if token == "" { if token == "" {
err := ErrIAPTokenMissing{Header: config.AuthIdentityAwareProxyJwtHeader.GetString()} err := ErrIAPTokenMissing{Header: config.AuthIdentityAwareProxyJwtHeader.GetString()}
@ -85,13 +92,23 @@ func Middleware() echo.MiddlewareFunc {
if err != nil { if err != nil {
return handler.HandleHTTPError(err, c) return handler.HandleHTTPError(err, c)
} }
c.Set(IAPClaimsContextKey, cl) c.Set(IAPClaimsContextKey, cl)
// Generate auth.AuthClaims from the IAP identity
user, err := userForIAPClaims(cl)
if err != nil {
return handler.HandleHTTPError(err, c)
}
authClaims := newIAPUserJWTAuthClaims(user)
c.Set(auth.AuthClaimsContextKey, authClaims)
return next(c) return next(c)
} }
} }
} }
// The authMiddleware generates and stores internal auth based on
// those claims. This overwrites any auth from the JWT middleware
func parseAndValidateJwt(token string, keyset *jwk.Set) (*IAPClaims, error) { func parseAndValidateJwt(token string, keyset *jwk.Set) (*IAPClaims, error) {
// Parse the jwt from the identity-aware proxy using the correct key // Parse the jwt from the identity-aware proxy using the correct key
tken, err := jwt.ParseWithClaims(token, &IAPClaims{}, func(unvalidatedToken *jwt.Token) (interface{}, error) { tken, err := jwt.ParseWithClaims(token, &IAPClaims{}, func(unvalidatedToken *jwt.Token) (interface{}, error) {

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life. // Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved. // Copyright 2018-2021 Vikunja and contributors. All rights reserved.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU Affero General Public Licensee for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
package identityawareproxy package identityawareproxy

View File

@ -0,0 +1,80 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package auth
import (
"code.vikunja.io/api/pkg/config"
"github.com/dgrijalva/jwt-go"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
// Resolves circular dependencies of auth -> IAP -> auth
var authMiddlewares = map[AuthType]echo.MiddlewareFunc{}
func RegisterAuthMiddleware(t AuthType, f echo.MiddlewareFunc) {
authMiddlewares[t] = f
}
const authTokenJWTContextKey = "jwtToken"
// GetJWTConfig returns the config for the default JWT middleware
func GetJWTConfig() middleware.JWTConfig {
return middleware.JWTConfig{
SigningKey: []byte(config.ServiceJWTSecret.GetString()),
SigningMethod: middleware.AlgorithmHS256,
ContextKey: authTokenJWTContextKey,
Claims: &AuthClaims{},
}
}
// The auth middleware uses the JWT middleware to parse and validate a JWT.
// If that does not succeed, it generates a JWT token from the identity-aware proxy
func Middleware() echo.MiddlewareFunc {
// Create a noop next function to let us run middlewares without jumping to the next
// one in the chain
noOpNext := func(_ echo.Context) error {
return nil
}
jwtMiddleware := middleware.JWTWithConfig(GetJWTConfig())
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// First attempt to get auth from a provided JWT
jwtErr := jwtMiddleware(noOpNext)(c)
if c.Get(authTokenJWTContextKey) != nil && jwtErr == nil {
// If it succeeded, use the authClaims from the JWT
// and continue in the middleware chain
jwtinf := c.Get(authTokenJWTContextKey).(*jwt.Token)
claims := jwtinf.Claims.(*AuthClaims)
c.Set(AuthClaimsContextKey, claims)
return next(c)
}
// Otherwise, attempt to get auth from authMiddlewares
for _, authMiddleware := range authMiddlewares {
err := authMiddleware(noOpNext)(c)
if c.Get(AuthClaimsContextKey) != nil && err == nil {
// If it succeeded, continue in the middleware chain
return next(c)
}
}
// Otherwise, return the original error from jwt middleware
return jwtErr
}
}
}

View File

@ -55,7 +55,6 @@ import (
"code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/modules/auth" "code.vikunja.io/api/pkg/modules/auth"
"code.vikunja.io/api/pkg/modules/auth/identityawareproxy"
"code.vikunja.io/api/pkg/modules/auth/openid" "code.vikunja.io/api/pkg/modules/auth/openid"
"code.vikunja.io/api/pkg/modules/background" "code.vikunja.io/api/pkg/modules/background"
backgroundHandler "code.vikunja.io/api/pkg/modules/background/handler" backgroundHandler "code.vikunja.io/api/pkg/modules/background/handler"
@ -251,19 +250,9 @@ func registerAPIRoutes(a *echo.Group) {
n.POST("/shares/:share/auth", apiv1.AuthenticateLinkShare) n.POST("/shares/:share/auth", apiv1.AuthenticateLinkShare)
} }
// Identity-Aware Proxy auth, requires the same iap middleware as authenticated routes
if config.AuthIdentityAwareProxyEnabled.GetBool() {
m := n.Group("")
m.Use(identityawareproxy.Middleware())
m.GET("/auth/identityawareproxy/token", identityawareproxy.GetToken)
}
// ===== Routes with Authentication ===== // ===== Routes with Authentication =====
// Authentification // Authentification
a.Use(middleware.JWTWithConfig(auth.GetJWTConfig())) a.Use(auth.Middleware())
if config.AuthIdentityAwareProxyEnabled.GetBool() {
a.Use(identityawareproxy.Middleware())
}
// Rate limit // Rate limit
setupRateLimit(a, config.RateLimitKind.GetString()) setupRateLimit(a, config.RateLimitKind.GetString())

View File

@ -1340,7 +1340,8 @@ paths:
get: get:
consumes: consumes:
- N/A - N/A
description: Generates a short-lived JWT based on the identity from the identity-aware proxy in order to provide the front-end with user id and username info description: Generates a short-lived JWT based on the identity from the identity-aware
proxy in order to provide the front-end with user id and username info
produces: produces:
- application/json - application/json
responses: responses: