Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expose redirect uri to oidc API #2370

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/v1alpha1/oidc_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ type OIDC struct {
// +kubebuilder:validation:Required
ClientSecret gwapiv1b1.SecretObjectReference `json:"clientSecret"`

// The redirect URI to be used in the OIDC
// [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
RedirectURI string `json:"redirectURI"`

// The OIDC scopes to be used in the
// [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
// The "openid" scope is always added to the list of scopes if not already
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,12 @@ spec:
required:
- issuer
type: object
redirectURI:
description: The redirect URI to be used in the OIDC [Authentication
Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
maxLength: 253
minLength: 1
type: string
scopes:
description: The OIDC scopes to be used in the [Authentication
Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
Expand All @@ -346,6 +352,7 @@ spec:
- clientID
- clientSecret
- provider
- redirectURI
type: object
targetRef:
description: TargetRef is the name of the Gateway resource this policy
Expand Down
28 changes: 24 additions & 4 deletions internal/gatewayapi/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,34 @@ func (t *Translator) buildOIDC(
}
scopes := appendOpenidScopeIfNotExist(oidc.Scopes)

redirectPathMatcher := redirectPath(oidc.RedirectURI)
if redirectPathMatcher == "" {
return nil, fmt.Errorf("invalid redirect URI: %s", oidc.RedirectURI)
}

return &ir.OIDC{
Provider: *provider,
ClientID: oidc.ClientID,
ClientSecret: clientSecretBytes,
Scopes: scopes,
Provider: *provider,
ClientID: oidc.ClientID,
ClientSecret: clientSecretBytes,
RedirectURI: oidc.RedirectURI,
RedirectPathMatcher: redirectPathMatcher,
Scopes: scopes,
}, nil
}

func redirectPath(redirectURI string) string {
count := 0
for i, char := range redirectURI {
if char == '/' {
count++
if count == 3 {
return redirectURI[i:]
}
}
}
return ""
}

// appendOpenidScopeIfNotExist appends the openid scope to the provided scopes
// if it is not already present.
// `openid` is a required scope for OIDC.
Expand Down
37 changes: 37 additions & 0 deletions internal/gatewayapi/securitypolicy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package gatewayapi

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_redirectPathMatcher(t *testing.T) {

tests := []struct {
name string
redirectURI string
want string
}{
{
name: "redirectURI with path",
redirectURI: "https://example.com/test/oauth2/callback",
want: "/test/oauth2/callback",
},
{
name: "redirectURI with header tokens",
redirectURI: "%REQ(x-forwarded-proto)%://%REQ(:authority)%/test/oauth2/callback",
want: "/test/oauth2/callback",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, redirectPath(tt.redirectURI), "redirectPathMatcher(%v)", tt.redirectURI)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ securityPolicies:
clientID: "client1.apps.googleusercontent.com"
clientSecret:
name: "client1-secret"
redirectURI: "https://www.example.com/oauth2/callback"
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
Expand Down Expand Up @@ -109,3 +110,4 @@ securityPolicies:
clientID: "client1.apps.googleusercontent.com"
clientSecret:
name: "client2-secret"
redirectURI: "https://www.example.com/oauth2/callback"
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ securityPolicies:
name: client2-secret
provider:
issuer: https://accounts.google.com
redirectURI: https://www.example.com/oauth2/callback
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
Expand Down Expand Up @@ -197,6 +198,7 @@ securityPolicies:
name: client1-secret
provider:
issuer: https://accounts.google.com
redirectURI: https://www.example.com/oauth2/callback
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ securityPolicies:
clientID: "client1.apps.foo.bar.com"
clientSecret:
name: "client1-secret"
redirectURI: "https://www.example.com/oauth2/callback"
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ securityPolicies:
name: client1-secret
provider:
issuer: https://httpbin.org/
redirectURI: https://www.example.com/oauth2/callback
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ securityPolicies:
clientID: "client1.apps.googleusercontent.com"
clientSecret:
name: "client1-secret"
redirectURI: "https://www.example.com/oauth2/callback"
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
Expand All @@ -95,6 +96,7 @@ securityPolicies:
clientSecret:
namespace: envoy-gateway
name: "client2-secret"
redirectURI: "https://www.example.com/oauth2/callback"
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ securityPolicies:
authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth
issuer: https://accounts.google.com
tokenEndpoint: https://oauth2.googleapis.com/token
redirectURI: https://www.example.com/oauth2/callback
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
Expand Down Expand Up @@ -212,6 +213,7 @@ securityPolicies:
authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth
issuer: https://accounts.google.com
tokenEndpoint: https://oauth2.googleapis.com/token
redirectURI: https://www.example.com/oauth2/callback
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
Expand Down Expand Up @@ -241,6 +243,7 @@ securityPolicies:
authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth
issuer: https://accounts.google.com
tokenEndpoint: https://oauth2.googleapis.com/token
redirectURI: ""
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ securityPolicies:
clientID: "client1.apps.googleusercontent.com"
clientSecret:
name: "client1-secret"
redirectURI: "https://www.example.com/bar/oauth2/callback"
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
Expand All @@ -126,6 +127,7 @@ securityPolicies:
clientID: "client2.oauth.foo.com"
clientSecret:
name: "client2-secret"
redirectURI: "https://www.example.com/foo/oauth2/callback"
scopes: ["openid", "email", "profile"]
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
Expand Down
21 changes: 15 additions & 6 deletions internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ securityPolicies:
authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth
issuer: https://oauth.foo.com
tokenEndpoint: https://oauth.foo.com/token
redirectURI: https://www.example.com/foo/oauth2/callback
scopes:
- openid
- email
Expand Down Expand Up @@ -218,16 +219,17 @@ securityPolicies:
authorizationEndpoint: https://oauth.bar.com/oauth2/v2/auth
issuer: https://oauth.bar.com
tokenEndpoint: https://oauth.bar.com/token
redirectURI: ""
targetRef:
group: gateway.networking.k8s.io
kind: GRPCRoute
name: grpcroute-1
status:
conditions:
- lastTransitionTime: null
message: SecurityPolicy has been accepted.
reason: Accepted
status: "True"
message: 'Invalid redirect URI: '
reason: Invalid
status: "False"
type: Accepted
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
Expand All @@ -244,6 +246,7 @@ securityPolicies:
name: client1-secret
provider:
issuer: https://accounts.google.com
redirectURI: https://www.example.com/bar/oauth2/callback
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
Expand Down Expand Up @@ -289,6 +292,8 @@ xdsIR:
provider:
authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth
tokenEndpoint: https://oauth.foo.com/token
redirectPathMatcher: /foo/oauth2/callback
redirectURI: https://www.example.com/foo/oauth2/callback
scopes:
- openid
- email
Expand Down Expand Up @@ -317,6 +322,8 @@ xdsIR:
provider:
authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth
tokenEndpoint: https://oauth2.googleapis.com/token
redirectPathMatcher: /bar/oauth2/callback
redirectURI: https://www.example.com/bar/oauth2/callback
scopes:
- openid
pathMatch:
Expand All @@ -338,10 +345,12 @@ xdsIR:
hostname: '*'
name: grpcroute/default/grpcroute-1/rule/0/match/-1/*
oidc:
clientID: client3.bar.foo.com
clientID: client1.apps.googleusercontent.com
clientSecret: Y2xpZW50MTpzZWNyZXQK
provider:
authorizationEndpoint: https://oauth.bar.com/oauth2/v2/auth
tokenEndpoint: https://oauth.bar.com/token
authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth
tokenEndpoint: https://oauth2.googleapis.com/token
redirectPathMatcher: /bar/oauth2/callback
redirectURI: https://www.example.com/bar/oauth2/callback
scopes:
- openid
8 changes: 7 additions & 1 deletion internal/ir/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,14 @@ type OIDC struct {
// [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
//
// This is an Opaque secret. The client secret should be stored in the key "client-secret".
ClientSecret []byte `json:"clientSecret" yaml:"clientSecret"`

ClientSecret []byte `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"`
// The redirect URI to be used in the
// [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
RedirectURI string `json:"redirectURI" yaml:"redirectURI"`

// Matching rule for the redirect path.
RedirectPathMatcher string `json:"redirectPathMatcher" yaml:"redirectPathMatcher"`

// The OIDC scopes to be used in the
// [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
Expand Down
6 changes: 2 additions & 4 deletions internal/xds/translator/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ import (
const (
oauth2Filter = "envoy.filters.http.oauth2"
defaultTokenEndpointTimeout = 10
redirectURL = "%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback"
redirectPathMatcher = "/oauth2/callback"
defaultSignoutPath = "/signout"
)

Expand Down Expand Up @@ -131,12 +129,12 @@ func oauth2Config(route *ir.HTTPRoute) (*oauth2v3.OAuth2, error) {
},
},
AuthorizationEndpoint: route.OIDC.Provider.AuthorizationEndpoint,
RedirectUri: redirectURL,
RedirectUri: route.OIDC.RedirectURI,
RedirectPathMatcher: &matcherv3.PathMatcher{
Rule: &matcherv3.PathMatcher_Path{
Path: &matcherv3.StringMatcher{
MatchPattern: &matcherv3.StringMatcher_Exact{
Exact: redirectPathMatcher,
Exact: route.OIDC.RedirectPathMatcher,
},
},
},
Expand Down
6 changes: 6 additions & 0 deletions internal/xds/translator/testdata/in/xds-ir/oidc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ http:
oidc:
clientID: client.oauth.foo.com
clientSecret: Y2xpZW50MTpzZWNyZXQK
redirectURI: "https://www.example.com/foo/oauth2/callback"
redirectPathMatcher: "/foo/oauth2/callback"
provider:
authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth
tokenEndpoint: https://oauth.foo.com/token
Expand All @@ -38,6 +40,8 @@ http:
oidc:
clientID: client.oauth.bar.com
clientSecret: Y2xpZW50MTpzZWNyZXQK
redirectURI: "https://www.example.com/bar/oauth2/callback"
redirectPathMatcher: "/bar/oauth2/callback"
provider:
authorizationEndpoint: https://oauth.bar.com/oauth2/v2/auth
tokenEndpoint: https://oauth.bar.com/token
Expand All @@ -58,6 +62,8 @@ http:
oidc:
clientID: test.oauth.bar.com
clientSecret: Y2xpZW50MTpzZWNyZXQK
redirectURI: "https://www.example.com/test/oauth2/callback"
redirectPathMatcher: "/test/oauth2/callback"
provider:
authorizationEndpoint: https://oauth.bar.com/oauth2/v2/auth
tokenEndpoint: https://oauth.bar.com/token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
forwardBearerToken: true
redirectPathMatcher:
path:
exact: /oauth2/callback
redirectUri: '%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback'
exact: /foo/oauth2/callback
redirectUri: https://www.example.com/foo/oauth2/callback
signoutPath:
path:
exact: /signout
Expand Down Expand Up @@ -73,8 +73,8 @@
forwardBearerToken: true
redirectPathMatcher:
path:
exact: /oauth2/callback
redirectUri: '%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback'
exact: /bar/oauth2/callback
redirectUri: https://www.example.com/bar/oauth2/callback
signoutPath:
path:
exact: /signout
Expand Down Expand Up @@ -107,8 +107,8 @@
forwardBearerToken: true
redirectPathMatcher:
path:
exact: /oauth2/callback
redirectUri: '%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback'
exact: /test/oauth2/callback
redirectUri: https://www.example.com/test/oauth2/callback
signoutPath:
path:
exact: /signout
Expand Down
1 change: 1 addition & 0 deletions site/content/en/latest/api/extension_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,7 @@ _Appears in:_
| `clientID` _string_ | The client ID to be used in the OIDC [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). |
| `clientSecret` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | The Kubernetes secret which contains the OIDC client secret to be used in the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
This is an Opaque secret. The client secret should be stored in the key "client-secret". |
| `redirectURI` _string_ | The redirect URI to be used in the OIDC [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). |
| `scopes` _string array_ | The OIDC scopes to be used in the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). The "openid" scope is always added to the list of scopes if not already specified. |


Expand Down
Loading