fix(auth): don't panic on /token/test with API token
The JWT skipper bypassed validation entirely for /token/test when the bearer was an API token, leaving "user" unset in the context. CheckToken then type-asserted it to *jwt.Token and panicked. Validate the API token in the skipper but skip the route permission check (since /token/test is not exposed in the API token route registry, no token can hold explicit permission for it). Drop the now-redundant JWT assertion in CheckToken — auth has already passed by the time the handler runs.
This commit is contained in:
parent
01fff665c6
commit
3d75ca049b
|
|
@ -19,20 +19,13 @@ package v1
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/labstack/echo/v5"
|
||||
)
|
||||
|
||||
// CheckToken checks prints a message if the token is valid or not. Currently only used for testing purposes.
|
||||
// CheckToken returns 418 if the bearer token is valid. Used for testing.
|
||||
func CheckToken(c *echo.Context) error {
|
||||
|
||||
user := c.Get("user").(*jwt.Token)
|
||||
|
||||
log.Debugf("token valid: %t", user.Valid)
|
||||
|
||||
return c.JSON(418, models.Message{Message: "🍵"})
|
||||
return c.JSON(http.StatusTeapot, models.Message{Message: "🍵"})
|
||||
}
|
||||
|
||||
// TestToken returns a simple test message. Used for testing purposes.
|
||||
|
|
|
|||
|
|
@ -46,11 +46,8 @@ func SetupTokenMiddleware() echo.MiddlewareFunc {
|
|||
|
||||
for _, s := range authHeader {
|
||||
if strings.HasPrefix(s, "Bearer "+models.APITokenPrefix) {
|
||||
if c.Request().URL.Path == "/api/v1/token/test" {
|
||||
return true
|
||||
}
|
||||
|
||||
err := checkAPITokenAndPutItInContext(s, c)
|
||||
skipRouteCheck := c.Request().URL.Path == "/api/v1/token/test"
|
||||
err := checkAPITokenAndPutItInContext(s, c, skipRouteCheck)
|
||||
return err == nil
|
||||
}
|
||||
}
|
||||
|
|
@ -71,14 +68,14 @@ func SetupTokenMiddleware() echo.MiddlewareFunc {
|
|||
})
|
||||
}
|
||||
|
||||
func checkAPITokenAndPutItInContext(tokenHeaderValue string, c *echo.Context) error {
|
||||
func checkAPITokenAndPutItInContext(tokenHeaderValue string, c *echo.Context, skipRouteCheck bool) error {
|
||||
token, u, err := auth.ValidateAPITokenString(strings.TrimPrefix(tokenHeaderValue, "Bearer "))
|
||||
if err != nil {
|
||||
log.Debugf("[auth] API token validation failed: %v", err)
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||
}
|
||||
|
||||
if !models.CanDoAPIRoute(c, token) {
|
||||
if !skipRouteCheck && !models.CanDoAPIRoute(c, token) {
|
||||
log.Debugf("[auth] Tried authenticating with token %d but it does not have permission to do this route", token.ID)
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue