Skip to content

Commit a9ac466

Browse files
committed
feat: add intercept error enable and fix checking OIDC config data
fix: compare OIDC option to enable access token and intercepting error fix: revert
1 parent 5c9f9ed commit a9ac466

File tree

11 files changed

+253
-213
lines changed

11 files changed

+253
-213
lines changed

deployments/common/crds/k8s.nginx.org_policies.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ spec:
136136
type: integer
137137
accessTokenEnable:
138138
type: boolean
139+
interceptErrorEnable:
140+
type: boolean
139141
rateLimit:
140142
description: RateLimit defines a rate limit policy.
141143
type: object

deployments/helm-chart/crds/k8s.nginx.org_policies.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ spec:
136136
type: integer
137137
accessTokenEnable:
138138
type: boolean
139+
interceptErrorEnable:
140+
type: boolean
139141
rateLimit:
140142
description: RateLimit defines a rate limit policy.
141143
type: object

docs/content/configuration/policy-resource.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ spec:
357357
tokenEndpoint: https://idp.example.com/openid-connect/token
358358
jwksURI: https://idp.example.com/openid-connect/certs
359359
accessTokenEnable: true
360+
interceptErrorEnable: false
360361
```
361362

362363
NGINX Plus will pass the ID of an authenticated user to the backend in the HTTP header `username`.
@@ -388,6 +389,8 @@ The OIDC policy defines a few internal locations that can't be customized: `/_jw
388389
|``zoneSyncLeeway`` | Specifies the maximum timeout in milliseconds for synchronizing ID/access tokens and shared values between Ingress Controller pods. The default is ``200``. | ``int`` | No |
389390
|``accessTokenEnable`` | Option of whether Bearer token is used to authorize NGINX to access protected backend. | ``boolean`` | No |
390391
{{% /table %}}
392+
|``interceptErrorEnable`` | Option to intercept and redirect "401 Unauthorized" proxied responses to nginx for processing with the `error_page` directive to restart `@do_oidc_flow` if an access token can expire before ID token. | ``boolean`` | No |
393+
{{% /table %}}
391394

392395
> **Note**: Only one OIDC policy can be referenced in a VirtualServer and its VirtualServerRoutes. However, the same policy can still be applied to different routes in the VirtualServer and VirtualServerRoutes.
393396

examples/custom-resources/oidc/oidc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ spec:
1111
jwksURI: http://keycloak.default.svc.cluster.local:8080/auth/realms/master/protocol/openid-connect/certs
1212
scope: openid+profile+email
1313
accessTokenEnable: true
14+
interceptErrorEnable: false

internal/configs/oidc/openid_connect.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function auth(r, afterSyncCheck) {
101101
return;
102102
}
103103

104-
// Update ID token and access token in the key-value store
104+
// ID Token is valid, update keyval
105105
r.log("OIDC refresh success, updating id_token for " + r.variables.cookie_auth_token);
106106
r.variables.session_jwt = tokenset.id_token;
107107
if (tokenset.access_token) {

internal/configs/version2/http.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,17 @@ type EgressMTLS struct {
111111

112112
// OIDC holds OIDC configuration data.
113113
type OIDC struct {
114-
AuthEndpoint string
115-
ClientID string
116-
ClientSecret string
117-
JwksURI string
118-
Scope string
119-
TokenEndpoint string
120-
RedirectURI string
121-
ZoneSyncLeeway int
122-
AuthExtraArgs string
123-
AccessTokenEnable bool
114+
AuthEndpoint string
115+
ClientID string
116+
ClientSecret string
117+
JwksURI string
118+
Scope string
119+
TokenEndpoint string
120+
RedirectURI string
121+
ZoneSyncLeeway int
122+
AuthExtraArgs string
123+
AccessTokenEnable bool
124+
InterceptErrorEnable bool
124125
}
125126

126127
// WAF defines WAF configuration.

internal/configs/version2/nginx-plus.virtualserver.tmpl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,13 @@ server {
429429
{{ $proxyOrGRPC }}_set_header username $jwt_claim_sub;
430430
{{ end }}
431431

432-
{{ if $s.OIDC.AccessTokenEnable }}
432+
{{ with $oidc := $s.OIDC }}
433+
{{ if $oidc.AccessTokenEnable }}
433434
{{ $proxyOrGRPC }}_set_header Authorization "Bearer $access_token";
435+
{{ end }}
436+
{{ if $oidc.InterceptErrorEnable }}
434437
{{ $proxyOrGRPC }}_intercept_errors on;
438+
{{ end }}
435439
{{ end }}
436440

437441
{{ with $l.WAF }}

internal/configs/virtualserver.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,16 +1052,17 @@ func (p *policiesCfg) addOIDCConfig(
10521052
}
10531053

10541054
oidcPolCfg.oidc = &version2.OIDC{
1055-
AuthEndpoint: oidc.AuthEndpoint,
1056-
AuthExtraArgs: authExtraArgs,
1057-
TokenEndpoint: oidc.TokenEndpoint,
1058-
JwksURI: oidc.JWKSURI,
1059-
ClientID: oidc.ClientID,
1060-
ClientSecret: string(clientSecret),
1061-
Scope: scope,
1062-
RedirectURI: redirectURI,
1063-
ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200),
1064-
AccessTokenEnable: oidc.AccessTokenEnable,
1055+
AuthEndpoint: oidc.AuthEndpoint,
1056+
AuthExtraArgs: authExtraArgs,
1057+
TokenEndpoint: oidc.TokenEndpoint,
1058+
JwksURI: oidc.JWKSURI,
1059+
ClientID: oidc.ClientID,
1060+
ClientSecret: string(clientSecret),
1061+
Scope: scope,
1062+
RedirectURI: redirectURI,
1063+
ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200),
1064+
AccessTokenEnable: oidc.AccessTokenEnable,
1065+
InterceptErrorEnable: oidc.InterceptErrorEnable,
10651066
}
10661067
oidcPolCfg.key = polKey
10671068
}

internal/configs/virtualserver_test.go

Lines changed: 73 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3136,15 +3136,16 @@ func TestGeneratePolicies(t *testing.T) {
31363136
},
31373137
Spec: conf_v1.PolicySpec{
31383138
OIDC: &conf_v1.OIDC{
3139-
AuthEndpoint: "http://example.com/auth",
3140-
TokenEndpoint: "http://example.com/token",
3141-
JWKSURI: "http://example.com/jwks",
3142-
ClientID: "client-id",
3143-
ClientSecret: "oidc-secret",
3144-
Scope: "scope",
3145-
RedirectURI: "/redirect",
3146-
ZoneSyncLeeway: createPointerFromInt(20),
3147-
AccessTokenEnable: true,
3139+
AuthEndpoint: "http://example.com/auth",
3140+
TokenEndpoint: "http://example.com/token",
3141+
JWKSURI: "http://example.com/jwks",
3142+
ClientID: "client-id",
3143+
ClientSecret: "oidc-secret",
3144+
Scope: "scope",
3145+
RedirectURI: "/redirect",
3146+
ZoneSyncLeeway: createPointerFromInt(20),
3147+
AccessTokenEnable: true,
3148+
InterceptErrorEnable: false,
31483149
},
31493150
},
31503151
},
@@ -4253,11 +4254,12 @@ func TestGeneratePoliciesFails(t *testing.T) {
42534254
},
42544255
Spec: conf_v1.PolicySpec{
42554256
OIDC: &conf_v1.OIDC{
4256-
ClientSecret: "oidc-secret",
4257-
AuthEndpoint: "http://foo.com/bar",
4258-
TokenEndpoint: "http://foo.com/bar",
4259-
JWKSURI: "http://foo.com/bar",
4260-
AccessTokenEnable: true,
4257+
ClientSecret: "oidc-secret",
4258+
AuthEndpoint: "http://foo.com/bar",
4259+
TokenEndpoint: "http://foo.com/bar",
4260+
JWKSURI: "http://foo.com/bar",
4261+
AccessTokenEnable: true,
4262+
InterceptErrorEnable: false,
42614263
},
42624264
},
42634265
},
@@ -4300,12 +4302,13 @@ func TestGeneratePoliciesFails(t *testing.T) {
43004302
},
43014303
Spec: conf_v1.PolicySpec{
43024304
OIDC: &conf_v1.OIDC{
4303-
ClientID: "foo",
4304-
ClientSecret: "oidc-secret",
4305-
AuthEndpoint: "https://foo.com/auth",
4306-
TokenEndpoint: "https://foo.com/token",
4307-
JWKSURI: "https://foo.com/certs",
4308-
AccessTokenEnable: true,
4305+
ClientID: "foo",
4306+
ClientSecret: "oidc-secret",
4307+
AuthEndpoint: "https://foo.com/auth",
4308+
TokenEndpoint: "https://foo.com/token",
4309+
JWKSURI: "https://foo.com/certs",
4310+
AccessTokenEnable: true,
4311+
InterceptErrorEnable: false,
43094312
},
43104313
},
43114314
},
@@ -4316,12 +4319,13 @@ func TestGeneratePoliciesFails(t *testing.T) {
43164319
},
43174320
Spec: conf_v1.PolicySpec{
43184321
OIDC: &conf_v1.OIDC{
4319-
ClientID: "foo",
4320-
ClientSecret: "oidc-secret",
4321-
AuthEndpoint: "https://bar.com/auth",
4322-
TokenEndpoint: "https://bar.com/token",
4323-
JWKSURI: "https://bar.com/certs",
4324-
AccessTokenEnable: true,
4322+
ClientID: "foo",
4323+
ClientSecret: "oidc-secret",
4324+
AuthEndpoint: "https://bar.com/auth",
4325+
TokenEndpoint: "https://bar.com/token",
4326+
JWKSURI: "https://bar.com/certs",
4327+
AccessTokenEnable: true,
4328+
InterceptErrorEnable: false,
43254329
},
43264330
},
43274331
},
@@ -4341,15 +4345,16 @@ func TestGeneratePoliciesFails(t *testing.T) {
43414345
context: "route",
43424346
oidcPolCfg: &oidcPolicyCfg{
43434347
oidc: &version2.OIDC{
4344-
AuthEndpoint: "https://foo.com/auth",
4345-
TokenEndpoint: "https://foo.com/token",
4346-
JwksURI: "https://foo.com/certs",
4347-
ClientID: "foo",
4348-
ClientSecret: "super_secret_123",
4349-
RedirectURI: "/_codexch",
4350-
Scope: "openid",
4351-
ZoneSyncLeeway: 0,
4352-
AccessTokenEnable: true,
4348+
AuthEndpoint: "https://foo.com/auth",
4349+
TokenEndpoint: "https://foo.com/token",
4350+
JwksURI: "https://foo.com/certs",
4351+
ClientID: "foo",
4352+
ClientSecret: "super_secret_123",
4353+
RedirectURI: "/_codexch",
4354+
Scope: "openid",
4355+
ZoneSyncLeeway: 0,
4356+
AccessTokenEnable: true,
4357+
InterceptErrorEnable: false,
43534358
},
43544359
key: "default/oidc-policy-1",
43554360
},
@@ -4365,14 +4370,15 @@ func TestGeneratePoliciesFails(t *testing.T) {
43654370
},
43664371
expectedOidc: &oidcPolicyCfg{
43674372
oidc: &version2.OIDC{
4368-
AuthEndpoint: "https://foo.com/auth",
4369-
TokenEndpoint: "https://foo.com/token",
4370-
JwksURI: "https://foo.com/certs",
4371-
ClientID: "foo",
4372-
ClientSecret: "super_secret_123",
4373-
RedirectURI: "/_codexch",
4374-
Scope: "openid",
4375-
AccessTokenEnable: true,
4373+
AuthEndpoint: "https://foo.com/auth",
4374+
TokenEndpoint: "https://foo.com/token",
4375+
JwksURI: "https://foo.com/certs",
4376+
ClientID: "foo",
4377+
ClientSecret: "super_secret_123",
4378+
RedirectURI: "/_codexch",
4379+
Scope: "openid",
4380+
AccessTokenEnable: true,
4381+
InterceptErrorEnable: false,
43764382
},
43774383
key: "default/oidc-policy-1",
43784384
},
@@ -4397,12 +4403,13 @@ func TestGeneratePoliciesFails(t *testing.T) {
43974403
},
43984404
Spec: conf_v1.PolicySpec{
43994405
OIDC: &conf_v1.OIDC{
4400-
ClientSecret: "oidc-secret",
4401-
AuthEndpoint: "https://foo.com/auth",
4402-
TokenEndpoint: "https://foo.com/token",
4403-
JWKSURI: "https://foo.com/certs",
4404-
ClientID: "foo",
4405-
AccessTokenEnable: true,
4406+
ClientSecret: "oidc-secret",
4407+
AuthEndpoint: "https://foo.com/auth",
4408+
TokenEndpoint: "https://foo.com/token",
4409+
JWKSURI: "https://foo.com/certs",
4410+
ClientID: "foo",
4411+
AccessTokenEnable: true,
4412+
InterceptErrorEnable: false,
44064413
},
44074414
},
44084415
},
@@ -4413,12 +4420,13 @@ func TestGeneratePoliciesFails(t *testing.T) {
44134420
},
44144421
Spec: conf_v1.PolicySpec{
44154422
OIDC: &conf_v1.OIDC{
4416-
ClientSecret: "oidc-secret",
4417-
AuthEndpoint: "https://bar.com/auth",
4418-
TokenEndpoint: "https://bar.com/token",
4419-
JWKSURI: "https://bar.com/certs",
4420-
ClientID: "bar",
4421-
AccessTokenEnable: true,
4423+
ClientSecret: "oidc-secret",
4424+
AuthEndpoint: "https://bar.com/auth",
4425+
TokenEndpoint: "https://bar.com/token",
4426+
JWKSURI: "https://bar.com/certs",
4427+
ClientID: "bar",
4428+
AccessTokenEnable: true,
4429+
InterceptErrorEnable: false,
44224430
},
44234431
},
44244432
},
@@ -4446,15 +4454,16 @@ func TestGeneratePoliciesFails(t *testing.T) {
44464454
},
44474455
expectedOidc: &oidcPolicyCfg{
44484456
&version2.OIDC{
4449-
AuthEndpoint: "https://foo.com/auth",
4450-
TokenEndpoint: "https://foo.com/token",
4451-
JwksURI: "https://foo.com/certs",
4452-
ClientID: "foo",
4453-
ClientSecret: "super_secret_123",
4454-
RedirectURI: "/_codexch",
4455-
Scope: "openid",
4456-
ZoneSyncLeeway: 200,
4457-
AccessTokenEnable: true,
4457+
AuthEndpoint: "https://foo.com/auth",
4458+
TokenEndpoint: "https://foo.com/token",
4459+
JwksURI: "https://foo.com/certs",
4460+
ClientID: "foo",
4461+
ClientSecret: "super_secret_123",
4462+
RedirectURI: "/_codexch",
4463+
Scope: "openid",
4464+
ZoneSyncLeeway: 200,
4465+
AccessTokenEnable: true,
4466+
InterceptErrorEnable: false,
44584467
},
44594468
"default/oidc-policy",
44604469
},

pkg/apis/configuration/v1/types.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -475,16 +475,17 @@ type EgressMTLS struct {
475475

476476
// OIDC defines an Open ID Connect policy.
477477
type OIDC struct {
478-
AuthEndpoint string `json:"authEndpoint"`
479-
TokenEndpoint string `json:"tokenEndpoint"`
480-
JWKSURI string `json:"jwksURI"`
481-
ClientID string `json:"clientID"`
482-
ClientSecret string `json:"clientSecret"`
483-
Scope string `json:"scope"`
484-
RedirectURI string `json:"redirectURI"`
485-
ZoneSyncLeeway *int `json:"zoneSyncLeeway"`
486-
AuthExtraArgs []string `json:"authExtraArgs"`
487-
AccessTokenEnable bool `json:"accessTokenEnable"`
478+
AuthEndpoint string `json:"authEndpoint"`
479+
TokenEndpoint string `json:"tokenEndpoint"`
480+
JWKSURI string `json:"jwksURI"`
481+
ClientID string `json:"clientID"`
482+
ClientSecret string `json:"clientSecret"`
483+
Scope string `json:"scope"`
484+
RedirectURI string `json:"redirectURI"`
485+
ZoneSyncLeeway *int `json:"zoneSyncLeeway"`
486+
AuthExtraArgs []string `json:"authExtraArgs"`
487+
AccessTokenEnable bool `json:"accessTokenEnable"`
488+
InterceptErrorEnable bool `json:"interceptErrorEnable"`
488489
}
489490

490491
// WAF defines an WAF policy.

0 commit comments

Comments
 (0)