mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-06 16:36:51 +00:00
refactor: clean up id_token validation
This commit is contained in:
@@ -4,14 +4,16 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/token"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/nais/liberator/pkg/conftools"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
@@ -88,6 +90,11 @@ func run() error {
|
||||
Scopes: scopes,
|
||||
}
|
||||
|
||||
jwkSet, err := jwk.Fetch(context.Background(), cfg.IDPorten.WellKnown.JwksURI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching jwks: %w", err)
|
||||
}
|
||||
|
||||
handler := &router.Handler{
|
||||
Config: cfg.IDPorten,
|
||||
Crypter: crypt,
|
||||
@@ -95,11 +102,7 @@ func run() error {
|
||||
UpstreamHost: cfg.UpstreamHost,
|
||||
SecureCookies: true,
|
||||
Sessions: sessionStore,
|
||||
IdTokenVerifier: oidc.NewVerifier(
|
||||
cfg.IDPorten.WellKnown.Issuer,
|
||||
oidc.NewRemoteKeySet(context.Background(), cfg.IDPorten.WellKnown.JwksURI),
|
||||
&oidc.Config{ClientID: cfg.IDPorten.ClientID},
|
||||
),
|
||||
JwkSet: jwkSet,
|
||||
}
|
||||
|
||||
r := router.New(handler)
|
||||
|
||||
4
go.mod
4
go.mod
@@ -3,8 +3,6 @@ module github.com/nais/wonderwall
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible
|
||||
github.com/go-chi/chi v1.5.4
|
||||
github.com/go-redis/redis/v8 v8.11.3
|
||||
github.com/google/uuid v1.1.2
|
||||
@@ -15,9 +13,7 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
go.opentelemetry.io/otel v0.6.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
)
|
||||
|
||||
20
go.sum
20
go.sum
@@ -47,9 +47,7 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@@ -66,15 +64,12 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@@ -87,7 +82,6 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -245,8 +239,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
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/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -391,6 +385,7 @@ github.com/nais/liberator v0.0.0-20210809103005-edb0141d646d/go.mod h1:Dw7TPRYZk
|
||||
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@@ -398,14 +393,15 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU=
|
||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
@@ -421,7 +417,6 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77
|
||||
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
@@ -448,7 +443,6 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||
@@ -509,7 +503,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/otel v0.6.0/go.mod h1:jzBIgIzK43Iu1BpDAXwqOd6UPsSAk+ewVZ5ofSXw4Ek=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
@@ -614,7 +607,6 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
@@ -826,7 +818,6 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
@@ -897,7 +888,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
@@ -911,13 +901,13 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func ValidateIdToken(ctx context.Context, verifier *oidc.IDTokenVerifier, token *oauth2.Token, nonce string) (*oidc.IDToken, error) {
|
||||
raw, ok := token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing id_token in token response")
|
||||
}
|
||||
|
||||
idToken, err := verifier.Verify(ctx, raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if idToken.Nonce != nonce {
|
||||
return nil, fmt.Errorf("nonce does not match")
|
||||
}
|
||||
|
||||
return idToken, nil
|
||||
}
|
||||
30
pkg/keyset/keyset.go
Normal file
30
pkg/keyset/keyset.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package keyset
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/lestrrat-go/jwx/jwa"
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
)
|
||||
|
||||
// EnsureValid sets fields for the keys in the given keyset if missing.
|
||||
// We only accept keys with the "alg" value set to RS256.
|
||||
func EnsureValid(ctx context.Context, jwks jwk.Set) error {
|
||||
for iter := jwks.Iterate(ctx); iter.Next(ctx); {
|
||||
pair := iter.Pair()
|
||||
key := pair.Value.(jwk.Key)
|
||||
|
||||
if len(key.Algorithm()) == 0 {
|
||||
err := key.Set(jwk.AlgorithmKey, jwa.RS256)
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting key algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
if key.Algorithm() != string(jwa.RS256) {
|
||||
jwks.Remove(key)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -41,6 +41,16 @@ func NewIDPorten(clients map[string]string) *IDPorten {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = jwk.AssignKeyID(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = key.Set(jwk.AlgorithmKey, jwa.RS256)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
keys := jwk.NewSet()
|
||||
keys.Add(key)
|
||||
|
||||
|
||||
@@ -6,27 +6,24 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/nais/wonderwall/pkg/token"
|
||||
|
||||
"github.com/go-chi/chi/middleware"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/auth"
|
||||
"github.com/nais/wonderwall/pkg/cryptutil"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"golang.org/x/oauth2"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/config"
|
||||
"github.com/nais/wonderwall/pkg/cryptutil"
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
"github.com/nais/wonderwall/pkg/token"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -39,14 +36,14 @@ const (
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
Config config.IDPorten
|
||||
OauthConfig oauth2.Config
|
||||
Crypter cryptutil.Crypter
|
||||
UpstreamHost string
|
||||
IdTokenVerifier *oidc.IDTokenVerifier
|
||||
SecureCookies bool
|
||||
Sessions session.Store
|
||||
lock sync.Mutex
|
||||
Config config.IDPorten
|
||||
OauthConfig oauth2.Config
|
||||
Crypter cryptutil.Crypter
|
||||
UpstreamHost string
|
||||
JwkSet jwk.Set
|
||||
SecureCookies bool
|
||||
Sessions session.Store
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
type loginParams struct {
|
||||
@@ -112,6 +109,7 @@ func (h *Handler) LoginURL() (*loginParams, error) {
|
||||
func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
||||
params, err := h.LoginURL()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -122,6 +120,7 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
||||
NewCookie(CodeVerifierCookieName, params.codeVerifier, LoginCookieLifetime),
|
||||
)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -170,32 +169,35 @@ func (h *Handler) Callback(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
idToken, err := auth.ValidateIdToken(r.Context(), h.IdTokenVerifier, tokens, cookies.Nonce)
|
||||
idToken, err := token.ParseIDToken(r.Context(), h.JwkSet, tokens)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
var claims struct {
|
||||
SessionID string `json:"sid"`
|
||||
validateOpts := []jwt.ValidateOption{
|
||||
jwt.WithAudience(h.Config.ClientID),
|
||||
jwt.WithClaimValue("nonce", cookies.Nonce),
|
||||
jwt.WithIssuer(h.Config.WellKnown.Issuer),
|
||||
}
|
||||
|
||||
if err := idToken.Claims(&claims); err != nil {
|
||||
err = idToken.Validate(validateOpts...)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.setEncryptedCookie(w, SessionCookieName, claims.SessionID, SessionMaxLifetime)
|
||||
err = h.setEncryptedCookie(w, SessionCookieName, idToken.SessionID, SessionMaxLifetime)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.Sessions.Write(r.Context(), claims.SessionID, &session.Data{
|
||||
ID: claims.SessionID,
|
||||
err = h.Sessions.Write(r.Context(), idToken.SessionID, &session.Data{
|
||||
ID: idToken.SessionID,
|
||||
Token: tokens,
|
||||
}, SessionMaxLifetime)
|
||||
if err != nil {
|
||||
@@ -287,7 +289,7 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, u.String(), http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
||||
// Logout triggers self-initiated for the current user
|
||||
// FrontChannelLogout triggers logout triggered by a third-party.
|
||||
func (h *Handler) FrontChannelLogout(w http.ResponseWriter, r *http.Request) {
|
||||
params := r.URL.Query()
|
||||
|
||||
@@ -307,25 +309,15 @@ func (h *Handler) FrontChannelLogout(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// From here on, check that 'iss' from request matches data found in access token.
|
||||
tok, err := jwt.ParseSigned(sess.Token.AccessToken)
|
||||
tok, err := jwt.Parse([]byte(sess.Token.AccessToken))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var claims struct {
|
||||
Issuer string `json:"iss"`
|
||||
}
|
||||
|
||||
err = tok.UnsafeClaimsWithoutVerification(&claims)
|
||||
err = jwt.Validate(tok, jwt.WithClaimValue("iss", iss))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if claims.Issuer != iss {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/http/httptest"
|
||||
@@ -12,9 +11,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/cryptutil"
|
||||
|
||||
@@ -77,7 +78,6 @@ func handler() *router.Handler {
|
||||
},
|
||||
Crypter: cryptutil.New(encryptionKey),
|
||||
UpstreamHost: "",
|
||||
IdTokenVerifier: nil,
|
||||
}
|
||||
return &handler
|
||||
}
|
||||
@@ -147,11 +147,9 @@ func TestHandler_Callback_and_Logout(t *testing.T) {
|
||||
h.Config.WellKnown.EndSessionEndpoint = idpserver.URL + "/endsession"
|
||||
h.Config.RedirectURI = server.URL + "/oauth2/callback"
|
||||
h.Config.PostLogoutRedirectURI = server.URL
|
||||
h.IdTokenVerifier = oidc.NewVerifier(
|
||||
cfg.WellKnown.Issuer,
|
||||
oidc.NewRemoteKeySet(context.Background(), idpserver.URL+"/jwks"),
|
||||
&oidc.Config{ClientID: cfg.ClientID},
|
||||
)
|
||||
jwkSet, err := jwk.Fetch(context.Background(), idpserver.URL+"/jwks")
|
||||
assert.NoError(t, err)
|
||||
h.JwkSet = jwkSet
|
||||
|
||||
jar, err := cookiejar.New(nil)
|
||||
assert.NoError(t, err)
|
||||
@@ -241,11 +239,10 @@ func TestHandler_FrontChannelLogout(t *testing.T) {
|
||||
h.Config.WellKnown.EndSessionEndpoint = idpserver.URL + "/endsession"
|
||||
h.Config.RedirectURI = server.URL + "/oauth2/callback"
|
||||
h.Config.PostLogoutRedirectURI = server.URL
|
||||
h.IdTokenVerifier = oidc.NewVerifier(
|
||||
cfg.WellKnown.Issuer,
|
||||
oidc.NewRemoteKeySet(context.Background(), idpserver.URL+"/jwks"),
|
||||
&oidc.Config{ClientID: cfg.ClientID},
|
||||
)
|
||||
|
||||
jwkSet, err := jwk.Fetch(context.Background(), idpserver.URL+"/jwks")
|
||||
assert.NoError(t, err)
|
||||
h.JwkSet = jwkSet
|
||||
|
||||
jar, err := cookiejar.New(nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
package token
|
||||
|
||||
const ScopeOpenID = "openid"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/keyset"
|
||||
)
|
||||
|
||||
const ScopeOpenID = "openid"
|
||||
|
||||
type JWTTokenRequest struct {
|
||||
Issuer string `json:"iss"`
|
||||
@@ -10,3 +21,47 @@ type JWTTokenRequest struct {
|
||||
IssuedAt int64 `json:"iat"`
|
||||
ExpiresAt int64 `json:"exp"`
|
||||
}
|
||||
|
||||
type IDToken struct {
|
||||
Raw string
|
||||
SessionID string
|
||||
Token jwt.Token
|
||||
}
|
||||
|
||||
func (in *IDToken) Validate(opts ...jwt.ValidateOption) error {
|
||||
return jwt.Validate(in.Token, opts...)
|
||||
}
|
||||
|
||||
func ParseIDToken(ctx context.Context, jwks jwk.Set, token *oauth2.Token) (*IDToken, error) {
|
||||
raw, ok := token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing id_token in token response")
|
||||
}
|
||||
|
||||
err := keyset.EnsureValid(ctx, jwks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parseOpts := []jwt.ParseOption{
|
||||
jwt.WithKeySet(jwks),
|
||||
jwt.WithRequiredClaim("sid"),
|
||||
}
|
||||
idToken, err := jwt.Parse([]byte(raw), parseOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing jwt: %w", err)
|
||||
}
|
||||
|
||||
sessionID, ok := idToken.Get("sid")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing 'sid' claim in id_token")
|
||||
}
|
||||
|
||||
result := &IDToken{
|
||||
Raw: raw,
|
||||
SessionID: sessionID.(string),
|
||||
Token: idToken,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user