diff --git a/auth/authentication.go b/auth/authentication.go index fbe183d..397d077 100644 --- a/auth/authentication.go +++ b/auth/authentication.go @@ -2,10 +2,10 @@ package auth import ( "errors" - "github.com/gin-gonic/gin" "github.com/gotify/server/v2/auth/password" "github.com/gotify/server/v2/model" + "strings" ) const ( @@ -82,7 +82,9 @@ func (a *Auth) RequireApplicationToken() gin.HandlerFunc { func (a *Auth) tokenFromQueryOrHeader(ctx *gin.Context) string { if token := a.tokenFromQuery(ctx); token != "" { return token - } else if token := a.tokenFromHeader(ctx); token != "" { + } else if token := a.tokenFromXGotifyHeader(ctx); token != "" { + return token + } else if token := a.tokenFromAuthorizationHeader(ctx); token != "" { return token } return "" @@ -92,10 +94,25 @@ func (a *Auth) tokenFromQuery(ctx *gin.Context) string { return ctx.Request.URL.Query().Get("token") } -func (a *Auth) tokenFromHeader(ctx *gin.Context) string { +func (a *Auth) tokenFromXGotifyHeader(ctx *gin.Context) string { return ctx.Request.Header.Get(headerName) } +func (a *Auth) tokenFromAuthorizationHeader(ctx *gin.Context) string { + const prefix = "Bearer " + + authHeader := ctx.Request.Header.Get("Authorization") + if authHeader == "" { + return "" + } + + if len(authHeader) < len(prefix) || !strings.EqualFold(prefix, authHeader[:len(prefix)]) { + return "" + } + + return authHeader[len(prefix):] +} + func (a *Auth) userFromBasicAuth(ctx *gin.Context) (*model.User, error) { if name, pass, ok := ctx.Request.BasicAuth(); ok { if user, err := a.DB.GetUserByName(name); err != nil { diff --git a/auth/authentication_test.go b/auth/authentication_test.go index 84a260b..374f63d 100644 --- a/auth/authentication_test.go +++ b/auth/authentication_test.go @@ -104,16 +104,6 @@ func (s *AuthenticationSuite) TestHeaderApiKeyToken() { s.assertHeaderRequest("X-Gotify-Key", "ergerogerg", s.auth.RequireClient, 401) s.assertHeaderRequest("X-Gotify-Key", "ergerogerg", s.auth.RequireAdmin, 401) - // no authentication schema - s.assertHeaderRequest("Authorization", "ergerogerg", s.auth.RequireApplicationToken, 401) - s.assertHeaderRequest("Authorization", "ergerogerg", s.auth.RequireClient, 401) - s.assertHeaderRequest("Authorization", "ergerogerg", s.auth.RequireAdmin, 401) - - // wrong authentication schema - s.assertHeaderRequest("Authorization", "ApiKeyx clienttoken", s.auth.RequireApplicationToken, 401) - s.assertHeaderRequest("Authorization", "ApiKeyx clienttoken", s.auth.RequireClient, 401) - s.assertHeaderRequest("Authorization", "ApiKeyx clienttoken", s.auth.RequireAdmin, 401) - // not existing key s.assertHeaderRequest("X-Gotify-Keyx", "clienttoken", s.auth.RequireApplicationToken, 401) s.assertHeaderRequest("X-Gotify-Keyx", "clienttoken", s.auth.RequireClient, 401) @@ -136,6 +126,39 @@ func (s *AuthenticationSuite) TestHeaderApiKeyToken() { s.assertHeaderRequest("X-Gotify-Key", "clienttoken_admin", s.auth.RequireAdmin, 200) } +func (s *AuthenticationSuite) TestAuthorizationHeaderApiKeyToken() { + // not existing token + s.assertHeaderRequest("Authorization", "Bearer ergerogerg", s.auth.RequireApplicationToken, 401) + s.assertHeaderRequest("Authorization", "Bearer ergerogerg", s.auth.RequireClient, 401) + s.assertHeaderRequest("Authorization", "Bearer ergerogerg", s.auth.RequireAdmin, 401) + + // no authentication schema + s.assertHeaderRequest("Authorization", "ergerogerg", s.auth.RequireApplicationToken, 401) + s.assertHeaderRequest("Authorization", "ergerogerg", s.auth.RequireClient, 401) + s.assertHeaderRequest("Authorization", "ergerogerg", s.auth.RequireAdmin, 401) + + // wrong authentication schema + s.assertHeaderRequest("Authorization", "ApiKeyx clienttoken", s.auth.RequireApplicationToken, 401) + s.assertHeaderRequest("Authorization", "ApiKeyx clienttoken", s.auth.RequireClient, 401) + s.assertHeaderRequest("Authorization", "ApiKeyx clienttoken", s.auth.RequireAdmin, 401) + + // Authorization Bearer apptoken + s.assertHeaderRequest("Authorization", "Bearer apptoken", s.auth.RequireApplicationToken, 200) + s.assertHeaderRequest("Authorization", "Bearer apptoken", s.auth.RequireClient, 401) + s.assertHeaderRequest("Authorization", "Bearer apptoken", s.auth.RequireAdmin, 401) + s.assertHeaderRequest("Authorization", "Bearer apptoken_admin", s.auth.RequireApplicationToken, 200) + s.assertHeaderRequest("Authorization", "Bearer apptoken_admin", s.auth.RequireClient, 401) + s.assertHeaderRequest("Authorization", "Bearer apptoken_admin", s.auth.RequireAdmin, 401) + + // Authorization Bearer clienttoken + s.assertHeaderRequest("Authorization", "Bearer clienttoken", s.auth.RequireApplicationToken, 401) + s.assertHeaderRequest("Authorization", "Bearer clienttoken", s.auth.RequireClient, 200) + s.assertHeaderRequest("Authorization", "Bearer clienttoken", s.auth.RequireAdmin, 403) + s.assertHeaderRequest("Authorization", "bearer clienttoken_admin", s.auth.RequireApplicationToken, 401) + s.assertHeaderRequest("Authorization", "bearer clienttoken_admin", s.auth.RequireClient, 200) + s.assertHeaderRequest("Authorization", "bearer clienttoken_admin", s.auth.RequireAdmin, 200) +} + func (s *AuthenticationSuite) TestBasicAuth() { s.assertHeaderRequest("Authorization", "Basic ergerogerg", s.auth.RequireApplicationToken, 401) s.assertHeaderRequest("Authorization", "Basic ergerogerg", s.auth.RequireClient, 401)