mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 04:57:37 +03:00
Upgrade to go-chi 5
This commit is contained in:
parent
fb5840705e
commit
7d96167abc
12 changed files with 107 additions and 81 deletions
2
Makefile
2
Makefile
|
@ -28,7 +28,7 @@ watch: ##@Development Start Go tests in watch mode (re-run when code changes)
|
|||
.PHONY: watch
|
||||
|
||||
test: ##@Development Run Go tests
|
||||
go test ./... -v
|
||||
go test ./...
|
||||
.PHONY: test
|
||||
|
||||
testall: test ##@Development Run Go and JS tests
|
||||
|
|
|
@ -2,12 +2,11 @@ package auth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/go-chi/jwtauth"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
|
@ -33,12 +32,16 @@ func InitTokenAuth(ds model.DataStore) {
|
|||
}
|
||||
|
||||
func CreateToken(u *model.User) (string, error) {
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
claims["iss"] = consts.JWTIssuer
|
||||
claims["sub"] = u.UserName
|
||||
claims := map[string]interface{}{}
|
||||
claims[jwt.IssuerKey] = consts.JWTIssuer
|
||||
claims[jwt.IssuedAtKey] = time.Now().UTC().Unix()
|
||||
claims[jwt.SubjectKey] = u.UserName
|
||||
claims["uid"] = u.ID
|
||||
claims["adm"] = u.IsAdmin
|
||||
token, _, err := TokenAuth.Encode(claims)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return TouchToken(token)
|
||||
}
|
||||
|
@ -51,29 +54,23 @@ func getSessionTimeOut() time.Duration {
|
|||
return sessionTimeOut
|
||||
}
|
||||
|
||||
func TouchToken(token *jwt.Token) (string, error) {
|
||||
timeout := getSessionTimeOut()
|
||||
expireIn := time.Now().Add(timeout).Unix()
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
claims["exp"] = expireIn
|
||||
|
||||
return token.SignedString(Secret)
|
||||
}
|
||||
|
||||
func keyFunc(token *jwt.Token) (interface{}, error) {
|
||||
// Don't forget to validate the alg is what you expect:
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
func TouchToken(token jwt.Token) (string, error) {
|
||||
claims, err := token.AsMap(context.Background())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
|
||||
return Secret, nil
|
||||
timeout := getSessionTimeOut()
|
||||
claims[jwt.ExpirationKey] = time.Now().UTC().Add(timeout).Unix()
|
||||
_, newToken, err := TokenAuth.Encode(claims)
|
||||
|
||||
return newToken, err
|
||||
}
|
||||
|
||||
func Validate(tokenStr string) (jwt.MapClaims, error) {
|
||||
token, err := jwt.Parse(tokenStr, keyFunc)
|
||||
func Validate(tokenStr string) (map[string]interface{}, error) {
|
||||
token, err := jwtauth.VerifyToken(TokenAuth, tokenStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return token.Claims.(jwt.MapClaims), err
|
||||
return token.AsMap(context.Background())
|
||||
}
|
||||
|
|
|
@ -4,14 +4,12 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/navidrome/navidrome/core/auth"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
@ -34,35 +32,37 @@ var _ = Describe("Auth", func() {
|
|||
|
||||
BeforeEach(func() {
|
||||
auth.Secret = []byte(testJWTSecret)
|
||||
auth.TokenAuth = jwtauth.New("HS256", auth.Secret, nil)
|
||||
})
|
||||
|
||||
Describe("Validate", func() {
|
||||
It("returns error with an invalid JWT token", func() {
|
||||
_, err := auth.Validate("invalid.token")
|
||||
Expect(err).To(Not(BeNil()))
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the claims from a valid JWT token", func() {
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
claims := map[string]interface{}{}
|
||||
claims["iss"] = "issuer"
|
||||
claims["iat"] = time.Now().Unix()
|
||||
claims["exp"] = time.Now().Add(1 * time.Minute).Unix()
|
||||
tokenStr, _ := token.SignedString(auth.Secret)
|
||||
_, tokenStr, err := auth.TokenAuth.Encode(claims)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
decodedClaims, err := auth.Validate(tokenStr)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(decodedClaims["iss"]).To(Equal("issuer"))
|
||||
})
|
||||
|
||||
It("returns ErrExpired if the `exp` field is in the past", func() {
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
claims := map[string]interface{}{}
|
||||
claims["iss"] = "issuer"
|
||||
claims["exp"] = time.Now().Add(-1 * time.Minute).Unix()
|
||||
tokenStr, _ := token.SignedString(auth.Secret)
|
||||
_, tokenStr, err := auth.TokenAuth.Encode(claims)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err := auth.Validate(tokenStr)
|
||||
Expect(err).To(MatchError("Token is expired"))
|
||||
_, err = auth.Validate(tokenStr)
|
||||
Expect(err).To(MatchError("token is expired"))
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -74,36 +74,35 @@ var _ = Describe("Auth", func() {
|
|||
IsAdmin: true,
|
||||
}
|
||||
tokenStr, err := auth.CreateToken(u)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
claims, err := auth.Validate(tokenStr)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(claims["iss"]).To(Equal(consts.JWTIssuer))
|
||||
Expect(claims["sub"]).To(Equal("johndoe"))
|
||||
Expect(claims["uid"]).To(Equal("123"))
|
||||
Expect(claims["adm"]).To(Equal(true))
|
||||
|
||||
exp := time.Unix(int64(claims["exp"].(float64)), 0)
|
||||
Expect(exp).To(BeTemporally(">", time.Now()))
|
||||
Expect(claims["exp"]).To(BeTemporally(">", time.Now()))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("TouchToken", func() {
|
||||
It("updates the expiration time", func() {
|
||||
yesterday := time.Now().Add(-oneDay)
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
claims := map[string]interface{}{}
|
||||
claims["iss"] = "issuer"
|
||||
claims["exp"] = yesterday.Unix()
|
||||
token, _, err := auth.TokenAuth.Encode(claims)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
touched, err := auth.TouchToken(token)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
decodedClaims, err := auth.Validate(touched)
|
||||
Expect(err).To(BeNil())
|
||||
expiration := time.Unix(int64(decodedClaims["exp"].(float64)), 0)
|
||||
Expect(expiration.Sub(yesterday)).To(BeNumerically(">=", oneDay))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
exp := decodedClaims["exp"].(time.Time)
|
||||
Expect(exp.Sub(yesterday)).To(BeNumerically(">=", oneDay))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
8
go.mod
8
go.mod
|
@ -12,20 +12,20 @@ require (
|
|||
github.com/cespare/reflex v0.3.0
|
||||
github.com/deluan/rest v0.0.0-20210503015435-e7091d44f0ba
|
||||
github.com/denisenkom/go-mssqldb v0.9.0 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/dhowden/tag v0.0.0-20200412032933-5d76b8eaae27
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/djherbis/fscache v0.10.2-0.20201024185917-a0daa9e52747
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/go-chi/chi v1.5.1
|
||||
github.com/go-chi/cors v1.1.1
|
||||
github.com/go-chi/chi/v5 v5.0.3
|
||||
github.com/go-chi/cors v1.2.0
|
||||
github.com/go-chi/httprate v0.4.0
|
||||
github.com/go-chi/jwtauth v4.0.4+incompatible
|
||||
github.com/go-chi/jwtauth/v5 v5.0.1
|
||||
github.com/golangci/golangci-lint v1.40.0
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/google/wire v0.5.0
|
||||
github.com/kennygrant/sanitize v0.0.0-20170120101633-6a0bfdde8629
|
||||
github.com/kr/pretty v0.2.1
|
||||
github.com/lestrrat-go/jwx v1.1.6
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/microcosm-cc/bluemonday v1.0.9
|
||||
github.com/mitchellh/mapstructure v1.3.2 // indirect
|
||||
|
|
37
go.sum
37
go.sum
|
@ -152,13 +152,16 @@ github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8=
|
||||
github.com/deluan/rest v0.0.0-20210503015435-e7091d44f0ba h1:soWusRLgeSlkpw7rWUVrNd9COIVmazDBWfyK0HAcVPU=
|
||||
github.com/deluan/rest v0.0.0-20210503015435-e7091d44f0ba/go.mod h1:tSgDythFsl0QgS/PFWfIZqcJKnkADWneY80jaVRlqK8=
|
||||
github.com/denis-tingajkin/go-header v0.4.2 h1:jEeSF4sdv8/3cT/WY8AgDHUoItNSoEZ7qg9dX7pc218=
|
||||
github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA=
|
||||
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
|
||||
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
|
@ -194,14 +197,15 @@ github.com/fzipp/gocyclo v0.3.1 h1:A9UeX3HJSXTBzvHzhqoYVuE0eAhe+aM8XBCCwsPMZOc=
|
|||
github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||
github.com/go-chi/chi v1.5.1 h1:kfTK3Cxd/dkMu/rKs5ZceWYp+t5CtiE7vmaTv3LjC6w=
|
||||
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
|
||||
github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw=
|
||||
github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||
github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4=
|
||||
github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
|
||||
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/httprate v0.4.0 h1:M2qVV0w6ksgLs6L8lTrvqNeaVm0ZJNVdbYM8u2T8HaE=
|
||||
github.com/go-chi/httprate v0.4.0/go.mod h1:7e7qjQtHzEbdyW5TYQrl4X2uNRCnlTajictc7B4ftgc=
|
||||
github.com/go-chi/jwtauth v4.0.4+incompatible h1:LGIxg6YfvSBzxU2BljXbrzVc1fMlgqSKBQgKOGAVtPY=
|
||||
github.com/go-chi/jwtauth v4.0.4+incompatible/go.mod h1:Q5EIArY/QnD6BdS+IyDw7B2m6iNbnPxtfd6/BcmtWbs=
|
||||
github.com/go-chi/jwtauth/v5 v5.0.1 h1:eyJ6Yx5VphEfjkqpZ7+LJEWThzyIcF5aN2QVpgqSIu0=
|
||||
github.com/go-chi/jwtauth/v5 v5.0.1/go.mod h1:+JtcRYGZsnA4+ur1LFlb4Bei3O9WeUzoMfDZWfUJuoY=
|
||||
github.com/go-critic/go-critic v0.5.6 h1:siUR1+322iVikWXoV75I1YRfNaC/yaLzhdF9Zwd8Tus=
|
||||
github.com/go-critic/go-critic v0.5.6/go.mod h1:cVjj0DfqewQVIlIAGexPCaGaZDAqGE29PYDDADIVNEo=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
|
@ -242,6 +246,8 @@ github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4
|
|||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/goccy/go-json v0.4.8 h1:TfwOxfSp8hXH+ivoOk36RyDNmXATUETRdaNWDaZglf8=
|
||||
github.com/goccy/go-json v0.4.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
|
||||
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
|
@ -471,6 +477,20 @@ github.com/ldez/gomoddirectives v0.2.1/go.mod h1:sGicqkRgBOg//JfpXwkB9Hj0X5RyJ7m
|
|||
github.com/ldez/tagliatelle v0.2.0 h1:693V8Bf1NdShJ8eu/s84QySA0J2VWBanVBa2WwXD/Wk=
|
||||
github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88=
|
||||
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||
github.com/lestrrat-go/codegen v1.0.0/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=
|
||||
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
|
||||
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
|
||||
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||
github.com/lestrrat-go/jwx v1.1.6 h1:VfyUo2PAU4lO/liwhdwiSZ55/QZDLTT3EYY5z9KfwZs=
|
||||
github.com/lestrrat-go/jwx v1.1.6/go.mod h1:c+R8G7qsaFNmTzYjU98A+sMh8Bo/MJqO9GnpqR+X024=
|
||||
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.1 h1:3G5sX/aw/TbMTtVc9U7IHBWRZtMvwvBziF1e4HoQtv8=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4=
|
||||
github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
|
@ -815,6 +835,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
|
@ -1061,6 +1082,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||
golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
|
@ -1073,6 +1095,7 @@ golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1-0.20210430200834-7a6108e9b210 h1:pPyaiOWQiSDX1de9ibfdQGlkYAIA5M3RX7dfpujuUVQ=
|
||||
golang.org/x/tools v0.1.1-0.20210430200834-7a6108e9b210/go.mod h1:q7cPXv+8VGj9Sx5ckHx2nzMtCSaZFrowzWpjN/cwVb8=
|
||||
|
|
|
@ -7,11 +7,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/deluan/rest"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/httprate"
|
||||
"github.com/go-chi/jwtauth"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/core/auth"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/server/events"
|
||||
|
@ -55,7 +53,7 @@ func (app *Router) routes(path string) http.Handler {
|
|||
|
||||
r.Route("/api", func(r chi.Router) {
|
||||
r.Use(mapAuthHeader())
|
||||
r.Use(jwtauth.Verifier(auth.TokenAuth))
|
||||
r.Use(verifier())
|
||||
r.Use(authenticator(app.ds))
|
||||
app.R(r, "/user", model.User{}, true)
|
||||
app.R(r, "/song", model.MediaFile{}, true)
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/deluan/rest"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/go-chi/jwtauth"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/core/auth"
|
||||
|
@ -149,16 +149,16 @@ func validateLogin(userRepo model.UserRepository, userName, password string) (*m
|
|||
return u, nil
|
||||
}
|
||||
|
||||
func contextWithUser(ctx context.Context, ds model.DataStore, claims jwt.MapClaims) context.Context {
|
||||
userName := claims["sub"].(string)
|
||||
func contextWithUser(ctx context.Context, ds model.DataStore, token jwt.Token) context.Context {
|
||||
userName := token.Subject()
|
||||
user, _ := ds.User(ctx).FindByUsername(userName)
|
||||
return request.WithUser(ctx, *user)
|
||||
}
|
||||
|
||||
func getToken(ds model.DataStore, ctx context.Context) (*jwt.Token, error) {
|
||||
func getToken(ds model.DataStore, ctx context.Context) (jwt.Token, error) {
|
||||
token, claims, err := jwtauth.FromContext(ctx)
|
||||
|
||||
valid := err == nil && token != nil && token.Valid
|
||||
valid := err == nil && token != nil
|
||||
valid = valid && claims["sub"] != nil
|
||||
if valid {
|
||||
return token, nil
|
||||
|
@ -183,6 +183,12 @@ func mapAuthHeader() func(next http.Handler) http.Handler {
|
|||
}
|
||||
}
|
||||
|
||||
func verifier() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return jwtauth.Verify(auth.TokenAuth, jwtauth.TokenFromHeader, jwtauth.TokenFromCookie, jwtauth.TokenFromQuery)(next)
|
||||
}
|
||||
}
|
||||
|
||||
func authenticator(ds model.DataStore) func(next http.Handler) http.Handler {
|
||||
auth.InitTokenAuth(ds)
|
||||
|
||||
|
@ -198,9 +204,7 @@ func authenticator(ds model.DataStore) func(next http.Handler) http.Handler {
|
|||
return
|
||||
}
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
|
||||
newCtx := contextWithUser(r.Context(), ds, claims)
|
||||
newCtx := contextWithUser(r.Context(), ds, token)
|
||||
newTokenString, err := auth.TouchToken(token)
|
||||
if err != nil {
|
||||
log.Error(r, "signing new token", err)
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/deluan/rest"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/unrolled/secure"
|
||||
)
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"net/http"
|
||||
"path"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/go-chi/cors"
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"net/http"
|
||||
"runtime"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/core"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
|
|
|
@ -6,7 +6,9 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/core"
|
||||
"github.com/navidrome/navidrome/core/auth"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
|
@ -268,6 +270,9 @@ var _ = Describe("Middlewares", func() {
|
|||
Context("JWT based authentication", func() {
|
||||
var validToken string
|
||||
BeforeEach(func() {
|
||||
auth.InitTokenAuth(ds)
|
||||
conf.Server.SessionTimeout = time.Minute
|
||||
|
||||
u := &model.User{UserName: "admin"}
|
||||
var err error
|
||||
validToken, err = auth.CreateToken(u)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue