3
0

Bump github.com/crewjam/saml from 0.4.6 to 0.4.13 in /server

Bumps [github.com/crewjam/saml](https://github.com/crewjam/saml) from 0.4.6 to 0.4.13.
- [Release notes](https://github.com/crewjam/saml/releases)
- [Commits](https://github.com/crewjam/saml/compare/v0.4.6...v0.4.13)

---
updated-dependencies:
- dependency-name: github.com/crewjam/saml
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2023-04-11 10:27:46 +00:00 committed by EmmyMay
parent b5f6c212ff
commit bf64c9ff68
34 changed files with 1231 additions and 679 deletions

17
server/go.mod vendored
View File

@ -14,7 +14,7 @@ require (
github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/brianvoe/gofakeit/v6 v6.16.0
github.com/crewjam/saml v0.4.6
github.com/crewjam/saml v0.4.13
github.com/crusttech/go-oidc v0.0.0-20180918092017-982855dad3e1
github.com/davecgh/go-spew v1.1.1
github.com/denisenkom/go-mssqldb v0.12.3
@ -24,6 +24,7 @@ require (
github.com/doug-martin/goqu/v9 v9.18.0
github.com/edwvee/exiffix v0.0.0-20210922235313-0f6cbda5e58f
github.com/evanw/esbuild v0.14.38
github.com/fogleman/gg v1.3.0
github.com/fsnotify/fsnotify v1.5.3
github.com/gabriel-vasile/mimetype v1.4.0
github.com/getsentry/sentry-go v0.13.0
@ -33,7 +34,8 @@ require (
github.com/go-chi/jwtauth v1.2.0
github.com/go-oauth2/oauth2/v4 v4.4.3
github.com/go-sql-driver/mysql v1.6.0
github.com/golang-jwt/jwt/v4 v4.4.1
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.1.2
@ -61,18 +63,19 @@ require (
github.com/spf13/cobra v1.4.0
github.com/steinfletcher/apitest v1.5.11
github.com/steinfletcher/apitest-jsonpath v1.7.1
github.com/stretchr/testify v1.7.1
github.com/stretchr/testify v1.8.1
github.com/tidwall/btree v1.3.1
github.com/valyala/fastjson v1.6.3
go.uber.org/atomic v1.9.0
go.uber.org/zap v1.21.0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
golang.org/x/text v0.8.0
google.golang.org/grpc v1.46.0
google.golang.org/protobuf v1.28.0
gopkg.in/mail.v2 v2.3.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gopkg.in/yaml.v3 v3.0.1
moul.io/zapfilter v1.7.0
rsc.io/qr v0.2.0
)
@ -89,14 +92,12 @@ require (
github.com/crewjam/httperr v0.2.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect
github.com/dlclark/regexp2 v1.8.1 // indirect
github.com/fogleman/gg v1.3.0 // indirect
github.com/go-chi/chi v3.3.4+incompatible // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/goccy/go-json v0.9.6 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
@ -124,14 +125,12 @@ require (
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/russellhaering/goxmldsig v1.1.1 // indirect
github.com/russellhaering/goxmldsig v1.2.0 // indirect
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/valyala/fasthttp v1.35.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect

39
server/go.sum vendored
View File

@ -126,14 +126,14 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo=
github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
github.com/crewjam/saml v0.4.6 h1:XCUFPkQSJLvzyl4cW9OvpWUbRf0gE7VUpU8ZnilbeM4=
github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc=
github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
github.com/crusttech/go-oidc v0.0.0-20180918092017-982855dad3e1 h1:V2GKd4ImRY9lFUu3TclHNmqgJCADdA7muym9JuVEPlY=
github.com/crusttech/go-oidc v0.0.0-20180918092017-982855dad3e1/go.mod h1:2LVBu240CBZgYkGOSRx733tkh9QUNcH+fIqmeAsdrds=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
github.com/dchest/uniuri v1.2.0/go.mod h1:fSzm4SLHzNZvWLvWJew423PhAzkpNQYq+uNLq4kxhkY=
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
@ -222,10 +222,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
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/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
@ -278,8 +277,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -385,8 +385,9 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -505,10 +506,11 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM=
github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
@ -545,16 +547,19 @@ github.com/steinfletcher/apitest-jsonpath v1.7.1 h1:dj0Z/7DJt2Ts/R52OeVbnMp+gegc
github.com/steinfletcher/apitest-jsonpath v1.7.1/go.mod h1:FzU2i3ZIyIdF6yBI8a0DZ10gCC6jhiD1yAdU0nCz5Do=
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.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
github.com/tidwall/btree v0.0.0-20191029221954-400434d76274/go.mod h1:huei1BkDWJ3/sLXmO+bsCNELL+Bp2Kks9OLyQFkzvA8=
github.com/tidwall/btree v1.3.1 h1:636+tdVDs8Hjcf35Di260W2xCW4KuoXOKyk9QWOvCpA=
@ -636,10 +641,10 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@ -914,7 +919,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@ -1091,8 +1095,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -58,7 +58,7 @@ import (
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", samlsp.AttributeFromContext(r.Context(), "cn"))
fmt.Fprintf(w, "Hello, %s!", samlsp.AttributeFromContext(r.Context(), "displayName"))
}
func main() {

31
server/vendor/github.com/crewjam/saml/flate.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
package saml
import (
"compress/flate"
"fmt"
"io"
)
const flateUncompressLimit = 10 * 1024 * 1024 // 10MB
func newSaferFlateReader(r io.Reader) io.ReadCloser {
return &saferFlateReader{r: flate.NewReader(r)}
}
type saferFlateReader struct {
r io.ReadCloser
count int
}
func (r *saferFlateReader) Read(p []byte) (n int, err error) {
if r.count+len(p) > flateUncompressLimit {
return 0, fmt.Errorf("flate: uncompress limit exceeded (%d bytes)", flateUncompressLimit)
}
n, err = r.r.Read(p)
r.count += n
return n, err
}
func (r *saferFlateReader) Close() error {
return r.r.Close()
}

View File

@ -2,7 +2,6 @@ package saml
import (
"bytes"
"compress/flate"
"crypto"
"crypto/tls"
"crypto/x509"
@ -36,7 +35,10 @@ type Session struct {
ExpireTime time.Time
Index string
NameID string
NameID string
NameIDFormat string
SubjectID string
Groups []string
UserName string
UserEmail string
@ -360,7 +362,7 @@ func NewIdpAuthnRequest(idp *IdentityProvider, r *http.Request) (*IdpAuthnReques
if err != nil {
return nil, fmt.Errorf("cannot decode request: %s", err)
}
req.RequestBuffer, err = ioutil.ReadAll(flate.NewReader(bytes.NewReader(compressedRequest)))
req.RequestBuffer, err = ioutil.ReadAll(newSaferFlateReader(bytes.NewReader(compressedRequest)))
if err != nil {
return nil, fmt.Errorf("cannot decompress request: %s", err)
}
@ -734,6 +736,19 @@ func (DefaultAssertionMaker) MakeAssertion(req *IdpAuthnRequest, session *Sessio
})
}
if session.SubjectID != "" {
attributes = append(attributes, Attribute{
Name: "urn:oasis:names:tc:SAML:attribute:subject-id",
NameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
Values: []AttributeValue{
{
Type: "xs:string",
Value: session.SubjectID,
},
},
})
}
// allow for some clock skew in the validity period using the
// issuer's apparent clock.
notBefore := req.Now.Add(-1 * MaxClockSkew)
@ -743,6 +758,12 @@ func (DefaultAssertionMaker) MakeAssertion(req *IdpAuthnRequest, session *Sessio
notOnOrAfterAfter = notBefore.Add(MaxIssueDelay)
}
nameIDFormat := "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
if session.NameIDFormat != "" {
nameIDFormat = session.NameIDFormat
}
req.Assertion = &Assertion{
ID: fmt.Sprintf("id-%x", randomBytes(20)),
IssueInstant: TimeNow(),
@ -753,7 +774,7 @@ func (DefaultAssertionMaker) MakeAssertion(req *IdpAuthnRequest, session *Sessio
},
Subject: &Subject{
NameID: &NameID{
Format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
Format: nameIDFormat,
NameQualifier: req.IDP.Metadata().EntityID,
SPNameQualifier: req.ServiceProviderMetadata.EntityID,
Value: session.NameID,
@ -875,12 +896,23 @@ func (req *IdpAuthnRequest) MakeAssertionEl() error {
return nil
}
// WriteResponse writes the `Response` to the http.ResponseWriter. If
// `Response` is not already set, it calls MakeResponse to produce it.
func (req *IdpAuthnRequest) WriteResponse(w http.ResponseWriter) error {
// IdpAuthnRequestForm contans HTML form information to be submitted to the
// SAML HTTP POST binding ACS.
type IdpAuthnRequestForm struct {
URL string
SAMLResponse string
RelayState string
}
// PostBinding creates the HTTP POST form information for this
// `IdpAuthnRequest`. If `Response` is not already set, it calls MakeResponse
// to produce it.
func (req *IdpAuthnRequest) PostBinding() (IdpAuthnRequestForm, error) {
var form IdpAuthnRequestForm
if req.ResponseEl == nil {
if err := req.MakeResponse(); err != nil {
return err
return form, err
}
}
@ -888,45 +920,48 @@ func (req *IdpAuthnRequest) WriteResponse(w http.ResponseWriter) error {
doc.SetRoot(req.ResponseEl)
responseBuf, err := doc.WriteToBytes()
if err != nil {
return err
return form, err
}
// the only supported binding is the HTTP-POST binding
switch req.ACSEndpoint.Binding {
case HTTPPostBinding:
tmpl := template.Must(template.New("saml-post-form").Parse(`<html>` +
`<form method="post" action="{{.URL}}" id="SAMLResponseForm">` +
`<input type="hidden" name="SAMLResponse" value="{{.SAMLResponse}}" />` +
`<input type="hidden" name="RelayState" value="{{.RelayState}}" />` +
`<input id="SAMLSubmitButton" type="submit" value="Continue" />` +
`</form>` +
`<script>document.getElementById('SAMLSubmitButton').style.visibility='hidden';</script>` +
`<script>document.getElementById('SAMLResponseForm').submit();</script>` +
`</html>`))
data := struct {
URL string
SAMLResponse string
RelayState string
}{
URL: req.ACSEndpoint.Location,
SAMLResponse: base64.StdEncoding.EncodeToString(responseBuf),
RelayState: req.RelayState,
}
buf := bytes.NewBuffer(nil)
if err := tmpl.Execute(buf, data); err != nil {
return err
}
if _, err := io.Copy(w, buf); err != nil {
return err
}
return nil
default:
return fmt.Errorf("%s: unsupported binding %s",
if req.ACSEndpoint.Binding != HTTPPostBinding {
return form, fmt.Errorf("%s: unsupported binding %s",
req.ServiceProviderMetadata.EntityID,
req.ACSEndpoint.Binding)
}
form.URL = req.ACSEndpoint.Location
form.SAMLResponse = base64.StdEncoding.EncodeToString(responseBuf)
form.RelayState = req.RelayState
return form, nil
}
// WriteResponse writes the `Response` to the http.ResponseWriter. If
// `Response` is not already set, it calls MakeResponse to produce it.
func (req *IdpAuthnRequest) WriteResponse(w http.ResponseWriter) error {
form, err := req.PostBinding()
if err != nil {
return err
}
tmpl := template.Must(template.New("saml-post-form").Parse(`<html>` +
`<form method="post" action="{{.URL}}" id="SAMLResponseForm">` +
`<input type="hidden" name="SAMLResponse" value="{{.SAMLResponse}}" />` +
`<input type="hidden" name="RelayState" value="{{.RelayState}}" />` +
`<input id="SAMLSubmitButton" type="submit" value="Continue" />` +
`</form>` +
`<script>document.getElementById('SAMLSubmitButton').style.visibility='hidden';</script>` +
`<script>document.getElementById('SAMLResponseForm').submit();</script>` +
`</html>`))
buf := bytes.NewBuffer(nil)
if err := tmpl.Execute(buf, form); err != nil {
return err
}
if _, err := io.Copy(w, buf); err != nil {
return err
}
return nil
}
// getSPEncryptionCert returns the certificate which we can use to encrypt things

View File

@ -1,13 +1,13 @@
// Package saml contains a partial implementation of the SAML standard in golang.
// SAML is a standard for identity federation, i.e. either allowing a third party to authenticate your users or allowing third parties to rely on us to authenticate their users.
//
// Introduction
// # Introduction
//
// In SAML parlance an Identity Provider (IDP) is a service that knows how to authenticate users. A Service Provider (SP) is a service that delegates authentication to an IDP. If you are building a service where users log in with someone else's credentials, then you are a Service Provider. This package supports implementing both service providers and identity providers.
//
// The core package contains the implementation of SAML. The package samlsp provides helper middleware suitable for use in Service Provider applications. The package samlidp provides a rudimentary IDP service that is useful for testing or as a starting point for other integrations.
//
// Breaking Changes
// # Breaking Changes
//
// Version 0.4.0 introduces a few breaking changes to the _samlsp_ package in order to make the package more extensible, and to clean up the interfaces a bit. The default behavior remains the same, but you can now provide interface implementations of _RequestTracker_ (which tracks pending requests), _Session_ (which handles maintaining a session) and _OnError_ which handles reporting errors.
//
@ -32,7 +32,7 @@
// - `CookieDomain` - Instead assign a custom CookieRequestTracker or CookieSessionProvider
// - `CookieDomain` - Instead assign a custom CookieRequestTracker or CookieSessionProvider
//
// Getting Started as a Service Provider
// # Getting Started as a Service Provider
//
// Let us assume we have a simple web application to protect. We'll modify this application so it uses SAML to authenticate users.
//
@ -40,24 +40,27 @@
// package main
//
// import (
// "fmt"
// "net/http"
//
// "fmt"
// "net/http"
//
// )
//
// func hello(w http.ResponseWriter, r *http.Request) {
// fmt.Fprintf(w, "Hello, World!")
// }
// func hello(w http.ResponseWriter, r *http.Request) {
// fmt.Fprintf(w, "Hello, World!")
// }
//
// func main() {
// app := http.HandlerFunc(hello)
// http.Handle("/hello", app)
// http.ListenAndServe(":8000", nil)
// }
//
// func main() {
// app := http.HandlerFunc(hello)
// http.Handle("/hello", app)
// http.ListenAndServe(":8000", nil)
// }
// ```
//
// Each service provider must have an self-signed X.509 key pair established. You can generate your own with something like this:
//
// openssl req -x509 -newkey rsa:2048 -keyout myservice.key -out myservice.cert -days 365 -nodes -subj "/CN=myservice.example.com"
// openssl req -x509 -newkey rsa:2048 -keyout myservice.key -out myservice.cert -days 365 -nodes -subj "/CN=myservice.example.com"
//
// We will use `samlsp.Middleware` to wrap the endpoint we want to protect. Middleware provides both an `http.Handler` to serve the SAML specific URLs and a set of wrappers to require the user to be logged in. We also provide the URL where the service provider can fetch the metadata from the IDP at startup. In our case, we'll use [samltest.id](https://samltest.id/), an identity provider designed for testing.
//
@ -65,57 +68,60 @@
// package main
//
// import (
// "crypto/rsa"
// "crypto/tls"
// "crypto/x509"
// "fmt"
// "net/http"
// "net/url"
//
// "github.com/crewjam/saml/samlsp"
// "crypto/rsa"
// "crypto/tls"
// "crypto/x509"
// "fmt"
// "net/http"
// "net/url"
//
// "github.com/crewjam/saml/samlsp"
//
// )
//
// func hello(w http.ResponseWriter, r *http.Request) {
// fmt.Fprintf(w, "Hello, %s!", samlsp.Token(r.Context()).Attributes.Get("cn"))
// }
// func hello(w http.ResponseWriter, r *http.Request) {
// fmt.Fprintf(w, "Hello, %s!", samlsp.Token(r.Context()).Attributes.Get("cn"))
// }
//
// func main() {
// keyPair, err := tls.LoadX509KeyPair("myservice.cert", "myservice.key")
// if err != nil {
// panic(err) // TODO handle error
// }
// keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
// if err != nil {
// panic(err) // TODO handle error
// }
// func main() {
// keyPair, err := tls.LoadX509KeyPair("myservice.cert", "myservice.key")
// if err != nil {
// panic(err) // TODO handle error
// }
// keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
// if err != nil {
// panic(err) // TODO handle error
// }
//
// idpMetadataURL, err := url.Parse("https://samltest.id/saml/idp")
// if err != nil {
// panic(err) // TODO handle error
// }
// idpMetadataURL, err := url.Parse("https://samltest.id/saml/idp")
// if err != nil {
// panic(err) // TODO handle error
// }
//
// rootURL, err := url.Parse("http://localhost:8000")
// if err != nil {
// panic(err) // TODO handle error
// }
// rootURL, err := url.Parse("http://localhost:8000")
// if err != nil {
// panic(err) // TODO handle error
// }
//
// samlSP, _ := samlsp.New(samlsp.Options{
// URL: *rootURL,
// Key: keyPair.PrivateKey.(*rsa.PrivateKey),
// Certificate: keyPair.Leaf,
// IDPMetadataURL: idpMetadataURL,
// })
// app := http.HandlerFunc(hello)
// http.Handle("/hello", samlSP.RequireAccount(app))
// http.Handle("/saml/", samlSP)
// http.ListenAndServe(":8000", nil)
// }
//
// samlSP, _ := samlsp.New(samlsp.Options{
// URL: *rootURL,
// Key: keyPair.PrivateKey.(*rsa.PrivateKey),
// Certificate: keyPair.Leaf,
// IDPMetadataURL: idpMetadataURL,
// })
// app := http.HandlerFunc(hello)
// http.Handle("/hello", samlSP.RequireAccount(app))
// http.Handle("/saml/", samlSP)
// http.ListenAndServe(":8000", nil)
// }
// ```
//
// Next we'll have to register our service provider with the identity provider to establish trust from the service provider to the IDP. For [samltest.id](https://samltest.id/), you can do something like:
//
// mdpath=saml-test-$USER-$HOST.xml
// curl localhost:8000/saml/metadata > $mdpath
// mdpath=saml-test-$USER-$HOST.xml
// curl localhost:8000/saml/metadata > $mdpath
//
// Navigate to https://samltest.id/upload.php and upload the file you fetched.
//
@ -133,11 +139,11 @@
//
// 1. This time when `localhost:8000/hello` is requested there is a valid session and so the main content is served.
//
// Getting Started as an Identity Provider
// # Getting Started as an Identity Provider
//
// Please see `example/idp/` for a substantially complete example of how to use the library and helpers to be an identity provider.
//
// Support
// # Support
//
// The SAML standard is huge and complex with many dark corners and strange, unused features. This package implements the most commonly used subset of these features required to provide a single sign on experience. The package supports at least the subset of SAML known as [interoperable SAML](http://saml2int.org).
//
@ -145,13 +151,13 @@
//
// The package can produce signed SAML assertions, and can validate both signed and encrypted SAML assertions. It does not support signed or encrypted requests.
//
// RelayState
// # RelayState
//
// The _RelayState_ parameter allows you to pass user state information across the authentication flow. The most common use for this is to allow a user to request a deep link into your site, be redirected through the SAML login flow, and upon successful completion, be directed to the originally requested link, rather than the root.
//
// Unfortunately, _RelayState_ is less useful than it could be. Firstly, it is not authenticated, so anything you supply must be signed to avoid XSS or CSRF. Secondly, it is limited to 80 bytes in length, which precludes signing. (See section 3.6.3.1 of SAMLProfiles.)
//
// References
// # References
//
// The SAML specification is a collection of PDFs (sadly):
//
@ -165,7 +171,7 @@
//
// [SAMLtest](https://samltest.id/) is a testing ground for SAML service and identity providers.
//
// Security Issues
// # Security Issues
//
// Please do not report security issues in the issue tracker. Rather, please contact me directly at ross@kndr.org ([PGP Key `78B6038B3B9DFB88`](https://keybase.io/crewjam)).
package saml

View File

@ -186,12 +186,19 @@ func (m *Middleware) CreateSessionFromAssertion(w http.ResponseWriter, r *http.R
if trackedRequestIndex := r.Form.Get("RelayState"); trackedRequestIndex != "" {
trackedRequest, err := m.RequestTracker.GetTrackedRequest(r, trackedRequestIndex)
if err != nil {
m.OnError(w, r, err)
return
}
m.RequestTracker.StopTrackingRequest(w, r, trackedRequestIndex)
if err == http.ErrNoCookie && m.ServiceProvider.AllowIDPInitiated {
if uri := r.Form.Get("RelayState"); uri != "" {
redirectURI = uri
}
} else {
m.OnError(w, r, err)
return
}
} else {
m.RequestTracker.StopTrackingRequest(w, r, trackedRequestIndex)
redirectURI = trackedRequest.URI
redirectURI = trackedRequest.URI
}
}
if err := m.Session.CreateSession(w, r, assertion); err != nil {
@ -209,9 +216,8 @@ func (m *Middleware) CreateSessionFromAssertion(w http.ResponseWriter, r *http.R
//
// For example:
//
// goji.Use(m.RequireAccount)
// goji.Use(RequireAttributeMiddleware("eduPersonAffiliation", "Staff"))
//
// goji.Use(m.RequireAccount)
// goji.Use(RequireAttributeMiddleware("eduPersonAffiliation", "Staff"))
func RequireAttribute(name, value string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@ -14,19 +14,23 @@ import (
// Options represents the parameters for creating a new middleware
type Options struct {
EntityID string
URL url.URL
Key *rsa.PrivateKey
Certificate *x509.Certificate
Intermediates []*x509.Certificate
AllowIDPInitiated bool
DefaultRedirectURI string
IDPMetadata *saml.EntityDescriptor
SignRequest bool
UseArtifactResponse bool
ForceAuthn bool // TODO(ross): this should be *bool
CookieSameSite http.SameSite
RelayStateFunc func(w http.ResponseWriter, r *http.Request) string
EntityID string
URL url.URL
Key *rsa.PrivateKey
Certificate *x509.Certificate
Intermediates []*x509.Certificate
HTTPClient *http.Client
AllowIDPInitiated bool
DefaultRedirectURI string
IDPMetadata *saml.EntityDescriptor
SignRequest bool
UseArtifactResponse bool
ForceAuthn bool // TODO(ross): this should be *bool
RequestedAuthnContext *saml.RequestedAuthnContext
CookieSameSite http.SameSite
CookieName string
RelayStateFunc func(w http.ResponseWriter, r *http.Request) string
LogoutBindings []string
}
// DefaultSessionCodec returns the default SessionCodec for the provided options,
@ -44,8 +48,12 @@ func DefaultSessionCodec(opts Options) JWTSessionCodec {
// DefaultSessionProvider returns the default SessionProvider for the provided options,
// a CookieSessionProvider configured to store sessions in a cookie.
func DefaultSessionProvider(opts Options) CookieSessionProvider {
cookieName := opts.CookieName
if cookieName == "" {
cookieName = defaultSessionCookieName
}
return CookieSessionProvider{
Name: defaultSessionCookieName,
Name: cookieName,
Domain: opts.URL.Host,
MaxAge: defaultSessionMaxAge,
HTTPOnly: true,
@ -100,19 +108,26 @@ func DefaultServiceProvider(opts Options) saml.ServiceProvider {
opts.DefaultRedirectURI = "/"
}
if len(opts.LogoutBindings) == 0 {
opts.LogoutBindings = []string{saml.HTTPPostBinding}
}
return saml.ServiceProvider{
EntityID: opts.EntityID,
Key: opts.Key,
Certificate: opts.Certificate,
Intermediates: opts.Intermediates,
MetadataURL: *metadataURL,
AcsURL: *acsURL,
SloURL: *sloURL,
IDPMetadata: opts.IDPMetadata,
ForceAuthn: forceAuthn,
SignatureMethod: signatureMethod,
AllowIDPInitiated: opts.AllowIDPInitiated,
DefaultRedirectURI: opts.DefaultRedirectURI,
EntityID: opts.EntityID,
Key: opts.Key,
Certificate: opts.Certificate,
HTTPClient: opts.HTTPClient,
Intermediates: opts.Intermediates,
MetadataURL: *metadataURL,
AcsURL: *acsURL,
SloURL: *sloURL,
IDPMetadata: opts.IDPMetadata,
ForceAuthn: forceAuthn,
RequestedAuthnContext: opts.RequestedAuthnContext,
SignatureMethod: signatureMethod,
AllowIDPInitiated: opts.AllowIDPInitiated,
DefaultRedirectURI: opts.DefaultRedirectURI,
LogoutBindings: opts.LogoutBindings,
}
}

View File

@ -8,11 +8,11 @@ import (
//
// There are two main reasons for this:
//
// 1. When the middleware initiates an authentication request it must track the original URL
// in order to redirect the user to the right place after the authentication completes.
// 1. When the middleware initiates an authentication request it must track the original URL
// in order to redirect the user to the right place after the authentication completes.
//
// 2. After the authentication completes, we want to ensure that the user presenting the
// assertion is actually the one the request it, to mitigate request forgeries.
// 2. After the authentication completes, we want to ensure that the user presenting the
// assertion is actually the one the request it, to mitigate request forgeries.
type RequestTracker interface {
// TrackRequest starts tracking the SAML request with the given ID. It returns an
// `index` that should be used as the RelayState in the SAMl request flow.

View File

@ -11,6 +11,24 @@ import (
"github.com/russellhaering/goxmldsig/etreeutils"
)
// RequestedAuthnContext represents the SAML object of the same name, an indication of the
// requirements on the authentication process.
type RequestedAuthnContext struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol RequestedAuthnContext"`
Comparison string `xml:",attr"`
AuthnContextClassRef string `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnContextClassRef"`
}
// Element returns an etree.Element representing the object in XML form.
func (r *RequestedAuthnContext) Element() *etree.Element {
el := etree.NewElement("samlp:RequestedAuthnContext")
el.CreateAttr("Comparison", r.Comparison)
elContext := etree.NewElement("saml:AuthnContextClassRef")
elContext.SetText(r.AuthnContextClassRef)
el.AddChild(elContext)
return el
}
// AuthnRequest represents the SAML object of the same name, a request from a service provider
// to authenticate a user.
//
@ -26,10 +44,10 @@ type AuthnRequest struct {
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Subject *Subject
NameIDPolicy *NameIDPolicy `xml:"urn:oasis:names:tc:SAML:2.0:protocol NameIDPolicy"`
Conditions *Conditions
//RequestedAuthnContext *RequestedAuthnContext // TODO
Subject *Subject
NameIDPolicy *NameIDPolicy `xml:"urn:oasis:names:tc:SAML:2.0:protocol NameIDPolicy"`
Conditions *Conditions
RequestedAuthnContext *RequestedAuthnContext
//Scoping *Scoping // TODO
ForceAuthn *bool `xml:",attr"`
@ -77,12 +95,12 @@ func (r *LogoutRequest) Element() *etree.Element {
if r.Issuer != nil {
el.AddChild(r.Issuer.Element())
}
if r.NameID != nil {
el.AddChild(r.NameID.Element())
}
if r.Signature != nil {
el.AddChild(r.Signature)
}
if r.NameID != nil {
el.AddChild(r.NameID.Element())
}
if r.SessionIndex != nil {
el.AddChild(r.SessionIndex.Element())
}
@ -159,7 +177,6 @@ func (r *LogoutRequest) Deflate() ([]byte, error) {
return b.Bytes(), nil
}
// Element returns an etree.Element representing the object
// Element returns an etree.Element representing the object in XML form.
func (r *AuthnRequest) Element() *etree.Element {
el := etree.NewElement("samlp:AuthnRequest")
@ -189,9 +206,9 @@ func (r *AuthnRequest) Element() *etree.Element {
if r.Conditions != nil {
el.AddChild(r.Conditions.Element())
}
//if r.RequestedAuthnContext != nil {
// el.AddChild(r.RequestedAuthnContext.Element())
//}
if r.RequestedAuthnContext != nil {
el.AddChild(r.RequestedAuthnContext.Element())
}
//if r.Scoping != nil {
// el.AddChild(r.Scoping.Element())
//}
@ -306,7 +323,7 @@ func (a *NameIDPolicy) Element() *etree.Element {
// ArtifactResolve represents the SAML object of the same name.
type ArtifactResolve struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol ArtifactResponse"`
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol ArtifactResolve"`
ID string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
@ -747,7 +764,7 @@ func (a *Assertion) Element() *etree.Element {
for _, attributeStatement := range a.AttributeStatements {
el.AddChild(attributeStatement.Element())
}
err := etreeutils.TransformExcC14n(el, canonicalizerPrefixList)
err := etreeutils.TransformExcC14n(el, canonicalizerPrefixList, false)
if err != nil {
panic(err)
}

File diff suppressed because it is too large Load Diff

View File

@ -36,24 +36,39 @@ The part in the middle is the interesting bit. It's called the Claims and conta
This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own.
## Installation Guidelines
1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program.
```sh
go get -u github.com/golang-jwt/jwt/v4
```
2. Import it in your code:
```go
import "github.com/golang-jwt/jwt/v4"
```
## Examples
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt) for examples of usage:
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage:
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac)
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac)
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt#pkg-examples)
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac)
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-New-Hmac)
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#pkg-examples)
## Extensions
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
This library publishes all the necessary components for adding your own signing methods or key functions. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod` or provide a `jwt.Keyfunc`.
A common use case would be integrating with different 3rd party signature providers, like key management services from various cloud providers or Hardware Security Modules (HSMs).
A common use case would be integrating with different 3rd party signature providers, like key management services from various cloud providers or Hardware Security Modules (HSMs) or to implement additional standards.
| Extension | Purpose | Repo |
|-----------|----------------------------------------------------------------------------------------------|--------------------------------------------|
| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go |
| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms |
| Extension | Purpose | Repo |
| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go |
| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms |
| JWKS | Provides support for JWKS ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517)) as a `jwt.Keyfunc` | https://github.com/MicahParks/keyfunc |
*Disclaimer*: Unless otherwise specified, these integrations are maintained by third parties and should not be considered as a primary offer by any of the mentioned cloud providers
@ -81,7 +96,7 @@ A token is simply a JSON object that is signed by its author. this tells you exa
* The author of the token was in the possession of the signing secret
* The data has not been modified since it was signed
It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library.
It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. The companion project https://github.com/golang-jwt/jwe aims at a (very) experimental implementation of the JWE standard.
### Choosing a Signing Method
@ -95,10 +110,10 @@ Asymmetric signing methods, such as RSA, use different keys for signing and veri
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
### JWT and OAuth
@ -116,7 +131,7 @@ This library uses descriptive error messages whenever possible. If you are not g
## More
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt).
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt/v4).
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.

19
server/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# Security Policy
## Supported Versions
As of February 2022 (and until this document is updated), the latest version `v4` is supported.
## Reporting a Vulnerability
If you think you found a vulnerability, and even if you are not sure, please report it to jwt-go-security@googlegroups.com or one of the other [golang-jwt maintainers](https://github.com/orgs/golang-jwt/people). Please try be explicit, describe steps to reproduce the security issue with code example(s).
You will receive a response within a timely manner. If the issue is confirmed, we will do our best to release a patch as soon as possible given the complexity of the problem.
## Public Discussions
Please avoid publicly discussing a potential security vulnerability.
Let's take this offline and find a solution first, this limits the potential impact as much as possible.
We appreciate your help!

View File

@ -265,9 +265,5 @@ func verifyIss(iss string, cmp string, required bool) bool {
if iss == "" {
return !required
}
if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
return true
} else {
return false
}
return subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0
}

View File

@ -42,6 +42,13 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
}
// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
// interface. This provides default values which can be overridden and allows a caller to use their own type, rather
// than the default MapClaims implementation of Claims.
//
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
token, parts, err := p.ParseUnverified(tokenString, claims)
if err != nil {

View File

@ -1,3 +1,4 @@
//go:build go1.4
// +build go1.4
package jwt

View File

@ -7,7 +7,6 @@ import (
"time"
)
// DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515
// states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations
// of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global
@ -100,6 +99,11 @@ func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token
return NewParser(options...).Parse(tokenString, keyFunc)
}
// ParseWithClaims is a shortcut for NewParser().ParseWithClaims().
//
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
}

View File

@ -53,9 +53,23 @@ func (date NumericDate) MarshalJSON() (b []byte, err error) {
if TimePrecision < time.Second {
prec = int(math.Log10(float64(time.Second) / float64(TimePrecision)))
}
f := float64(date.Truncate(TimePrecision).UnixNano()) / float64(time.Second)
truncatedDate := date.Truncate(TimePrecision)
return []byte(strconv.FormatFloat(f, 'f', prec, 64)), nil
// For very large timestamps, UnixNano would overflow an int64, but this
// function requires nanosecond level precision, so we have to use the
// following technique to get round the issue:
// 1. Take the normal unix timestamp to form the whole number part of the
// output,
// 2. Take the result of the Nanosecond function, which retuns the offset
// within the second of the particular unix time instance, to form the
// decimal part of the output
// 3. Concatenate them to produce the final result
seconds := strconv.FormatInt(truncatedDate.Unix(), 10)
nanosecondsOffset := strconv.FormatFloat(float64(truncatedDate.Nanosecond())/float64(time.Second), 'f', prec, 64)
output := append([]byte(seconds), []byte(nanosecondsOffset)[1:]...)
return output, nil
}
// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a

View File

@ -1,6 +1,6 @@
# goxmldsig
[![Build Status](https://travis-ci.org/russellhaering/goxmldsig.svg?branch=master)](https://travis-ci.org/russellhaering/goxmldsig)
![Build Status](https://github.com/russellhaering/goxmldsig/actions/workflows/test.yml/badge.svg?branch=main)
[![GoDoc](https://godoc.org/github.com/russellhaering/goxmldsig?status.svg)](https://godoc.org/github.com/russellhaering/goxmldsig)
XML Digital Signatures implemented in pure Go.

View File

@ -26,11 +26,12 @@ func (c *NullCanonicalizer) Algorithm() AlgorithmID {
func (c *NullCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope, false))
return canonicalSerialize(canonicalPrep(el, scope, false, true))
}
type c14N10ExclusiveCanonicalizer struct {
prefixList string
comments bool
}
// MakeC14N10ExclusiveCanonicalizerWithPrefixList constructs an exclusive Canonicalizer
@ -38,12 +39,22 @@ type c14N10ExclusiveCanonicalizer struct {
func MakeC14N10ExclusiveCanonicalizerWithPrefixList(prefixList string) Canonicalizer {
return &c14N10ExclusiveCanonicalizer{
prefixList: prefixList,
comments: false,
}
}
// MakeC14N10ExclusiveWithCommentsCanonicalizerWithPrefixList constructs an exclusive Canonicalizer
// from a PrefixList in NMTOKENS format (a white space separated list).
func MakeC14N10ExclusiveWithCommentsCanonicalizerWithPrefixList(prefixList string) Canonicalizer {
return &c14N10ExclusiveCanonicalizer{
prefixList: prefixList,
comments: true,
}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N10ExclusiveCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
err := etreeutils.TransformExcC14n(el, c.prefixList)
err := etreeutils.TransformExcC14n(el, c.prefixList, c.comments)
if err != nil {
return nil, err
}
@ -52,58 +63,73 @@ func (c *c14N10ExclusiveCanonicalizer) Canonicalize(el *etree.Element) ([]byte,
}
func (c *c14N10ExclusiveCanonicalizer) Algorithm() AlgorithmID {
if c.comments {
return CanonicalXML10ExclusiveWithCommentsAlgorithmId
}
return CanonicalXML10ExclusiveAlgorithmId
}
type c14N11Canonicalizer struct{}
type c14N11Canonicalizer struct {
comments bool
}
// MakeC14N11Canonicalizer constructs an inclusive canonicalizer.
func MakeC14N11Canonicalizer() Canonicalizer {
return &c14N11Canonicalizer{}
return &c14N11Canonicalizer{
comments: false,
}
}
// MakeC14N11WithCommentsCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N11WithCommentsCanonicalizer() Canonicalizer {
return &c14N11Canonicalizer{
comments: true,
}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N11Canonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope, true))
return canonicalSerialize(canonicalPrep(el, scope, true, c.comments))
}
func (c *c14N11Canonicalizer) Algorithm() AlgorithmID {
if c.comments {
return CanonicalXML11WithCommentsAlgorithmId
}
return CanonicalXML11AlgorithmId
}
type c14N10RecCanonicalizer struct{}
type c14N10RecCanonicalizer struct {
comments bool
}
// MakeC14N10RecCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N10RecCanonicalizer() Canonicalizer {
return &c14N10RecCanonicalizer{}
return &c14N10RecCanonicalizer{
comments: false,
}
}
// MakeC14N10WithCommentsCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N10WithCommentsCanonicalizer() Canonicalizer {
return &c14N10RecCanonicalizer{
comments: true,
}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N10RecCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope, true))
return canonicalSerialize(canonicalPrep(el, scope, true, c.comments))
}
func (c *c14N10RecCanonicalizer) Algorithm() AlgorithmID {
if c.comments {
return CanonicalXML10WithCommentsAlgorithmId
}
return CanonicalXML10RecAlgorithmId
}
type c14N10CommentCanonicalizer struct{}
// MakeC14N10CommentCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N10CommentCanonicalizer() Canonicalizer {
return &c14N10CommentCanonicalizer{}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N10CommentCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope, true))
}
func (c *c14N10CommentCanonicalizer) Algorithm() AlgorithmID {
return CanonicalXML10CommentAlgorithmId
}
func composeAttr(space, key string) string {
@ -132,7 +158,7 @@ const nsSpace = "xmlns"
//
// TODO(russell_h): This is very similar to excCanonicalPrep - perhaps they should
// be unified into one parameterized function?
func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}, strip bool) *etree.Element {
func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}, strip bool, comments bool) *etree.Element {
_seenSoFar := make(map[string]struct{})
for k, v := range seenSoFar {
_seenSoFar[k] = v
@ -140,16 +166,29 @@ func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}, strip bool)
ne := el.Copy()
sort.Sort(etreeutils.SortedAttrs(ne.Attr))
if len(ne.Attr) != 0 {
for _, attr := range ne.Attr {
if attr.Space != nsSpace {
continue
}
key := attr.Space + ":" + attr.Key
if _, seen := _seenSoFar[key]; seen {
ne.RemoveAttr(attr.Space + ":" + attr.Key)
n := 0
for _, attr := range ne.Attr {
if attr.Space != nsSpace {
ne.Attr[n] = attr
n++
continue
}
key := attr.Space + ":" + attr.Key
if _, seen := _seenSoFar[key]; !seen {
ne.Attr[n] = attr
n++
_seenSoFar[key] = struct{}{}
}
}
ne.Attr = ne.Attr[:n]
if !comments {
c := 0
for c < len(ne.Child) {
if _, ok := ne.Child[c].(*etree.Comment); ok {
ne.RemoveChildAt(c)
} else {
_seenSoFar[key] = struct{}{}
c++
}
}
}
@ -157,7 +196,7 @@ func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}, strip bool)
for i, token := range ne.Child {
childElement, ok := token.(*etree.Element)
if ok {
ne.Child[i] = canonicalPrep(childElement, _seenSoFar, strip)
ne.Child[i] = canonicalPrep(childElement, _seenSoFar, strip, comments)
}
}

View File

@ -8,7 +8,7 @@ import (
)
// TransformExcC14n transforms the passed element into xml-exc-c14n form.
func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string) error {
func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string, comments bool) error {
prefixes := strings.Fields(inclusiveNamespacesPrefixList)
prefixSet := make(map[string]struct{}, len(prefixes))
@ -16,7 +16,7 @@ func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string) e
prefixSet[prefix] = struct{}{}
}
err := transformExcC14n(DefaultNSContext, DefaultNSContext, el, prefixSet)
err := transformExcC14n(DefaultNSContext, DefaultNSContext, el, prefixSet, comments)
if err != nil {
return err
}
@ -24,7 +24,7 @@ func TransformExcC14n(el *etree.Element, inclusiveNamespacesPrefixList string) e
return nil
}
func transformExcC14n(ctx, declared NSContext, el *etree.Element, inclusiveNamespaces map[string]struct{}) error {
func transformExcC14n(ctx, declared NSContext, el *etree.Element, inclusiveNamespaces map[string]struct{}, comments bool) error {
scope, err := ctx.SubContext(el)
if err != nil {
return err
@ -86,9 +86,20 @@ func transformExcC14n(ctx, declared NSContext, el *etree.Element, inclusiveNames
sort.Sort(SortedAttrs(el.Attr))
if !comments {
c := 0
for c < len(el.Child) {
if _, ok := el.Child[c].(*etree.Comment); ok {
el.RemoveChildAt(c)
} else {
c++
}
}
}
// Transform child elements
for _, child := range el.ChildElements() {
err := transformExcC14n(scope, declared, child, inclusiveNamespaces)
err := transformExcC14n(scope, declared, child, inclusiveNamespaces, comments)
if err != nil {
return err
}

View File

@ -21,7 +21,7 @@ var (
// ErrMissingSignature indicates that no enveloped signature was found referencing
// the top level element passed for signature verification.
ErrMissingSignature = errors.New("Missing signature referencing the top-level element")
ErrInvalidSignature = errors.New( "Invalid Signature")
ErrInvalidSignature = errors.New("Invalid Signature")
)
type ValidationContext struct {
@ -70,7 +70,7 @@ func mapPathToElement(tree, el *etree.Element) []int {
for i, child := range tree.Child {
if childElement, ok := child.(*etree.Element); ok {
childPath := mapPathToElement(childElement, el)
if childElement != nil {
if childPath != nil {
return append([]int{i}, childPath...)
}
}
@ -138,14 +138,25 @@ func (ctx *ValidationContext) transform(
canonicalizer = MakeC14N10ExclusiveCanonicalizerWithPrefixList(prefixList)
case CanonicalXML10ExclusiveWithCommentsAlgorithmId:
var prefixList string
if transform.InclusiveNamespaces != nil {
prefixList = transform.InclusiveNamespaces.PrefixList
}
canonicalizer = MakeC14N10ExclusiveWithCommentsCanonicalizerWithPrefixList(prefixList)
case CanonicalXML11AlgorithmId:
canonicalizer = MakeC14N11Canonicalizer()
case CanonicalXML11WithCommentsAlgorithmId:
canonicalizer = MakeC14N11WithCommentsCanonicalizer()
case CanonicalXML10RecAlgorithmId:
canonicalizer = MakeC14N10RecCanonicalizer()
case CanonicalXML10CommentAlgorithmId:
canonicalizer = MakeC14N10CommentCanonicalizer()
case CanonicalXML10WithCommentsAlgorithmId:
canonicalizer = MakeC14N10WithCommentsCanonicalizer()
default:
return nil, nil, errors.New("Unknown Transform Algorithm: " + algo)
@ -353,9 +364,9 @@ func (ctx *ValidationContext) findSignature(root *etree.Element) (*types.Signatu
var canonicalSignedInfo *etree.Element
switch AlgorithmID(c14NAlgorithm) {
case CanonicalXML10ExclusiveAlgorithmId:
err := etreeutils.TransformExcC14n(detachedSignedInfo, "")
switch alg := AlgorithmID(c14NAlgorithm); alg {
case CanonicalXML10ExclusiveAlgorithmId, CanonicalXML10ExclusiveWithCommentsAlgorithmId:
err := etreeutils.TransformExcC14n(detachedSignedInfo, "", alg == CanonicalXML10ExclusiveWithCommentsAlgorithmId)
if err != nil {
return err
}
@ -366,14 +377,11 @@ func (ctx *ValidationContext) findSignature(root *etree.Element) (*types.Signatu
// removing of elements below.
canonicalSignedInfo = detachedSignedInfo
case CanonicalXML11AlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{}, true)
case CanonicalXML11AlgorithmId, CanonicalXML10RecAlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{}, true, false)
case CanonicalXML10RecAlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{}, true)
case CanonicalXML10CommentAlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{}, true)
case CanonicalXML11WithCommentsAlgorithmId, CanonicalXML10WithCommentsAlgorithmId:
canonicalSignedInfo = canonicalPrep(detachedSignedInfo, map[string]struct{}{}, true, true)
default:
return fmt.Errorf("invalid CanonicalizationMethod on Signature: %s", c14NAlgorithm)

View File

@ -47,11 +47,14 @@ const (
//Well-known signature algorithms
const (
// Supported canonicalization algorithms
CanonicalXML10ExclusiveAlgorithmId AlgorithmID = "http://www.w3.org/2001/10/xml-exc-c14n#"
CanonicalXML11AlgorithmId AlgorithmID = "http://www.w3.org/2006/12/xml-c14n11"
CanonicalXML10ExclusiveAlgorithmId AlgorithmID = "http://www.w3.org/2001/10/xml-exc-c14n#"
CanonicalXML10ExclusiveWithCommentsAlgorithmId AlgorithmID = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"
CanonicalXML10RecAlgorithmId AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
CanonicalXML10CommentAlgorithmId AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
CanonicalXML11AlgorithmId AlgorithmID = "http://www.w3.org/2006/12/xml-c14n11"
CanonicalXML11WithCommentsAlgorithmId AlgorithmID = "http://www.w3.org/2006/12/xml-c14n11#WithComments"
CanonicalXML10RecAlgorithmId AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
CanonicalXML10WithCommentsAlgorithmId AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
EnvelopedSignatureAltorithmId AlgorithmID = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
)

View File

@ -35,7 +35,7 @@ const reportTemplate = `<!DOCTYPE html>
}
.copy-to-clipboard-button {
background-color: #FFFFFF;
background-color: #fff;
border: 1px solid #eee;
cursor: pointer;
font-size: 12px;

View File

@ -1,6 +1,7 @@
package assert
import (
"bytes"
"fmt"
"reflect"
"time"
@ -32,7 +33,8 @@ var (
stringType = reflect.TypeOf("")
timeType = reflect.TypeOf(time.Time{})
timeType = reflect.TypeOf(time.Time{})
bytesType = reflect.TypeOf([]byte{})
)
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
@ -323,6 +325,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
}
case reflect.Slice:
{
// We only care about the []byte type.
if !canConvert(obj1Value, bytesType) {
break
}
// []byte can be compared!
bytesObj1, ok := obj1.([]byte)
if !ok {
bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
}
bytesObj2, ok := obj2.([]byte)
if !ok {
bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
}
return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
}
}
return compareEqual, false

View File

@ -9,7 +9,7 @@ package assert
import "reflect"
// Wrapper around reflect.Value.CanConvert, for compatability
// Wrapper around reflect.Value.CanConvert, for compatibility
// reasons.
func canConvert(value reflect.Value, to reflect.Type) bool {
return value.CanConvert(to)

View File

@ -736,6 +736,16 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
}
// WithinRangef asserts that a time is within a time range (inclusive).
//
// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...)
}
// YAMLEqf asserts that two YAML strings are equivalent.
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {

View File

@ -1461,6 +1461,26 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
}
// WithinRange asserts that a time is within a time range (inclusive).
//
// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return WithinRange(a.t, actual, start, end, msgAndArgs...)
}
// WithinRangef asserts that a time is within a time range (inclusive).
//
// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return WithinRangef(a.t, actual, start, end, msg, args...)
}
// YAMLEq asserts that two YAML strings are equivalent.
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {

View File

@ -8,6 +8,7 @@ import (
"fmt"
"math"
"os"
"path/filepath"
"reflect"
"regexp"
"runtime"
@ -144,7 +145,8 @@ func CallerInfo() []string {
if len(parts) > 1 {
dir := parts[len(parts)-2]
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
path, _ := filepath.Abs(file)
callers = append(callers, fmt.Sprintf("%s:%d", path, line))
}
}
@ -563,16 +565,17 @@ func isEmpty(object interface{}) bool {
switch objValue.Kind() {
// collection types are empty when they have no element
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
case reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// pointers are empty if nil or if the value they point to is empty
// pointers are empty if nil or if the value they point to is empty
case reflect.Ptr:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
return isEmpty(deref)
// for all other types, compare against the zero value
// for all other types, compare against the zero value
// array types are empty when they match their zero-initialized state
default:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
@ -815,7 +818,6 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
return true // we consider nil to be equal to the nil set
}
subsetValue := reflect.ValueOf(subset)
defer func() {
if e := recover(); e != nil {
ok = false
@ -825,14 +827,32 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
listKind := reflect.TypeOf(list).Kind()
subsetKind := reflect.TypeOf(subset).Kind()
if listKind != reflect.Array && listKind != reflect.Slice {
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
}
if subsetKind != reflect.Array && subsetKind != reflect.Slice {
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
}
subsetValue := reflect.ValueOf(subset)
if subsetKind == reflect.Map && listKind == reflect.Map {
listValue := reflect.ValueOf(list)
subsetKeys := subsetValue.MapKeys()
for i := 0; i < len(subsetKeys); i++ {
subsetKey := subsetKeys[i]
subsetElement := subsetValue.MapIndex(subsetKey).Interface()
listElement := listValue.MapIndex(subsetKey).Interface()
if !ObjectsAreEqual(subsetElement, listElement) {
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, subsetElement), msgAndArgs...)
}
}
return true
}
for i := 0; i < subsetValue.Len(); i++ {
element := subsetValue.Index(i).Interface()
ok, found := containsElement(list, element)
@ -859,7 +879,6 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
}
subsetValue := reflect.ValueOf(subset)
defer func() {
if e := recover(); e != nil {
ok = false
@ -869,14 +888,32 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
listKind := reflect.TypeOf(list).Kind()
subsetKind := reflect.TypeOf(subset).Kind()
if listKind != reflect.Array && listKind != reflect.Slice {
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
}
if subsetKind != reflect.Array && subsetKind != reflect.Slice {
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
}
subsetValue := reflect.ValueOf(subset)
if subsetKind == reflect.Map && listKind == reflect.Map {
listValue := reflect.ValueOf(list)
subsetKeys := subsetValue.MapKeys()
for i := 0; i < len(subsetKeys); i++ {
subsetKey := subsetKeys[i]
subsetElement := subsetValue.MapIndex(subsetKey).Interface()
listElement := listValue.MapIndex(subsetKey).Interface()
if !ObjectsAreEqual(subsetElement, listElement) {
return true
}
}
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
}
for i := 0; i < subsetValue.Len(); i++ {
element := subsetValue.Index(i).Interface()
ok, found := containsElement(list, element)
@ -1109,6 +1146,27 @@ func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration,
return true
}
// WithinRange asserts that a time is within a time range (inclusive).
//
// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if end.Before(start) {
return Fail(t, "Start should be before end", msgAndArgs...)
}
if actual.Before(start) {
return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...)
} else if actual.After(end) {
return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...)
}
return true
}
func toFloat(x interface{}) (float64, bool) {
var xf float64
xok := true

View File

@ -1864,6 +1864,32 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
t.FailNow()
}
// WithinRange asserts that a time is within a time range (inclusive).
//
// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.WithinRange(t, actual, start, end, msgAndArgs...) {
return
}
t.FailNow()
}
// WithinRangef asserts that a time is within a time range (inclusive).
//
// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.WithinRangef(t, actual, start, end, msg, args...) {
return
}
t.FailNow()
}
// YAMLEq asserts that two YAML strings are equivalent.
func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {

View File

@ -1462,6 +1462,26 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
WithinDurationf(a.t, expected, actual, delta, msg, args...)
}
// WithinRange asserts that a time is within a time range (inclusive).
//
// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
WithinRange(a.t, actual, start, end, msgAndArgs...)
}
// WithinRangef asserts that a time is within a time range (inclusive).
//
// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
WithinRangef(a.t, actual, start, end, msg, args...)
}
// YAMLEq asserts that two YAML strings are equivalent.
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {

View File

@ -100,7 +100,10 @@ func (p *parser) peek() yaml_event_type_t {
if p.event.typ != yaml_NO_EVENT {
return p.event.typ
}
if !yaml_parser_parse(&p.parser, &p.event) {
// It's curious choice from the underlying API to generally return a
// positive result on success, but on this case return true in an error
// scenario. This was the source of bugs in the past (issue #666).
if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
p.fail()
}
return p.event.typ
@ -320,6 +323,8 @@ type decoder struct {
decodeCount int
aliasCount int
aliasDepth int
mergedFields map[interface{}]bool
}
var (
@ -808,6 +813,11 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
}
}
mergedFields := d.mergedFields
d.mergedFields = nil
var mergeNode *Node
mapIsNew := false
if out.IsNil() {
out.Set(reflect.MakeMap(outt))
@ -815,11 +825,18 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
}
for i := 0; i < l; i += 2 {
if isMerge(n.Content[i]) {
d.merge(n.Content[i+1], out)
mergeNode = n.Content[i+1]
continue
}
k := reflect.New(kt).Elem()
if d.unmarshal(n.Content[i], k) {
if mergedFields != nil {
ki := k.Interface()
if mergedFields[ki] {
continue
}
mergedFields[ki] = true
}
kkind := k.Kind()
if kkind == reflect.Interface {
kkind = k.Elem().Kind()
@ -833,6 +850,12 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
}
}
}
d.mergedFields = mergedFields
if mergeNode != nil {
d.merge(n, mergeNode, out)
}
d.stringMapType = stringMapType
d.generalMapType = generalMapType
return true
@ -844,7 +867,8 @@ func isStringMap(n *Node) bool {
}
l := len(n.Content)
for i := 0; i < l; i += 2 {
if n.Content[i].ShortTag() != strTag {
shortTag := n.Content[i].ShortTag()
if shortTag != strTag && shortTag != mergeTag {
return false
}
}
@ -861,7 +885,6 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
var elemType reflect.Type
if sinfo.InlineMap != -1 {
inlineMap = out.Field(sinfo.InlineMap)
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
elemType = inlineMap.Type().Elem()
}
@ -870,6 +893,9 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
d.prepare(n, field)
}
mergedFields := d.mergedFields
d.mergedFields = nil
var mergeNode *Node
var doneFields []bool
if d.uniqueKeys {
doneFields = make([]bool, len(sinfo.FieldsList))
@ -879,13 +905,20 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
for i := 0; i < l; i += 2 {
ni := n.Content[i]
if isMerge(ni) {
d.merge(n.Content[i+1], out)
mergeNode = n.Content[i+1]
continue
}
if !d.unmarshal(ni, name) {
continue
}
if info, ok := sinfo.FieldsMap[name.String()]; ok {
sname := name.String()
if mergedFields != nil {
if mergedFields[sname] {
continue
}
mergedFields[sname] = true
}
if info, ok := sinfo.FieldsMap[sname]; ok {
if d.uniqueKeys {
if doneFields[info.Id] {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
@ -911,6 +944,11 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
}
}
d.mergedFields = mergedFields
if mergeNode != nil {
d.merge(n, mergeNode, out)
}
return true
}
@ -918,19 +956,29 @@ func failWantMap() {
failf("map merge requires map or sequence of maps as the value")
}
func (d *decoder) merge(n *Node, out reflect.Value) {
switch n.Kind {
func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
mergedFields := d.mergedFields
if mergedFields == nil {
d.mergedFields = make(map[interface{}]bool)
for i := 0; i < len(parent.Content); i += 2 {
k := reflect.New(ifaceType).Elem()
if d.unmarshal(parent.Content[i], k) {
d.mergedFields[k.Interface()] = true
}
}
}
switch merge.Kind {
case MappingNode:
d.unmarshal(n, out)
d.unmarshal(merge, out)
case AliasNode:
if n.Alias != nil && n.Alias.Kind != MappingNode {
if merge.Alias != nil && merge.Alias.Kind != MappingNode {
failWantMap()
}
d.unmarshal(n, out)
d.unmarshal(merge, out)
case SequenceNode:
// Step backwards as earlier nodes take precedence.
for i := len(n.Content) - 1; i >= 0; i-- {
ni := n.Content[i]
for i := 0; i < len(merge.Content); i++ {
ni := merge.Content[i]
if ni.Kind == AliasNode {
if ni.Alias != nil && ni.Alias.Kind != MappingNode {
failWantMap()
@ -943,6 +991,8 @@ func (d *decoder) merge(n *Node, out reflect.Value) {
default:
failWantMap()
}
d.mergedFields = mergedFields
}
func isMerge(n *Node) bool {

View File

@ -687,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@ -786,7 +789,7 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
}
token := peek_token(parser)
if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
return
}
@ -813,6 +816,9 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@ -922,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}

View File

@ -49,8 +49,8 @@ github.com/cespare/xxhash/v2
# github.com/crewjam/httperr v0.2.0
## explicit; go 1.13
github.com/crewjam/httperr
# github.com/crewjam/saml v0.4.6
## explicit; go 1.13
# github.com/crewjam/saml v0.4.13
## explicit; go 1.16
github.com/crewjam/saml
github.com/crewjam/saml/logger
github.com/crewjam/saml/samlsp
@ -199,7 +199,7 @@ github.com/goccy/go-json/internal/runtime
# github.com/golang-jwt/jwt v3.2.2+incompatible
## explicit
github.com/golang-jwt/jwt
# github.com/golang-jwt/jwt/v4 v4.4.1
# github.com/golang-jwt/jwt/v4 v4.4.3
## explicit; go 1.16
github.com/golang-jwt/jwt/v4
# github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
@ -407,7 +407,7 @@ github.com/prometheus/common/model
github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs
github.com/prometheus/procfs/internal/util
# github.com/russellhaering/goxmldsig v1.1.1
# github.com/russellhaering/goxmldsig v1.2.0
## explicit; go 1.15
github.com/russellhaering/goxmldsig
github.com/russellhaering/goxmldsig/etreeutils
@ -444,9 +444,7 @@ github.com/steinfletcher/apitest/difflib
github.com/steinfletcher/apitest-jsonpath
github.com/steinfletcher/apitest-jsonpath/http
github.com/steinfletcher/apitest-jsonpath/jsonpath
# github.com/stretchr/objx v0.2.0
## explicit; go 1.12
# github.com/stretchr/testify v1.7.1
# github.com/stretchr/testify v1.8.1
## explicit; go 1.13
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
@ -663,7 +661,7 @@ gopkg.in/mail.v2
gopkg.in/square/go-jose.v2
gopkg.in/square/go-jose.v2/cipher
gopkg.in/square/go-jose.v2/json
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3
# moul.io/zapfilter v1.7.0