diff --git a/_example/go.mod b/_example/go.mod index 2353172c..b0fec951 100644 --- a/_example/go.mod +++ b/_example/go.mod @@ -15,7 +15,7 @@ require ( ) require ( - cloud.google.com/go/compute/metadata v0.4.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect github.com/dghubble/oauth1 v0.7.3 // indirect github.com/go-pkgz/repeater v1.1.3 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -34,12 +34,12 @@ require ( github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.etcd.io/bbolt v1.3.10 // indirect go.mongodb.org/mongo-driver v1.16.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/image v0.18.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect ) diff --git a/_example/go.sum b/_example/go.sum index 8fd4aede..3d6a0423 100644 --- a/_example/go.sum +++ b/_example/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= -cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -145,10 +145,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= -github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo= -github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= @@ -160,11 +158,10 @@ go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -172,7 +169,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -180,8 +176,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -193,7 +189,6 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -208,8 +203,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/_example/main.go b/_example/main.go index 2a2e42dc..3dd315c8 100644 --- a/_example/main.go +++ b/_example/main.go @@ -22,7 +22,7 @@ import ( log "github.com/go-pkgz/lgr" "github.com/go-pkgz/rest" "github.com/go-pkgz/rest/logger" - "github.com/golang-jwt/jwt" + oldjwt "github.com/golang-jwt/jwt" "golang.org/x/oauth2" "github.com/go-pkgz/auth" @@ -295,7 +295,7 @@ func initGoauth2Srv() *goauth2.Server { manager.MustTokenStorage(store.NewMemoryTokenStore()) // generate jwt access token - manager.MapAccessGenerate(generates.NewJWTAccessGenerate("custom", []byte("00000000"), jwt.SigningMethodHS512)) + manager.MapAccessGenerate(generates.NewJWTAccessGenerate("custom", []byte("00000000"), oldjwt.SigningMethodHS512)) // client memory store clientStore := store.NewClientStore() diff --git a/go.mod b/go.mod index 24acb60f..11e90517 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( ) require ( - cloud.google.com/go/compute/metadata v0.4.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect @@ -26,7 +26,7 @@ require ( github.com/montanaflynn/stats v0.7.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/tidwall/btree v1.7.0 // indirect - github.com/tidwall/buntdb v1.3.0 // indirect + github.com/tidwall/buntdb v1.3.1 // indirect github.com/tidwall/gjson v1.17.1 // indirect github.com/tidwall/grect v0.1.4 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -36,11 +36,11 @@ require ( github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/net v0.26.0 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8cadc79b..b99556b3 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= -cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -102,8 +102,8 @@ github.com/tidwall/btree v0.0.0-20191029221954-400434d76274/go.mod h1:huei1BkDWJ github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/buntdb v1.1.2/go.mod h1:xAzi36Hir4FarpSHyfuZ6JzPJdjRZ8QlLZSntE2mqlI= -github.com/tidwall/buntdb v1.3.0 h1:gdhWO+/YwoB2qZMeAU9JcWWsHSYU3OvcieYgFRS0zwA= -github.com/tidwall/buntdb v1.3.0/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU= +github.com/tidwall/buntdb v1.3.1 h1:HKoDF01/aBhl9RjYtbaLnvX9/OuenwvQiC3OP1CcL4o= +github.com/tidwall/buntdb v1.3.1/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU= github.com/tidwall/gjson v1.3.4/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= @@ -145,10 +145,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= -github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo= -github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= @@ -160,11 +158,10 @@ go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -172,7 +169,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -180,8 +176,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -193,7 +189,6 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -208,8 +203,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/provider/telegram_test.go b/provider/telegram_test.go index 5121c7cd..12afe070 100644 --- a/provider/telegram_test.go +++ b/provider/telegram_test.go @@ -108,10 +108,20 @@ func TestTelegramConfirmedRequest(t *testing.T) { return &upd, nil }, AvatarFunc: func(ctx context.Context, userID int) (string, error) { + select { + case <-ctx.Done(): + return "", ctx.Err() + default: + } assert.Equal(t, 313131313, userID) return "http://t.me/avatar.png", nil }, SendFunc: func(ctx context.Context, id int, text string) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } assert.Equal(t, 313131313, id) assert.Equal(t, "success", text) return nil @@ -213,10 +223,20 @@ func TestTelegram_ProcessUpdateFlow(t *testing.T) { return &telegramUpdate{}, nil }, SendFunc: func(ctx context.Context, id int, text string) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } assert.Equal(t, 313131313, id) return nil }, AvatarFunc: func(ctx context.Context, userID int) (string, error) { + select { + case <-ctx.Done(): + return "", ctx.Err() + default: + } assert.Equal(t, 313131313, userID) return "http://t.me/avatar.png", nil }, diff --git a/v2/auth.go b/v2/auth.go index d7e854d0..b3ac141a 100644 --- a/v2/auth.go +++ b/v2/auth.go @@ -46,14 +46,15 @@ type Opts struct { DisableIAT bool // disable IssuedAt claim // optional (custom) names for cookies and headers - JWTCookieName string // default "JWT" - JWTCookieDomain string // default empty - JWTHeaderKey string // default "X-JWT" - XSRFCookieName string // default "XSRF-TOKEN" - XSRFHeaderKey string // default "X-XSRF-TOKEN" - JWTQuery string // default "token" - SendJWTHeader bool // if enabled send JWT as a header instead of cookie - SameSiteCookie http.SameSite // limit cross-origin requests with SameSite cookie attribute + JWTCookieName string // default "JWT" + JWTCookieDomain string // default empty + JWTHeaderKey string // default "X-JWT" + XSRFCookieName string // default "XSRF-TOKEN" + XSRFHeaderKey string // default "X-XSRF-TOKEN" + XSRFIgnoreMethods []string // disable XSRF protection for the specified request methods (ex. []string{"GET", "POST")}, default empty + JWTQuery string // default "token" + SendJWTHeader bool // if enabled send JWT as a header instead of cookie + SameSiteCookie http.SameSite // limit cross-origin requests with SameSite cookie attribute Issuer string // optional value for iss claim, usually the application name, default "go-pkgz/auth" diff --git a/v2/go.mod b/v2/go.mod index d31e5fe4..5d36f3e5 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -9,6 +9,7 @@ require ( github.com/go-pkgz/repeater v1.1.3 github.com/go-pkgz/rest v1.19.0 github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d github.com/stretchr/testify v1.9.0 go.etcd.io/bbolt v1.3.10 @@ -18,7 +19,7 @@ require ( ) require ( - cloud.google.com/go/compute/metadata v0.4.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect @@ -26,7 +27,7 @@ require ( github.com/montanaflynn/stats v0.7.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/tidwall/btree v1.7.0 // indirect - github.com/tidwall/buntdb v1.3.0 // indirect + github.com/tidwall/buntdb v1.3.1 // indirect github.com/tidwall/gjson v1.17.1 // indirect github.com/tidwall/grect v0.1.4 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -36,11 +37,11 @@ require ( github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/net v0.26.0 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/v2/go.sum b/v2/go.sum index 8cadc79b..ee658aa9 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= -cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -29,6 +29,8 @@ github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2 github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -104,6 +106,8 @@ github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EU github.com/tidwall/buntdb v1.1.2/go.mod h1:xAzi36Hir4FarpSHyfuZ6JzPJdjRZ8QlLZSntE2mqlI= github.com/tidwall/buntdb v1.3.0 h1:gdhWO+/YwoB2qZMeAU9JcWWsHSYU3OvcieYgFRS0zwA= github.com/tidwall/buntdb v1.3.0/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU= +github.com/tidwall/buntdb v1.3.1 h1:HKoDF01/aBhl9RjYtbaLnvX9/OuenwvQiC3OP1CcL4o= +github.com/tidwall/buntdb v1.3.1/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU= github.com/tidwall/gjson v1.3.4/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= @@ -145,10 +149,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= -github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo= -github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= @@ -160,11 +162,10 @@ go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -172,7 +173,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -182,6 +182,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -193,7 +195,6 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -208,8 +209,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/v2/middleware/auth.go b/v2/middleware/auth.go index 80c73fff..8cb10b31 100644 --- a/v2/middleware/auth.go +++ b/v2/middleware/auth.go @@ -203,7 +203,7 @@ func (a *Authenticator) refreshExpiredToken(w http.ResponseWriter, claims token. } } - claims.ExpiresAt = 0 // this will cause now+duration for refreshed token + claims.ExpiresAt = nil // this will cause now+duration for refreshed token c, err := a.JWTService.Set(w, claims) // Set changes token if err != nil { return token.Claims{}, err diff --git a/v2/middleware/auth_test.go b/v2/middleware/auth_test.go index 518380c1..d71e0c9f 100644 --- a/v2/middleware/auth_test.go +++ b/v2/middleware/auth_test.go @@ -166,9 +166,8 @@ func TestAuthJWTRefresh(t *testing.T) { claims, err := a.JWTService.Parse(resp.Cookies()[0].Value) assert.NoError(t, err) - ts := time.Unix(claims.ExpiresAt, 0) - assert.True(t, ts.After(time.Now()), "expiration in the future") - log.Print(time.Unix(claims.ExpiresAt, 0)) + assert.True(t, claims.ExpiresAt.After(time.Now()), "expiration in the future") + log.Print(claims.ExpiresAt) } func TestAuthJWTRefreshConcurrentWithCache(t *testing.T) { diff --git a/v2/provider/apple.go b/v2/provider/apple.go index f83168ab..4a2fbcd0 100644 --- a/v2/provider/apple.go +++ b/v2/provider/apple.go @@ -24,7 +24,7 @@ import ( "golang.org/x/oauth2" "github.com/go-pkgz/rest" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/go-pkgz/auth/v2/logger" "github.com/go-pkgz/auth/v2/token" @@ -261,11 +261,11 @@ func (ah *AppleHandler) LoginHandler(w http.ResponseWriter, r *http.Request) { From: r.URL.Query().Get("from"), }, SessionOnly: r.URL.Query().Get("session") != "" && r.URL.Query().Get("session") != "0", - StandardClaims: jwt.StandardClaims{ - Id: cid, - Audience: r.URL.Query().Get("site"), - ExpiresAt: time.Now().Add(30 * time.Minute).Unix(), - NotBefore: time.Now().Add(-1 * time.Minute).Unix(), + RegisteredClaims: jwt.RegisteredClaims{ + ID: cid, + Audience: jwt.ClaimStrings{r.URL.Query().Get("site")}, + ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Minute)), }, } @@ -370,9 +370,9 @@ func (ah AppleHandler) AuthHandler(w http.ResponseWriter, r *http.Request) { claims := token.Claims{ User: &u, - StandardClaims: jwt.StandardClaims{ + RegisteredClaims: jwt.RegisteredClaims{ Issuer: ah.Issuer, - Id: cid, + ID: cid, Audience: oauthClaims.Audience, }, SessionOnly: false, @@ -467,13 +467,13 @@ func (ah *AppleHandler) createClientSecret() (string, error) { } // Create a claims now := time.Now() - exp := now.Add(time.Minute * 30).Unix() // default value + exp := now.Add(time.Minute * 30) // default value - claims := &jwt.StandardClaims{ + claims := &jwt.RegisteredClaims{ Issuer: ah.conf.TeamID, - IssuedAt: now.Unix(), - ExpiresAt: exp, - Audience: "https://appleid.apple.com", + IssuedAt: jwt.NewNumericDate(now), + ExpiresAt: jwt.NewNumericDate(exp), + Audience: []string{"https://appleid.apple.com"}, Subject: ah.conf.ClientID, } diff --git a/v2/provider/apple_pubkeys.go b/v2/provider/apple_pubkeys.go index ce0ccde0..c1975a2a 100644 --- a/v2/provider/apple_pubkeys.go +++ b/v2/provider/apple_pubkeys.go @@ -16,7 +16,7 @@ import ( "net/http" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" ) // appleKeysURL is the endpoint URL for fetch Appleā€™s public key diff --git a/v2/provider/apple_pubkeys_test.go b/v2/provider/apple_pubkeys_test.go index 3b6e810d..3003f0c1 100644 --- a/v2/provider/apple_pubkeys_test.go +++ b/v2/provider/apple_pubkeys_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/v2/provider/apple_test.go b/v2/provider/apple_test.go index 1b47deb1..19d10892 100644 --- a/v2/provider/apple_test.go +++ b/v2/provider/apple_test.go @@ -19,7 +19,7 @@ import ( "testing" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/oauth2" @@ -303,7 +303,7 @@ func TestAppleHandler_LoginHandler(t *testing.T) { require.NoError(t, err) t.Log(claims) assert.Equal(t, "go-pkgz/auth", claims.Issuer) - assert.Equal(t, "remark", claims.Audience) + assert.Equal(t, "remark", claims.Audience[0]) } diff --git a/v2/provider/custom_server_test.go b/v2/provider/custom_server_test.go index 945e7728..bcb31265 100644 --- a/v2/provider/custom_server_test.go +++ b/v2/provider/custom_server_test.go @@ -18,7 +18,7 @@ import ( "github.com/go-oauth2/oauth2/v4/models" goauth2 "github.com/go-oauth2/oauth2/v4/server" "github.com/go-oauth2/oauth2/v4/store" - "github.com/golang-jwt/jwt" + oldjwt "github.com/golang-jwt/jwt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -80,7 +80,7 @@ func TestCustomProvider(t *testing.T) { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } - assert.Equal(t, 2, len(resp.Cookies())) + require.Equal(t, 2, len(resp.Cookies())) assert.Equal(t, "JWT", resp.Cookies()[0].Name) assert.NotEqual(t, "", resp.Cookies()[0].Value, "token set") assert.Equal(t, 2678400, resp.Cookies()[0].MaxAge) @@ -192,7 +192,7 @@ func initGoauth2Srv(t *testing.T) *goauth2.Server { manager.MustTokenStorage(store.NewMemoryTokenStore()) // generate jwt access token - manager.MapAccessGenerate(generates.NewJWTAccessGenerate("", []byte("00000000"), jwt.SigningMethodHS512)) + manager.MapAccessGenerate(generates.NewJWTAccessGenerate("", []byte("00000000"), oldjwt.SigningMethodHS512)) // client memory store clientStore := store.NewClientStore() diff --git a/v2/provider/direct.go b/v2/provider/direct.go index 19a965e2..7d940177 100644 --- a/v2/provider/direct.go +++ b/v2/provider/direct.go @@ -9,7 +9,7 @@ import ( "time" "github.com/go-pkgz/rest" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/go-pkgz/auth/v2/logger" "github.com/go-pkgz/auth/v2/token" @@ -120,10 +120,10 @@ func (p DirectHandler) LoginHandler(w http.ResponseWriter, r *http.Request) { claims := token.Claims{ User: &u, - StandardClaims: jwt.StandardClaims{ - Id: cid, + RegisteredClaims: jwt.RegisteredClaims{ + ID: cid, Issuer: p.Issuer, - Audience: creds.Audience, + Audience: []string{creds.Audience}, }, SessionOnly: sessOnly, } diff --git a/v2/provider/direct_test.go b/v2/provider/direct_test.go index 0e8fcdf1..03199b22 100644 --- a/v2/provider/direct_test.go +++ b/v2/provider/direct_test.go @@ -90,9 +90,9 @@ func TestDirect_LoginHandler(t *testing.T) { claims, err := d.TokenService.Parse(c.Value) require.NoError(t, err) t.Logf("%+v", claims) - assert.Equal(t, "xyz123", claims.Audience) + assert.Equal(t, "xyz123", claims.Audience[0]) assert.Equal(t, "iss-test", claims.Issuer) - assert.True(t, claims.ExpiresAt > time.Now().Unix()) + assert.True(t, claims.ExpiresAt.After(time.Now())) assert.Equal(t, "myuser", claims.User.Name) }) } diff --git a/v2/provider/oauth1.go b/v2/provider/oauth1.go index b00e1e1c..6a51b0da 100644 --- a/v2/provider/oauth1.go +++ b/v2/provider/oauth1.go @@ -10,7 +10,7 @@ import ( "github.com/dghubble/oauth1" "github.com/go-pkgz/rest" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/go-pkgz/auth/v2/logger" "github.com/go-pkgz/auth/v2/token" @@ -55,11 +55,11 @@ func (h Oauth1Handler) LoginHandler(w http.ResponseWriter, r *http.Request) { From: r.URL.Query().Get("from"), }, SessionOnly: r.URL.Query().Get("session") != "" && r.URL.Query().Get("session") != "0", - StandardClaims: jwt.StandardClaims{ - Id: cid, - Audience: r.URL.Query().Get("site"), - ExpiresAt: time.Now().Add(30 * time.Minute).Unix(), - NotBefore: time.Now().Add(-1 * time.Minute).Unix(), + RegisteredClaims: jwt.RegisteredClaims{ + ID: cid, + Audience: []string{r.URL.Query().Get("site")}, + ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Minute)), }, } @@ -140,9 +140,9 @@ func (h Oauth1Handler) AuthHandler(w http.ResponseWriter, r *http.Request) { } claims := token.Claims{ User: &u, - StandardClaims: jwt.StandardClaims{ + RegisteredClaims: jwt.RegisteredClaims{ Issuer: h.Issuer, - Id: cid, + ID: cid, Audience: oauthClaims.Audience, }, SessionOnly: oauthClaims.SessionOnly, diff --git a/v2/provider/oauth1_test.go b/v2/provider/oauth1_test.go index 2565869f..920c467f 100644 --- a/v2/provider/oauth1_test.go +++ b/v2/provider/oauth1_test.go @@ -62,7 +62,7 @@ func TestOauth1Login(t *testing.T) { require.NoError(t, err) t.Log(claims) assert.Equal(t, "remark42", claims.Issuer) - assert.Equal(t, "remark", claims.Audience) + assert.Equal(t, "remark", claims.Audience[0]) // check admin user resp, err = client.Get(fmt.Sprintf("http://localhost:%d/login?site=remark", loginPort)) diff --git a/v2/provider/oauth2.go b/v2/provider/oauth2.go index 23cb605c..a985cd98 100644 --- a/v2/provider/oauth2.go +++ b/v2/provider/oauth2.go @@ -10,7 +10,7 @@ import ( "time" "github.com/go-pkgz/rest" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "golang.org/x/oauth2" "github.com/go-pkgz/auth/v2/logger" @@ -111,11 +111,11 @@ func (p Oauth2Handler) LoginHandler(w http.ResponseWriter, r *http.Request) { From: r.URL.Query().Get("from"), }, SessionOnly: r.URL.Query().Get("session") != "" && r.URL.Query().Get("session") != "0", - StandardClaims: jwt.StandardClaims{ - Id: cid, - Audience: aud, - ExpiresAt: time.Now().Add(30 * time.Minute).Unix(), - NotBefore: time.Now().Add(-1 * time.Minute).Unix(), + RegisteredClaims: jwt.RegisteredClaims{ + ID: cid, + Audience: []string{aud}, + ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Minute)), }, NoAva: r.URL.Query().Get("noava") == "1", } @@ -208,9 +208,9 @@ func (p Oauth2Handler) AuthHandler(w http.ResponseWriter, r *http.Request) { } claims := token.Claims{ User: &u, - StandardClaims: jwt.StandardClaims{ + RegisteredClaims: jwt.RegisteredClaims{ Issuer: p.Issuer, - Id: cid, + ID: cid, Audience: oauthClaims.Audience, }, SessionOnly: oauthClaims.SessionOnly, diff --git a/v2/provider/oauth2_test.go b/v2/provider/oauth2_test.go index 5448564b..ce890daa 100644 --- a/v2/provider/oauth2_test.go +++ b/v2/provider/oauth2_test.go @@ -73,7 +73,7 @@ func TestOauth2Login(t *testing.T) { require.NoError(t, err) t.Log(claims) assert.Equal(t, "remark42", claims.Issuer) - assert.Equal(t, "remark", claims.Audience) + assert.Equal(t, "remark", claims.Audience[0]) // check admin user resp, err = client.Get("http://localhost:8981/login?site=remark") diff --git a/v2/provider/telegram.go b/v2/provider/telegram.go index 8ecc2ef9..906fe59f 100644 --- a/v2/provider/telegram.go +++ b/v2/provider/telegram.go @@ -17,7 +17,7 @@ import ( "github.com/go-pkgz/repeater" "github.com/go-pkgz/rest" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/go-pkgz/auth/v2/logger" authtoken "github.com/go-pkgz/auth/v2/token" @@ -302,12 +302,12 @@ func (th *TelegramHandler) LoginHandler(w http.ResponseWriter, r *http.Request) claims := authtoken.Claims{ User: &u, - StandardClaims: jwt.StandardClaims{ - Audience: r.URL.Query().Get("site"), - Id: queryToken, + RegisteredClaims: jwt.RegisteredClaims{ + Audience: []string{r.URL.Query().Get("site")}, + ID: queryToken, Issuer: th.ProviderName, - ExpiresAt: time.Now().Add(30 * time.Minute).Unix(), - NotBefore: time.Now().Add(-1 * time.Minute).Unix(), + ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Minute)), }, SessionOnly: false, // TODO review? } diff --git a/v2/provider/telegram_test.go b/v2/provider/telegram_test.go index cadaf3fd..228ae237 100644 --- a/v2/provider/telegram_test.go +++ b/v2/provider/telegram_test.go @@ -108,10 +108,20 @@ func TestTelegramConfirmedRequest(t *testing.T) { return &upd, nil }, AvatarFunc: func(ctx context.Context, userID int) (string, error) { + select { + case <-ctx.Done(): + return "", ctx.Err() + default: + } assert.Equal(t, 313131313, userID) return "http://t.me/avatar.png", nil }, SendFunc: func(ctx context.Context, id int, text string) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } assert.Equal(t, 313131313, id) assert.Equal(t, "success", text) return nil @@ -213,10 +223,20 @@ func TestTelegram_ProcessUpdateFlow(t *testing.T) { return &telegramUpdate{}, nil }, SendFunc: func(ctx context.Context, id int, text string) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } assert.Equal(t, 313131313, id) return nil }, AvatarFunc: func(ctx context.Context, userID int) (string, error) { + select { + case <-ctx.Done(): + return "", ctx.Err() + default: + } assert.Equal(t, 313131313, userID) return "http://t.me/avatar.png", nil }, diff --git a/v2/provider/verify.go b/v2/provider/verify.go index a1376af3..0fc9ca6e 100644 --- a/v2/provider/verify.go +++ b/v2/provider/verify.go @@ -10,7 +10,7 @@ import ( "time" "github.com/go-pkgz/rest" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/go-pkgz/auth/v2/avatar" "github.com/go-pkgz/auth/v2/logger" @@ -111,8 +111,8 @@ func (e VerifyHandler) LoginHandler(w http.ResponseWriter, r *http.Request) { claims := token.Claims{ User: &u, - StandardClaims: jwt.StandardClaims{ - Id: cid, + RegisteredClaims: jwt.RegisteredClaims{ + ID: cid, Issuer: e.Issuer, Audience: confClaims.Audience, }, @@ -146,10 +146,10 @@ func (e VerifyHandler) sendConfirmation(w http.ResponseWriter, r *http.Request) ID: user + "::" + address, }, SessionOnly: r.URL.Query().Get("session") != "" && r.URL.Query().Get("session") != "0", - StandardClaims: jwt.StandardClaims{ - Audience: site, - ExpiresAt: time.Now().Add(30 * time.Minute).Unix(), - NotBefore: time.Now().Add(-1 * time.Minute).Unix(), + RegisteredClaims: jwt.RegisteredClaims{ + Audience: []string{site}, + ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Minute)), Issuer: e.Issuer, }, } diff --git a/v2/provider/verify_test.go b/v2/provider/verify_test.go index 2c298ed6..276600d4 100644 --- a/v2/provider/verify_test.go +++ b/v2/provider/verify_test.go @@ -54,8 +54,8 @@ func TestVerifyHandler_LoginSendConfirm(t *testing.T) { assert.NoError(t, err) t.Logf("%s %+v", tknStr, tkn) assert.Equal(t, "test123::blah@user.com", tkn.Handshake.ID) - assert.Equal(t, "remark42", tkn.Audience) - assert.True(t, tkn.ExpiresAt > tkn.NotBefore) + assert.Equal(t, "remark42", tkn.Audience[0]) + assert.True(t, tkn.ExpiresAt.After(tkn.NotBefore.Time)) assert.Equal(t, "test", e.Name()) } @@ -93,8 +93,8 @@ func TestVerifyHandler_LoginSendConfirmEscapesBadInput(t *testing.T) { t.Logf("%s %+v", tknStr, tkn) // not escaped in these fields as they are not rendered as HTML assert.Equal(t, badData+"::blah@user.com", tkn.Handshake.ID) - assert.Equal(t, badData, tkn.Audience) - assert.True(t, tkn.ExpiresAt > tkn.NotBefore) + assert.Equal(t, badData, tkn.Audience[0]) + assert.True(t, tkn.ExpiresAt.After(tkn.NotBefore.Time)) assert.Equal(t, "test", e.Name()) } @@ -125,9 +125,9 @@ func TestVerifyHandler_LoginAcceptConfirm(t *testing.T) { claims, err := e.TokenService.Parse(c.Value) require.NoError(t, err) t.Logf("%+v", claims) - assert.Equal(t, "remark42", claims.Audience) + assert.Equal(t, "remark42", claims.Audience[0]) assert.Equal(t, "iss-test", claims.Issuer) - assert.True(t, claims.ExpiresAt > time.Now().Unix()) + assert.True(t, claims.ExpiresAt.After(time.Now())) assert.Equal(t, "test123", claims.User.Name) assert.Equal(t, true, claims.SessionOnly) } diff --git a/v2/token/jwt.go b/v2/token/jwt.go index c899b070..8350ae85 100644 --- a/v2/token/jwt.go +++ b/v2/token/jwt.go @@ -3,12 +3,15 @@ package token import ( "encoding/json" + "errors" "fmt" "net/http" + "slices" "strings" + "sync" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" ) // Service wraps jwt operations @@ -19,7 +22,7 @@ type Service struct { // Claims stores user info for token and state & from from login type Claims struct { - jwt.StandardClaims + jwt.RegisteredClaims User *User `json:"user,omitempty"` // user info SessionOnly bool `json:"sess_only,omitempty"` Handshake *Handshake `json:"handshake,omitempty"` // used for oauth handshake @@ -49,6 +52,10 @@ const ( defaultTokenQuery = "token" ) +var ( + defaultXSRFIgnoreMethods = []string{} +) + // Opts holds constructor params type Opts struct { SecretReader Secret @@ -59,21 +66,27 @@ type Opts struct { DisableXSRF bool DisableIAT bool // disable IssuedAt claim // optional (custom) names for cookies and headers - JWTCookieName string - JWTCookieDomain string - JWTHeaderKey string - XSRFCookieName string - XSRFHeaderKey string - JWTQuery string - AudienceReader Audience // allowed aud values - Issuer string // optional value for iss claim, usually application name - AudSecrets bool // uses different secret for differed auds. important: adds pre-parsing of unverified token - SendJWTHeader bool // if enabled send JWT as a header instead of cookie - SameSite http.SameSite // define a cookie attribute making it impossible for the browser to send this cookie cross-site + JWTCookieName string + JWTCookieDomain string + JWTHeaderKey string + XSRFCookieName string + XSRFHeaderKey string + XSRFIgnoreMethods []string + JWTQuery string + AudienceReader Audience // allowed aud values + Issuer string // optional value for iss claim, usually application name + AudSecrets bool // uses different secret for differed auds. important: adds pre-parsing of unverified token + SendJWTHeader bool // if enabled send JWT as a header instead of cookie + SameSite http.SameSite // define a cookie attribute making it impossible for the browser to send this cookie cross-site } // NewService makes JWT service func NewService(opts Opts) *Service { + var once sync.Once + once.Do(func() { + jwt.MarshalSingleStringAsArray = false + }) + res := Service{Opts: opts} setDefault := func(fld *string, def string) { @@ -90,6 +103,10 @@ func NewService(opts Opts) *Service { setDefault(&res.Issuer, defaultIssuer) setDefault(&res.JWTCookieDomain, defaultJWTCookieDomain) + if opts.XSRFIgnoreMethods == nil { + opts.XSRFIgnoreMethods = defaultXSRFIgnoreMethods + } + if opts.TokenDuration == 0 { res.TokenDuration = defaultTokenDuration } @@ -121,7 +138,7 @@ func (j *Service) Token(claims Claims) (string, error) { return "", fmt.Errorf("aud rejected: %w", err) } - secret, err := j.SecretReader.Get(claims.Audience) // get secret via consumer defined SecretReader + secret, err := j.SecretReader.Get(claims.Audience[0]) // get secret via consumer defined SecretReader if err != nil { return "", fmt.Errorf("can't get secret: %w", err) } @@ -135,7 +152,7 @@ func (j *Service) Token(claims Claims) (string, error) { // Parse token string and verify. Not checking for expiration func (j *Service) Parse(tokenString string) (Claims, error) { - parser := jwt.Parser{SkipClaimsValidation: true} // allow parsing of expired tokens + parser := jwt.NewParser(jwt.WithoutClaimsValidation()) if j.SecretReader == nil { return Claims{}, fmt.Errorf("secret reader not defined") @@ -179,7 +196,7 @@ func (j *Service) Parse(tokenString string) (Claims, error) { // aud pre-parse token and extracts aud from the claim // important! this step ignores token verification, should not be used for any validations func (j *Service) aud(tokenString string) (string, error) { - parser := jwt.Parser{} + parser := jwt.NewParser() token, _, err := parser.ParseUnverified(tokenString, &Claims{}) if err != nil { return "", fmt.Errorf("can't pre-parse token: %w", err) @@ -188,34 +205,44 @@ func (j *Service) aud(tokenString string) (string, error) { if !ok { return "", fmt.Errorf("invalid token") } - if strings.TrimSpace(claims.Audience) == "" { + + if len(claims.Audience) == 0 { + return "", fmt.Errorf("empty aud") + } + aud := claims.Audience[0] + + if strings.TrimSpace(aud) == "" { return "", fmt.Errorf("empty aud") } - return claims.Audience, nil + return aud, nil } func (j *Service) validate(claims *Claims) error { - cerr := claims.Valid() + validator := jwt.NewValidator() + err := validator.Validate(claims) - if cerr == nil { + if err == nil { return nil } - if e, ok := cerr.(*jwt.ValidationError); ok { - if e.Errors == jwt.ValidationErrorExpired { - return nil // allow expired tokens + // Ignore "ErrTokenExpired" if it is the only error. + if errors.Is(err, jwt.ErrTokenExpired) { + if uw, ok := err.(interface{ Unwrap() []error }); ok && len(uw.Unwrap()) == 1 { + return nil } } - return cerr + return err } // Set creates token cookie with xsrf cookie and put it to ResponseWriter // accepts claims and sets expiration if none defined. permanent flag means long-living cookie, // false makes it session only. func (j *Service) Set(w http.ResponseWriter, claims Claims) (Claims, error) { - if claims.ExpiresAt == 0 { - claims.ExpiresAt = time.Now().Add(j.TokenDuration).Unix() + nowUnix := time.Now().Unix() + + if claims.ExpiresAt == nil || claims.ExpiresAt.Time.Unix() == 0 { + claims.ExpiresAt = jwt.NewNumericDate(time.Unix(nowUnix, 0).Add(j.TokenDuration)) } if claims.Issuer == "" { @@ -223,7 +250,7 @@ func (j *Service) Set(w http.ResponseWriter, claims Claims) (Claims, error) { } if !j.DisableIAT { - claims.IssuedAt = time.Now().Unix() + claims.IssuedAt = jwt.NewNumericDate(time.Unix(nowUnix, 0)) } tokenString, err := j.Token(claims) @@ -245,7 +272,7 @@ func (j *Service) Set(w http.ResponseWriter, claims Claims) (Claims, error) { MaxAge: cookieExpiration, Secure: j.SecureCookies, SameSite: j.SameSite} http.SetCookie(w, &jwtCookie) - xsrfCookie := http.Cookie{Name: j.XSRFCookieName, Value: claims.Id, HttpOnly: false, Path: "/", Domain: j.JWTCookieDomain, + xsrfCookie := http.Cookie{Name: j.XSRFCookieName, Value: claims.ID, HttpOnly: false, Path: "/", Domain: j.JWTCookieDomain, MaxAge: cookieExpiration, Secure: j.SecureCookies, SameSite: j.SameSite} http.SetCookie(w, &xsrfCookie) @@ -286,20 +313,23 @@ func (j *Service) Get(r *http.Request) (Claims, string, error) { // promote claim's aud to User.Audience if claims.User != nil { - claims.User.Audience = claims.Audience + if len(claims.Audience) != 1 { + return Claims{}, "", fmt.Errorf("aud is not of size 1") + } + claims.User.Audience = claims.Audience[0] } if !fromCookie && j.IsExpired(claims) { return Claims{}, "", fmt.Errorf("token expired") } - if j.DisableXSRF { + if j.DisableXSRF || slices.Contains(j.XSRFIgnoreMethods, r.Method) { return claims, tokenString, nil } if fromCookie && claims.User != nil { xsrf := r.Header.Get(j.XSRFHeaderKey) - if claims.Id != xsrf { + if claims.ID != xsrf { return Claims{}, "", fmt.Errorf("xsrf mismatch") } } @@ -309,7 +339,9 @@ func (j *Service) Get(r *http.Request) (Claims, string, error) { // IsExpired returns true if claims expired func (j *Service) IsExpired(claims Claims) bool { - return !claims.VerifyExpiresAt(time.Now().Unix(), true) + validator := jwt.NewValidator(jwt.WithExpirationRequired()) + err := validator.Validate(claims) + return errors.Is(err, jwt.ErrTokenExpired) } // Reset token's cookies @@ -327,25 +359,32 @@ func (j *Service) Reset(w http.ResponseWriter) { // checkAuds verifies if claims.Audience in the list of allowed by audReader func (j *Service) checkAuds(claims *Claims, audReader Audience) error { + // marshal the audience. if audReader == nil { // lack of any allowed means any return nil } + + if len(claims.Audience) == 0 { + return fmt.Errorf("no audience provided") + } + claimsAudience := claims.Audience[0] + auds, err := audReader.Get() if err != nil { return fmt.Errorf("failed to get auds: %w", err) } for _, a := range auds { - if strings.EqualFold(a, claims.Audience) { + if strings.EqualFold(a, claimsAudience) { return nil } } - return fmt.Errorf("aud %q not allowed", claims.Audience) + return fmt.Errorf("aud %q not allowed", claimsAudience) } func (c Claims) String() string { b, err := json.Marshal(c) if err != nil { - return fmt.Sprintf("%+v %+v", c.StandardClaims, c.User) + return fmt.Sprintf("%+v %+v", c.RegisteredClaims, c.User) } return string(b) } diff --git a/v2/token/jwt_test.go b/v2/token/jwt_test.go index e30ee137..d02c7803 100644 --- a/v2/token/jwt_test.go +++ b/v2/token/jwt_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -17,9 +17,9 @@ import ( // ("secret" in most cases here, "xyz 12345" in makeTestAuth), and alter the fields you want to be changed. var ( - testJwtValid = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0X3N5cyIsImV4cCI6Mjc4OTE5MTgyMiwianRpIjoicmFuZG9tIGlkIiwiaXNzIjoicmVtYXJrNDIiLCJuYmYiOjE1MjY4ODQyMjIsInVzZXIiOnsibmFtZSI6Im5hbWUxIiwiaWQiOiJpZDEiLCJwaWN0dXJlIjoiaHR0cDovL2V4YW1wbGUuY29tL3BpYy5wbmciLCJpcCI6IjEyNy4wLjAuMSIsImVtYWlsIjoibWVAZXhhbXBsZS5jb20iLCJhdHRycyI6eyJib29sYSI6dHJ1ZSwic3RyYSI6InN0cmEtdmFsIn19LCJoYW5kc2hha2UiOnsic3RhdGUiOiIxMjM0NTYiLCJmcm9tIjoiZnJvbSIsImlkIjoibXlpZC0xMjM0NTYifX0._2X1cAEoxjLA7XuN8xW8V9r7rYfP_m9lSRz_9_UFzac" - testJwtValidNoHandshake = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0X3N5cyIsImV4cCI6Mjc4OTE5MTgyMiwianRpIjoicmFuZG9tIGlkIiwiaXNzIjoicmVtYXJrNDIiLCJuYmYiOjE1MjY4ODQyMjIsInVzZXIiOnsibmFtZSI6Im5hbWUxIiwiaWQiOiJpZDEiLCJwaWN0dXJlIjoiaHR0cDovL2V4YW1wbGUuY29tL3BpYy5wbmciLCJpcCI6IjEyNy4wLjAuMSIsImVtYWlsIjoibWVAZXhhbXBsZS5jb20iLCJhdHRycyI6eyJib29sYSI6dHJ1ZSwic3RyYSI6InN0cmEtdmFsIn19fQ.OWPdibrSSSHuOV3DzzLH5soO6kUcERELL7_GLf7Ja_E" - testJwtValidSess = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0X3N5cyIsImV4cCI6Mjc4OTE5MTgyMiwianRpIjoicmFuZG9tIGlkIiwiaXNzIjoicmVtYXJrNDIiLCJuYmYiOjE1MjY4ODQyMjIsInVzZXIiOnsibmFtZSI6Im5hbWUxIiwiaWQiOiJpZDEiLCJwaWN0dXJlIjoiaHR0cDovL2V4YW1wbGUuY29tL3BpYy5wbmciLCJpcCI6IjEyNy4wLjAuMSIsImVtYWlsIjoibWVAZXhhbXBsZS5jb20iLCJhdHRycyI6eyJib29sYSI6dHJ1ZSwic3RyYSI6InN0cmEtdmFsIn19LCJzZXNzX29ubHkiOnRydWV9.SjPlVgca_bijC2wbaite2_eNHk66VXgsxUKLy7eqlXM" + testJwtValid = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJyZW1hcms0MiIsImF1ZCI6InRlc3Rfc3lzIiwiZXhwIjoyNzg5MTkxODIyLCJuYmYiOjE1MjY4ODQyMjIsImp0aSI6InJhbmRvbSBpZCIsInVzZXIiOnsibmFtZSI6Im5hbWUxIiwiaWQiOiJpZDEiLCJwaWN0dXJlIjoiaHR0cDovL2V4YW1wbGUuY29tL3BpYy5wbmciLCJpcCI6IjEyNy4wLjAuMSIsImVtYWlsIjoibWVAZXhhbXBsZS5jb20iLCJhdHRycyI6eyJib29sYSI6dHJ1ZSwic3RyYSI6InN0cmEtdmFsIn19LCJoYW5kc2hha2UiOnsic3RhdGUiOiIxMjM0NTYiLCJmcm9tIjoiZnJvbSIsImlkIjoibXlpZC0xMjM0NTYifX0.Ln7P2rEO-kWLN8AuKddWzjKC9l_kpw_yWfSO12MYo0o" + testJwtValidNoHandshake = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJyZW1hcms0MiIsImF1ZCI6InRlc3Rfc3lzIiwiZXhwIjoyNzg5MTkxODIyLCJuYmYiOjE1MjY4ODQyMjIsImp0aSI6InJhbmRvbSBpZCIsInVzZXIiOnsibmFtZSI6Im5hbWUxIiwiaWQiOiJpZDEiLCJwaWN0dXJlIjoiaHR0cDovL2V4YW1wbGUuY29tL3BpYy5wbmciLCJpcCI6IjEyNy4wLjAuMSIsImVtYWlsIjoibWVAZXhhbXBsZS5jb20iLCJhdHRycyI6eyJib29sYSI6dHJ1ZSwic3RyYSI6InN0cmEtdmFsIn19fQ.D7fO3tzq3y-uSnh3Mae-Mqp8w9WdkH9s4zPTh44k8Gs" + testJwtValidSess = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJyZW1hcms0MiIsImF1ZCI6InRlc3Rfc3lzIiwiZXhwIjoyNzg5MTkxODIyLCJuYmYiOjE1MjY4ODQyMjIsImp0aSI6InJhbmRvbSBpZCIsInVzZXIiOnsibmFtZSI6Im5hbWUxIiwiaWQiOiJpZDEiLCJwaWN0dXJlIjoiaHR0cDovL2V4YW1wbGUuY29tL3BpYy5wbmciLCJpcCI6IjEyNy4wLjAuMSIsImVtYWlsIjoibWVAZXhhbXBsZS5jb20iLCJhdHRycyI6eyJib29sYSI6dHJ1ZSwic3RyYSI6InN0cmEtdmFsIn19LCJzZXNzX29ubHkiOnRydWV9.RtQ6uBksqtMTd9GDLJen_eDUlLAYLh9uH0GBO_OIf4M" testJwtExpired = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MjY4ODc4MjIsImp0aSI6InJhbmRvbSBpZCIs" + "ImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiI" + "sImFkbWluIjpmYWxzZX0sInN0YXRlIjoiMTIzNDU2IiwiZnJvbSI6ImZyb20ifQ.4_dCrY9ihyfZIedz-kZwBTxmxU1a52V7IqeJrOqTzE4" @@ -88,6 +88,11 @@ func TestJWT_Token(t *testing.T) { assert.NoError(t, err) assert.Equal(t, testJwtValid, res) + newClaims, _ := j.Parse(res) + assert.Equal(t, claims, newClaims) + fmt.Println(claims) + fmt.Println(newClaims) + j.SecretReader = nil _, err = j.Token(claims) assert.EqualError(t, err, "secret reader not defined") @@ -126,10 +131,10 @@ func TestJWT_Parse(t *testing.T) { assert.Error(t, err, "bad token") _, err = j.Parse(testJwtBadSign) - assert.EqualError(t, err, "can't parse token: signature is invalid") + assert.EqualError(t, err, "can't parse token: token signature is invalid: signature is invalid") _, err = j.Parse(testJwtNoneAlg) - assert.EqualError(t, err, "can't parse token: unexpected signing method: none") + assert.EqualError(t, err, "can't parse token: token is unverifiable: error while executing keyfunc: unexpected signing method: none") j = NewService(Opts{ SecretReader: SecretFunc(func(string) (string, error) { return "bad 12345", nil }), @@ -271,7 +276,7 @@ func TestJWT_SetProlonged(t *testing.T) { claims := testClaims claims.Handshake = nil - claims.ExpiresAt = 0 + claims.ExpiresAt = nil rr := httptest.NewRecorder() _, err := j.Set(rr, claims) @@ -282,7 +287,7 @@ func TestJWT_SetProlonged(t *testing.T) { cc, err := j.Parse(cookies[0].Value) assert.NoError(t, err) - assert.True(t, cc.ExpiresAt > time.Now().Unix()) + assert.True(t, cc.ExpiresAt.After(time.Now().UTC())) } func TestJWT_NoIssuer(t *testing.T) { @@ -345,7 +350,7 @@ func TestJWT_GetFromHeader(t *testing.T) { req.Header.Add(jwtCustomHeaderKey, "bad bad token") _, _, err = j.Get(req) require.NotNil(t, err) - assert.True(t, strings.Contains(err.Error(), "failed to get token: can't parse token: token contains an invalid number of segments"), err.Error()) + assert.True(t, strings.Contains(err.Error(), "failed to get token: can't parse token: token is malformed: token contains an invalid number of segments"), err.Error()) } func TestJWT_GetFromQuery(t *testing.T) { @@ -375,7 +380,7 @@ func TestJWT_GetFromQuery(t *testing.T) { req = httptest.NewRequest("GET", "/blah?token=blah", nil) _, _, err = j.Get(req) require.NotNil(t, err) - assert.True(t, strings.Contains(err.Error(), "failed to get token: can't parse token: token contains an invalid number of segments"), err.Error()) + assert.True(t, strings.Contains(err.Error(), "failed to get token: can't parse token: token is malformed: token contains an invalid number of segments"), err.Error()) } func TestJWT_GetFailed(t *testing.T) { @@ -467,7 +472,54 @@ func TestJWT_SetAndGetWithXsrfMismatch(t *testing.T) { req.Header.Add(xsrfCustomHeaderKey, "random id wrong") c, _, err := j.Get(req) require.NoError(t, err, "xsrf mismatch, but ignored") - claims.User.Audience = c.Audience // set aud to user because we don't do the normal Get call + claims.User.Audience = c.Audience[0] // set aud to user because we don't do the normal Get call + assert.Equal(t, claims, c) +} + +func TestJWT_GetWithXsrfMismatchOnIgnoredMethod(t *testing.T) { + j := NewService(Opts{SecretReader: SecretFunc(mockKeyStore), SecureCookies: false, + TokenDuration: time.Hour, CookieDuration: days31, + JWTCookieName: jwtCustomCookieName, JWTHeaderKey: jwtCustomHeaderKey, + XSRFCookieName: xsrfCustomCookieName, XSRFHeaderKey: xsrfCustomHeaderKey, + ClaimsUpd: ClaimsUpdFunc(func(claims Claims) Claims { + claims.User.SetStrAttr("stra", "stra-val") + claims.User.SetBoolAttr("boola", true) + return claims + }), + Issuer: "remark42", + DisableIAT: true, + }) + + claims := testClaims + claims.SessionOnly = true + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/valid" { + _, e := j.Set(w, claims) + require.NoError(t, e) + w.WriteHeader(200) + } + })) + defer ts.Close() + + resp, err := http.Get(ts.URL + "/valid") + require.Nil(t, err) + assert.Equal(t, 200, resp.StatusCode) + + j.XSRFIgnoreMethods = []string{"GET"} + req := httptest.NewRequest("GET", "/valid", nil) + req.AddCookie(resp.Cookies()[0]) + req.Header.Add(xsrfCustomHeaderKey, "random id wrong") + _, _, err = j.Get(req) + require.NoError(t, err, "xsrf mismatch, but ignored") + + j.DisableXSRF = true + j.XSRFIgnoreMethods = []string{} + req = httptest.NewRequest("GET", "/valid", nil) + req.AddCookie(resp.Cookies()[0]) + req.Header.Add(xsrfCustomHeaderKey, "random id wrong") + c, _, err := j.Get(req) + require.NoError(t, err, "xsrf mismatch, but ignored") + claims.User.Audience = c.Audience[0] // set aud to user because we don't do the normal Get call assert.Equal(t, claims, c) } @@ -485,8 +537,8 @@ func TestJWT_SetAndGetWithCookiesExpired(t *testing.T) { }) claims := testClaims - claims.StandardClaims.ExpiresAt = time.Date(2018, 5, 21, 1, 35, 22, 0, time.Local).Unix() - claims.StandardClaims.NotBefore = time.Date(2018, 5, 21, 1, 30, 22, 0, time.Local).Unix() + claims.RegisteredClaims.ExpiresAt = jwt.NewNumericDate(time.Date(2018, 5, 21, 1, 35, 22, 0, time.Local)) + claims.RegisteredClaims.NotBefore = jwt.NewNumericDate(time.Date(2018, 5, 21, 1, 30, 22, 0, time.Local)) claims.SessionOnly = true ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -560,8 +612,8 @@ func TestAudience(t *testing.T) { }) c := Claims{ - StandardClaims: jwt.StandardClaims{ - Audience: "au1", + RegisteredClaims: jwt.RegisteredClaims{ + Audience: []string{"au1"}, Issuer: "test iss", }, } @@ -592,7 +644,7 @@ func TestAudReader(t *testing.T) { assert.EqualError(t, err, "empty aud") _, err = j.aud("blah bad bad") - assert.EqualError(t, err, "can't pre-parse token: token contains an invalid number of segments") + assert.EqualError(t, err, "can't pre-parse token: token is malformed: token contains an invalid number of segments") } func TestParseWithAud(t *testing.T) { @@ -608,19 +660,19 @@ func TestParseWithAud(t *testing.T) { claims, err = j.Parse(testJwtValidAud) assert.NoError(t, err) - assert.Equal(t, "test_aud_only", claims.Audience) + assert.Equal(t, "test_aud_only", claims.Audience[0]) claims, err = j.Parse(testJwtNonAudSign) - assert.EqualError(t, err, "can't parse token: signature is invalid") + assert.EqualError(t, err, "can't parse token: token signature is invalid: signature is invalid") } var testClaims = Claims{ - StandardClaims: jwt.StandardClaims{ - Id: "random id", + RegisteredClaims: jwt.RegisteredClaims{ + ID: "random id", Issuer: "remark42", - Audience: "test_sys", - ExpiresAt: time.Date(2058, 5, 21, 7, 30, 22, 0, time.UTC).Unix(), - NotBefore: time.Date(2018, 5, 21, 6, 30, 22, 0, time.UTC).Unix(), + Audience: []string{"test_sys"}, + ExpiresAt: jwt.NewNumericDate(time.Date(2058, 5, 21, 7, 30, 22, 0, time.UTC).Local()), + NotBefore: jwt.NewNumericDate(time.Date(2018, 5, 21, 6, 30, 22, 0, time.UTC).Local()), }, User: &User{