feat: accept API tokens for CalDAV basic auth

This commit is contained in:
kolaente
2026-03-26 11:31:47 +01:00
committed by kolaente
parent ebec91b356
commit 6207705928

View File

@@ -18,9 +18,12 @@ package caldav
import (
"errors"
"strings"
"time"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/user"
"xorm.io/xorm"
@@ -28,10 +31,62 @@ import (
"golang.org/x/crypto/bcrypt"
)
func checkAPIToken(s *xorm.Session, username, token string) (*user.User, error) {
apiToken, err := models.GetTokenFromTokenString(s, token)
if err != nil {
if models.IsErrAPITokenInvalid(err) {
log.Debugf("[caldav auth] Invalid API token provided for user %s", username)
return nil, nil
}
return nil, err
}
if time.Now().After(apiToken.ExpiresAt) {
log.Debugf("[caldav auth] API token %d has expired", apiToken.ID)
return nil, nil
}
if !apiToken.HasCaldavAccess() {
log.Debugf("[caldav auth] API token %d does not have caldav access permission", apiToken.ID)
return nil, nil
}
u, err := user.GetUserByID(s, apiToken.OwnerID)
if err != nil {
if user.IsErrUserStatusError(err) {
log.Debugf("[caldav auth] API token %d owner account is disabled or locked", apiToken.ID)
return nil, nil
}
return nil, err
}
if u.Username != username {
log.Debugf("[caldav auth] API token %d owner %s does not match provided username %s", apiToken.ID, u.Username, username)
return nil, nil
}
return u, nil
}
func BasicAuth(c *echo.Context, username, password string) (bool, error) {
s := db.NewSession()
defer s.Close()
// If the password looks like an API token, validate it as one.
// Don't fall through to other auth methods — tk_ prefix is unambiguous.
if strings.HasPrefix(password, models.APITokenPrefix) {
u, err := checkAPIToken(s, username, password)
if err != nil {
log.Errorf("Error during API token auth for caldav: %v", err)
return false, nil
}
if u != nil {
c.Set("userBasicAuth", u)
return true, nil
}
return false, nil
}
credentials := &user.Login{
Username: username,
Password: password,