git.iko.soy/typeable/oauth2-proxy
on master help sign in
Ensure required PKCE information is exposed from provider
commitc3158ebc485f7ed8169e1c006c7e5a86cfb3abe5 authorJoel Speed <joel.speed@hotmail.co.uk> dateFri 18 Feb 2022, 15:04 (5 years ago) parent474a3b0
2 files changed+69−13
pkg/providers/oidc/provider.go+30−13 pkg/providers/oidc/provider_test.go+39
pkg/providers/oidc/provider.go+30−13
@@ -11,11 +11,12 @@ import (
1111
1212// providerJSON resresents the information we need from an OIDC discovery
1313type providerJSON struct {
14− Issuer string `json:"issuer"`
15− AuthURL string `json:"authorization_endpoint"`
16− TokenURL string `json:"token_endpoint"`
17− JWKsURL string `json:"jwks_uri"`
18− UserInfoURL string `json:"userinfo_endpoint"`
14+ Issuer string `json:"issuer"`
15+ AuthURL string `json:"authorization_endpoint"`
16+ TokenURL string `json:"token_endpoint"`
17+ JWKsURL string `json:"jwks_uri"`
18+ UserInfoURL string `json:"userinfo_endpoint"`
19+ CodeChallengeAlgs []string `json:"code_challenge_methods_supported"`
1920}
2021
2122// Endpoints represents the endpoints discovered as part of the OIDC discovery process
@@ -27,10 +28,17 @@ type Endpoints struct {
2728 UserInfoURL string
2829}
2930
31+// PKCE holds information relevant to the PKCE (code challenge) support of the
32+// provider.
33+type PKCE struct {
34+ CodeChallengeAlgs []string
35+}
36+
3037// DiscoveryProvider holds information about an identity provider having
3138// used OIDC discovery to retrieve the information.
3239type DiscoveryProvider interface {
3340 Endpoints() Endpoints
41+ PKCE() PKCE
3442}
3543
3644// NewProvider allows a user to perform an OIDC discovery and returns the DiscoveryProvider.
@@ -55,19 +63,21 @@ func NewProvider(ctx context.Context, issuerURL string, skipIssuerVerification b
5563 }
5664
5765 return &discoveryProvider{
58− authURL: p.AuthURL,
59− tokenURL: p.TokenURL,
60− jwksURL: p.JWKsURL,
61− userInfoURL: p.UserInfoURL,
66+ authURL: p.AuthURL,
67+ tokenURL: p.TokenURL,
68+ jwksURL: p.JWKsURL,
69+ userInfoURL: p.UserInfoURL,
70+ codeChallengeAlgs: p.CodeChallengeAlgs,
6271 }, nil
6372}
6473
6574// discoveryProvider holds the discovered endpoints
6675type discoveryProvider struct {
67− authURL string
68− tokenURL string
69− jwksURL string
70− userInfoURL string
76+ authURL string
77+ tokenURL string
78+ jwksURL string
79+ userInfoURL string
80+ codeChallengeAlgs []string
7181}
7282
7383// Endpoints returns the discovered endpoints needed for an authentication provider.
@@ -79,3 +89,10 @@ func (p *discoveryProvider) Endpoints() Endpoints {
7989 UserInfoURL: p.userInfoURL,
8090 }
8191}
92+
93+// PKCE returns information related to the PKCE (code challenge) support of the provider.
94+func (p *discoveryProvider) PKCE() PKCE {
95+ return PKCE{
96+ CodeChallengeAlgs: p.codeChallengeAlgs,
97+ }
98+}
pkg/providers/oidc/provider_test.go+39
@@ -84,6 +84,25 @@ var _ = Describe("Provider", func() {
8484 expectedError: "failed to discover OIDC configuration: unexpected status \"400\"",
8585 }),
8686 )
87+
88+ It("with code challenges supported on the provider, shold populate PKCE information", func() {
89+ m, err := mockoidc.NewServer(nil)
90+ Expect(err).ToNot(HaveOccurred())
91+ m.AddMiddleware(newCodeChallengeIssuerMiddleware(m))
92+
93+ ln, err := net.Listen("tcp", "127.0.0.1:0")
94+ Expect(err).ToNot(HaveOccurred())
95+
96+ Expect(m.Start(ln, nil)).To(Succeed())
97+ defer func() {
98+ Expect(m.Shutdown()).To(Succeed())
99+ }()
100+
101+ provider, err := NewProvider(context.Background(), m.Issuer(), false)
102+ Expect(err).ToNot(HaveOccurred())
103+
104+ Expect(provider.PKCE().CodeChallengeAlgs).To(ConsistOf("S256", "plain"))
105+ })
87106})
88107
89108func newInvalidIssuerMiddleware(m *mockoidc.MockOIDC) func(http.Handler) http.Handler {
@@ -105,6 +124,26 @@ func newInvalidIssuerMiddleware(m *mockoidc.MockOIDC) func(http.Handler) http.Ha
105124 }
106125}
107126
127+func newCodeChallengeIssuerMiddleware(m *mockoidc.MockOIDC) func(http.Handler) http.Handler {
128+ return func(next http.Handler) http.Handler {
129+ return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
130+ p := providerJSON{
131+ Issuer: m.Issuer(),
132+ AuthURL: m.AuthorizationEndpoint(),
133+ TokenURL: m.TokenEndpoint(),
134+ JWKsURL: m.JWKSEndpoint(),
135+ UserInfoURL: m.UserinfoEndpoint(),
136+ CodeChallengeAlgs: []string{"S256", "plain"},
137+ }
138+ data, err := json.Marshal(p)
139+ if err != nil {
140+ rw.WriteHeader(500)
141+ }
142+ rw.Write(data)
143+ })
144+ }
145+}
146+
108147func newBadRequestMiddleware() func(http.Handler) http.Handler {
109148 return func(next http.Handler) http.Handler {
110149 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {