| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- package auth
- import (
- "crypto/subtle"
- "strings"
- types "github.com/OliveTin/OliveTin/internal/auth/authpublic"
- "github.com/OliveTin/OliveTin/internal/config"
- log "github.com/sirupsen/logrus"
- )
- const localBearerScheme = "Bearer"
- func constantTimeEqualString(a, b string) bool {
- if len(a) != len(b) {
- return false
- }
- return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
- }
- func bearerTokenFromAuthorizationHeader(authz string) (string, bool) {
- idx := strings.IndexByte(authz, ' ')
- if idx <= 0 {
- return "", false
- }
- if !strings.EqualFold(authz[:idx], localBearerScheme) {
- return "", false
- }
- token := strings.TrimSpace(authz[idx+1:])
- if token == "" {
- return "", false
- }
- return token, true
- }
- func localUserHasAPIKey(user *config.LocalUser) bool {
- return user != nil && user.ApiKey != ""
- }
- func findLocalUserByAPIKey(cfg *config.Config, token string) *config.LocalUser {
- for _, user := range cfg.AuthLocalUsers.Users {
- if !localUserHasAPIKey(user) {
- continue
- }
- if constantTimeEqualString(token, user.ApiKey) {
- return user
- }
- }
- return nil
- }
- func localBearerAuthorizationHasEmptyCredential(authz string) bool {
- idx := strings.IndexByte(authz, ' ')
- return idx > 0 &&
- strings.EqualFold(authz[:idx], localBearerScheme) &&
- strings.TrimSpace(authz[idx+1:]) == ""
- }
- func logLocalBearerAPIKeyParseFailure(authz string) {
- if strings.TrimSpace(authz) == "" {
- return
- }
- if localBearerAuthorizationHasEmptyCredential(authz) {
- log.Debugf("Local bearer API key: rejected (empty credential after Bearer prefix)")
- return
- }
- log.Tracef("Local bearer API key: skipped (Authorization is not a Bearer token)")
- }
- func checkUserFromLocalBearerApiKey(context *types.AuthCheckingContext) *types.AuthenticatedUser {
- if !context.Config.AuthLocalUsers.Enabled {
- log.Tracef("Local bearer API key: skipped (authLocalUsers disabled)")
- return nil
- }
- authz := context.Request.Header.Get("Authorization")
- token, ok := bearerTokenFromAuthorizationHeader(authz)
- if !ok {
- logLocalBearerAPIKeyParseFailure(authz)
- return nil
- }
- log.Debugf("Local bearer API key: checking configured local user API keys")
- user := findLocalUserByAPIKey(context.Config, token)
- if user == nil {
- log.Debugf("Local bearer API key: rejected (no matching local user)")
- return nil
- }
- log.WithFields(log.Fields{
- "username": user.Username,
- "usergroup": user.Usergroup,
- }).Debugf("Local bearer API key: authenticated")
- return &types.AuthenticatedUser{
- Username: user.Username,
- UsergroupLine: user.Usergroup,
- Provider: "local",
- }
- }
|