fix: improve JWS and key verification (#128)
* fix: improve JWS and key verification * fix: get remote keys if no cached key matches * fix: get remote keys if no cached key matches * fix exactMatch * fix exactMatch * chore: change default branch name in .releaserc.js
This commit is contained in:
parent
2b5b436c41
commit
a63fbee93d
7 changed files with 453 additions and 32 deletions
|
@ -5,4 +5,4 @@ module.exports = {
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/github"
|
"@semantic-release/github"
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
18
go.sum
18
go.sum
|
@ -50,9 +50,13 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||||
|
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
@ -95,6 +99,7 @@ github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6C
|
||||||
github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM=
|
github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
@ -120,6 +125,7 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
@ -129,21 +135,30 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
||||||
|
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
@ -244,6 +259,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -403,6 +419,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -3,26 +3,41 @@ package rp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/caos/oidc/pkg/utils"
|
"github.com/caos/oidc/pkg/utils"
|
||||||
|
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
|
||||||
"github.com/caos/oidc/pkg/oidc"
|
"github.com/caos/oidc/pkg/oidc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewRemoteKeySet(client *http.Client, jwksURL string) oidc.KeySet {
|
func NewRemoteKeySet(client *http.Client, jwksURL string, opts ...func(*remoteKeySet)) oidc.KeySet {
|
||||||
return &remoteKeySet{httpClient: client, jwksURL: jwksURL}
|
keyset := &remoteKeySet{httpClient: client, jwksURL: jwksURL}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(keyset)
|
||||||
|
}
|
||||||
|
return keyset
|
||||||
|
}
|
||||||
|
|
||||||
|
//SkipRemoteCheck will suppress checking for new remote keys if signature validation fails with cached keys
|
||||||
|
//and no kid header is set in the JWT
|
||||||
|
//
|
||||||
|
//this might be handy to save some unnecessary round trips in cases where the JWT does not contain a kid header and
|
||||||
|
//there is only a single remote key
|
||||||
|
//please notice that remote keys will then only be fetched if cached keys are empty
|
||||||
|
func SkipRemoteCheck() func(set *remoteKeySet) {
|
||||||
|
return func(set *remoteKeySet) {
|
||||||
|
set.skipRemoteCheck = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type remoteKeySet struct {
|
type remoteKeySet struct {
|
||||||
jwksURL string
|
jwksURL string
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
defaultAlg string
|
defaultAlg string
|
||||||
|
skipRemoteCheck bool
|
||||||
|
|
||||||
// guard all other fields
|
// guard all other fields
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
@ -72,23 +87,67 @@ func (r *remoteKeySet) VerifySignature(ctx context.Context, jws *jose.JSONWebSig
|
||||||
if alg == "" {
|
if alg == "" {
|
||||||
alg = r.defaultAlg
|
alg = r.defaultAlg
|
||||||
}
|
}
|
||||||
keys := r.keysFromCache()
|
payload, err := r.verifySignatureCached(jws, keyID, alg)
|
||||||
key, ok := oidc.FindKey(keyID, oidc.KeyUseSignature, alg, keys...)
|
if payload != nil {
|
||||||
if ok && keyID != "" {
|
return payload, nil
|
||||||
payload, err := jws.Verify(&key)
|
|
||||||
return payload, err
|
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return r.verifySignatureRemote(ctx, jws, keyID, alg)
|
||||||
|
}
|
||||||
|
|
||||||
|
//verifySignatureCached checks for a matching key in the cached key list
|
||||||
|
//
|
||||||
|
//if there is only one possible, it tries to verify the signature and will return the payload if successful
|
||||||
|
//
|
||||||
|
//it only returns an error if signature validation fails and keys exactMatch which is if either:
|
||||||
|
// - both kid are empty and skipRemoteCheck is set to true
|
||||||
|
// - or both (JWT and JWK) kid are equal
|
||||||
|
//
|
||||||
|
//otherwise it will return no error (so remote keys will be loaded)
|
||||||
|
func (r *remoteKeySet) verifySignatureCached(jws *jose.JSONWebSignature, keyID, alg string) ([]byte, error) {
|
||||||
|
keys := r.keysFromCache()
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
key, err := oidc.FindMatchingKey(keyID, oidc.KeyUseSignature, alg, keys...)
|
||||||
|
if err != nil {
|
||||||
|
//no key / multiple found, try with remote keys
|
||||||
|
return nil, nil //nolint:nilerr
|
||||||
|
}
|
||||||
|
payload, err := jws.Verify(&key)
|
||||||
|
if payload != nil {
|
||||||
|
return payload, nil
|
||||||
|
}
|
||||||
|
if !r.exactMatch(key.KeyID, keyID) {
|
||||||
|
//no exact key match, try getting better match with remote keys
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("signature verification failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remoteKeySet) exactMatch(jwkID, jwsID string) bool {
|
||||||
|
if jwkID == "" && jwsID == "" {
|
||||||
|
return r.skipRemoteCheck
|
||||||
|
}
|
||||||
|
return jwkID == jwsID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remoteKeySet) verifySignatureRemote(ctx context.Context, jws *jose.JSONWebSignature, keyID, alg string) ([]byte, error) {
|
||||||
keys, err := r.keysFromRemote(ctx)
|
keys, err := r.keysFromRemote(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("fetching keys %v", err)
|
return nil, fmt.Errorf("unable to fetch key for signature validation: %w", err)
|
||||||
}
|
}
|
||||||
key, ok = oidc.FindKey(keyID, oidc.KeyUseSignature, alg, keys...)
|
key, err := oidc.FindMatchingKey(keyID, oidc.KeyUseSignature, alg, keys...)
|
||||||
if ok {
|
if err != nil {
|
||||||
payload, err := jws.Verify(&key)
|
return nil, fmt.Errorf("unable to validate signature: %w", err)
|
||||||
return payload, err
|
|
||||||
}
|
}
|
||||||
return nil, errors.New("invalid key")
|
payload, err := jws.Verify(&key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("signature verification failed: %w", err)
|
||||||
|
}
|
||||||
|
return payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteKeySet) keysFromCache() (keys []jose.JSONWebKey) {
|
func (r *remoteKeySet) keysFromCache() (keys []jose.JSONWebKey) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
)
|
)
|
||||||
|
@ -13,6 +14,11 @@ const (
|
||||||
KeyUseSignature = "sig"
|
KeyUseSignature = "sig"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrKeyMultiple = errors.New("multiple possible keys match")
|
||||||
|
ErrKeyNone = errors.New("no possible keys matches")
|
||||||
|
)
|
||||||
|
|
||||||
//KeySet represents a set of JSON Web Keys
|
//KeySet represents a set of JSON Web Keys
|
||||||
// - remotely fetch via discovery and jwks_uri -> `remoteKeySet`
|
// - remotely fetch via discovery and jwks_uri -> `remoteKeySet`
|
||||||
// - held by the OP itself in storage -> `openIDKeySet`
|
// - held by the OP itself in storage -> `openIDKeySet`
|
||||||
|
@ -39,20 +45,38 @@ func GetKeyIDAndAlg(jws *jose.JSONWebSignature) (string, string) {
|
||||||
//will return the key immediately if matches exact (id, usage, type)
|
//will return the key immediately if matches exact (id, usage, type)
|
||||||
//
|
//
|
||||||
//will return false none or multiple match
|
//will return false none or multiple match
|
||||||
|
//
|
||||||
|
//deprecated: use FindMatchingKey which will return an error (more specific) instead of just a bool
|
||||||
|
//moved implementation already to FindMatchingKey
|
||||||
func FindKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (jose.JSONWebKey, bool) {
|
func FindKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (jose.JSONWebKey, bool) {
|
||||||
|
key, err := FindMatchingKey(keyID, use, expectedAlg, keys...)
|
||||||
|
return key, err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//FindMatchingKey searches the given JSON Web Keys for the requested key ID, usage and key type
|
||||||
|
//
|
||||||
|
//will return the key immediately if matches exact (id, usage, type)
|
||||||
|
//
|
||||||
|
//will return a specific error if none (ErrKeyNone) or multiple (ErrKeyMultiple) match
|
||||||
|
func FindMatchingKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (key jose.JSONWebKey, err error) {
|
||||||
var validKeys []jose.JSONWebKey
|
var validKeys []jose.JSONWebKey
|
||||||
for _, key := range keys {
|
for _, k := range keys {
|
||||||
if key.KeyID == keyID && key.Use == use && algToKeyType(key.Key, expectedAlg) {
|
if k.Use == use && algToKeyType(k.Key, expectedAlg) {
|
||||||
if keyID != "" {
|
if k.KeyID == keyID && keyID != "" {
|
||||||
return key, true
|
return k, nil
|
||||||
|
}
|
||||||
|
if k.KeyID == "" || keyID == "" {
|
||||||
|
validKeys = append(validKeys, k)
|
||||||
}
|
}
|
||||||
validKeys = append(validKeys, key)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(validKeys) == 1 {
|
if len(validKeys) == 1 {
|
||||||
return validKeys[0], true
|
return validKeys[0], nil
|
||||||
}
|
}
|
||||||
return jose.JSONWebKey{}, false
|
if len(validKeys) > 1 {
|
||||||
|
return key, ErrKeyMultiple
|
||||||
|
}
|
||||||
|
return key, ErrKeyNone
|
||||||
}
|
}
|
||||||
|
|
||||||
func algToKeyType(key interface{}, alg string) bool {
|
func algToKeyType(key interface{}, alg string) bool {
|
||||||
|
|
319
pkg/oidc/keyset_test.go
Normal file
319
pkg/oidc/keyset_test.go
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
package oidc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFindKey(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
keyID string
|
||||||
|
use string
|
||||||
|
expectedAlg string
|
||||||
|
keys []jose.JSONWebKey
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
key jose.JSONWebKey
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"no keys, ErrKeyNone",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: nil,
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyNone,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"single key enc, ErrKeyNone",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "enc",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyNone,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"single key wrong algorithm, ErrKeyNone",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PrivateKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyNone,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"single key no kid, no jwt kid, match",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"single key kid, jwt no kid, match",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"single key no kid, jwt with kid, match",
|
||||||
|
args{
|
||||||
|
keyID: "id",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"single key wrong kid, ErrKeyNone",
|
||||||
|
args{
|
||||||
|
keyID: "id",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id2",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyNone,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple keys no kid, jwt no kid, ErrKeyMultiple",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyMultiple,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple keys with kid, jwt no kid, ErrKeyMultiple",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id1",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id2",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyMultiple,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple keys, single sig key, jwt no kid, match",
|
||||||
|
args{
|
||||||
|
keyID: "",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Use: "enc",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple keys no kid, jwt with kid, ErrKeyMultiple",
|
||||||
|
args{
|
||||||
|
keyID: "id",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{},
|
||||||
|
err: ErrKeyMultiple,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple keys with kid, jwt with kid, match",
|
||||||
|
args{
|
||||||
|
keyID: "id1",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id1",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id2",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: "id1",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple keys, single sig key, jwt with kid, match",
|
||||||
|
args{
|
||||||
|
keyID: "id1",
|
||||||
|
use: KeyUseSignature,
|
||||||
|
expectedAlg: "RS256",
|
||||||
|
keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Use: "enc",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
key: jose.JSONWebKey{
|
||||||
|
Use: "sig",
|
||||||
|
Key: &rsa.PublicKey{},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := FindMatchingKey(tt.args.keyID, tt.args.use, tt.args.expectedAlg, tt.args.keys...)
|
||||||
|
if (tt.res.err != nil && !errors.Is(err, tt.res.err)) || (tt.res.err == nil && err != nil) {
|
||||||
|
t.Errorf("FindKey() error, got = %v, want = %v", err, tt.res.err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.res.key) {
|
||||||
|
t.Errorf("FindKey() got = %v, want %v", got, tt.res.key)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ var (
|
||||||
ErrSignatureMultiple = errors.New("id_token contains multiple signatures")
|
ErrSignatureMultiple = errors.New("id_token contains multiple signatures")
|
||||||
ErrSignatureUnsupportedAlg = errors.New("signature algorithm not supported")
|
ErrSignatureUnsupportedAlg = errors.New("signature algorithm not supported")
|
||||||
ErrSignatureInvalidPayload = errors.New("signature does not match Payload")
|
ErrSignatureInvalidPayload = errors.New("signature does not match Payload")
|
||||||
|
ErrSignatureInvalid = errors.New("invalid signature")
|
||||||
ErrExpired = errors.New("token has expired")
|
ErrExpired = errors.New("token has expired")
|
||||||
ErrIatMissing = errors.New("issuedAt of token is missing")
|
ErrIatMissing = errors.New("issuedAt of token is missing")
|
||||||
ErrIatInFuture = errors.New("issuedAt of token is in the future")
|
ErrIatInFuture = errors.New("issuedAt of token is in the future")
|
||||||
|
@ -143,7 +144,7 @@ func CheckSignature(ctx context.Context, token string, payload []byte, claims Cl
|
||||||
|
|
||||||
signedPayload, err := set.VerifySignature(ctx, jws)
|
signedPayload, err := set.VerifySignature(ctx, jws)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("%w (%v)", ErrSignatureInvalid, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(signedPayload, payload) {
|
if !bytes.Equal(signedPayload, payload) {
|
||||||
|
|
10
pkg/op/op.go
10
pkg/op/op.go
|
@ -2,7 +2,7 @@ package op
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -280,12 +280,12 @@ type openIDKeySet struct {
|
||||||
func (o *openIDKeySet) VerifySignature(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) {
|
func (o *openIDKeySet) VerifySignature(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) {
|
||||||
keySet, err := o.Storage.GetKeySet(ctx)
|
keySet, err := o.Storage.GetKeySet(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("error fetching keys")
|
return nil, fmt.Errorf("error fetching keys: %w", err)
|
||||||
}
|
}
|
||||||
keyID, alg := oidc.GetKeyIDAndAlg(jws)
|
keyID, alg := oidc.GetKeyIDAndAlg(jws)
|
||||||
key, ok := oidc.FindKey(keyID, oidc.KeyUseSignature, alg, keySet.Keys...)
|
key, err := oidc.FindMatchingKey(keyID, oidc.KeyUseSignature, alg, keySet.Keys...)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, errors.New("invalid kid")
|
return nil, fmt.Errorf("invalid signature: %w", err)
|
||||||
}
|
}
|
||||||
return jws.Verify(&key)
|
return jws.Verify(&key)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue