You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+75-33Lines changed: 75 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ With this environment, both the client and NGINX Plus communicate directly with
24
24
25
25
NGINX Plus is configured to perform OpenID Connect authentication. Upon a first visit to a protected resource, NGINX Plus initiates the OpenID Connect authorization code flow and redirects the client to the OpenID Connect provider (IdP). When the client returns to NGINX Plus with an authorization code, NGINX Plus exchanges that code for a set of tokens by communicating directly with the IdP.
26
26
27
-
The ID Token received from the IdP is then [validated](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation). NGINX Plus then stores the ID token in the key-value store, issues a session cookie to the client using a random string, (which becomes the key to obtain the ID token from the key-value store) and redirects the client to the original URI requested prior to authentication.
27
+
The ID Token received from the IdP is [validated](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation). NGINX Plus then stores the ID token in the key-value store, issues a session cookie to the client using a random string, (which becomes the key to obtain the ID token from the key-value store) and redirects the client to the original URI requested prior to authentication.
28
28
29
29
Subsequent requests to protected resources are authenticated by exchanging the session cookie for the ID Token in the key-value store. JWT validation is performed on each request, as normal, so that the ID Token validity period is enforced.
30
30
@@ -38,15 +38,19 @@ If a [refresh token](https://openid.net/specs/openid-connect-core-1_0.html#Refre
38
38
39
39
Requests made to the `/logout` location invalidate both the ID token and refresh token by erasing them from the key-value store. Therefore, subsequent requests to protected resources will be treated as a first-time request and send the client to the IdP for authentication. Note that the IdP may issue cookies such that an authenticated session still exists at the IdP.
40
40
41
-
## Installation
41
+
### Multiple IdPs
42
+
43
+
Where NGINX Plus is configured to proxy requests for multiple websites or applications, or user groups, these may require authentication by different IdPs. Separate IdPs can be configured, with each one matching on an attribute of the HTTP request, e.g. hostname or part of the URI path.
42
44
43
-
The master branch of this repo requires the most recent release of NGINX Plus. Older releases should use the branch corresponding to that NGINX Plus release. For installation instructions, see [Installing NGINX Plus](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-plus/).
45
+
> **Note:** When validating OpenID Connect tokens, NGINX Plus can be configured to read the signing key (JWKS) from disk, or a URL. When using multiple IdPs, each one must be configured to use the same method. It is not possible to use a mix of both disk and URLs for the `map…$oidc_jwt_keyfile` variable.
46
+
47
+
## Installation
44
48
45
-
In addition, the [njs module](https://www.nginx.com/blog/introduction-nginscript/) is required for handling the interaction between NGINX Plus and the OpenID Connect provider (IdP). Install the njs module after installing NGINX Plus by running one of the following:
49
+
Start by [installing NGINX Plus](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-plus/). In addition, the [NGINX JavaScript module](https://www.nginx.com/blog/introduction-nginscript/) (njs) is required for handling the interaction between NGINX Plus and the OpenID Connect provider (IdP). Install the njs module after installing NGINX Plus by running one of the following:
46
50
47
51
`$ sudo apt install nginx-plus-module-njs` for Debian/Ubuntu
48
52
49
-
`$ sudo yum install nginx-plus-module-njs` for CentOS/RedHat
53
+
`$ sudo yum install nginx-plus-module-njs` for CentOS/RHEL
50
54
51
55
The njs module needs to be loaded by adding the following configuration directive near the top of **nginx.conf**.
52
56
@@ -58,13 +62,24 @@ Finally, create a clone of the GitHub repository.
> **N.B.** There is a branch for each NGINX Plus release. Switch to the correct branch to ensure compatibility with the features and syntax of each release.
65
+
> **Note:** There is a branch for each NGINX Plus release. Switch to the correct branch to ensure compatibility with the features and syntax of each release. The master branch works with the most recent NGINX Plus and JavaScript module releases.
62
66
63
67
All files can be copied to **/etc/nginx/conf.d**
64
68
65
-
> **N.B.** The GitHub repository contains [include](http://nginx.org/en/docs/ngx_core_module.html#include) files for NGINX configuration and JavaScript code for token exchange and initial token validation. These files are referenced with a relative path (relative to /etc/nginx). If NGINX Plus is running from a non-standard location then copy the files from the GitHub repository to `/path/to/conf/conf.d` and use the `-p` flag to start NGINX with a prefix path that specifies the location where the configuration files are located.
The GitHub repository contains [`include`](http://nginx.org/en/docs/ngx_core_module.html#include) files for NGINX configuration, and JavaScript code for token exchange and initial token validation. These files are referenced with a relative path (relative to /etc/nginx). If NGINX Plus is running from a non-standard location then copy the files from the GitHub repository to `/path/to/conf/conf.d` and use the `-p` flag to start NGINX with a prefix path that specifies the location where the configuration files are located.
This implementation is suitable for running in a container provided that the [base image](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-docker/) includes the NGINX JavaScript module. The GitHub repository is designed to facilitate testing with a container by binding the cloned repository to a mount volume on the container.
78
+
79
+
```shell
80
+
$ cd nginx-openid-connect
81
+
$ docker run -d -p 8010:8010 -v $PWD:/etc/nginx/conf.d nginx-plus
82
+
```
68
83
69
84
## Configuring your IdP
70
85
@@ -74,45 +89,48 @@ All files can be copied to **/etc/nginx/conf.d**
74
89
* Ensure NGINX Plus is configured as a confidential client (with a client secret)
75
90
* Make a note of the `client ID` and `client secret`
76
91
77
-
* If your IdP supports OpenID Connect Discovery (usually at the URI `/.well-known/openid-configuration`) then use the `configure.sh` script to complete configuration. In this case you can skip the **frontend.conf** configuration. Otherwise:
92
+
* If your IdP supports OpenID Connect Discovery (usually at the URI `/.well-known/openid-configuration`) then use the `configure.sh` script to complete configuration. In this case you can skip the next section. Otherwise:
78
93
* Obtain the URL for `jwks_uri` or download the JWK file to your NGINX Plus instance
79
94
* Obtain the URL for the **authorization endpoint**
80
95
* Obtain the URL for the **token endpoint**
81
96
82
97
## Configuring NGINX Plus
83
98
84
-
Review the following files copied from the GitHub repository so that they match your IdP configuration.
99
+
Configuration can typically be completed automatically by using the `configure.sh` script.
100
+
101
+
Manual configuration involves reviewing the following files so that they match your IdP(s) configuration.
85
102
86
-
***frontend.conf** - this is the reverse proxy configuration and where the IdP is configured. This file can be automatically configured by using the `configure.sh` script.
103
+
***openid_connect_configuration.conf** - this contains the primary configuration for one or more IdPs in `map{}` blocks
104
+
* Modify all of the `map…$oidc_` blocks to match your IdP configuration
105
+
* Modify the URI defined in `map…$oidc_logout_redirect` to specify an unprotected resource to be displayed after requesting the `/logout` location
106
+
* Set a unique value for `$oidc_hmac_key` to ensure nonce values are unpredictable
107
+
108
+
***frontend.conf** - this is the reverse proxy configuration
87
109
* Modify the upstream group to match your backend site or app
88
-
* Modify the `resolver` directive to match a DNS server that is capable of resolving the IdP defined in `$oidc_token_endpoint`
89
-
* Modify the URI defined in `$oidc_logout_redirect` to specify an unprotected resource to be displayed after requesting the `/logout` location
90
110
* Configure the preferred listen port and [enable SSL/TLS configuration](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/)
91
-
*Set the value of `$oidc_jwt_keyfile` to specify the `jwks_uri` value or match the JWK file downloaded from the IdP (ensuring that it is readable by the NGINX worker processes)
111
+
*Modify the severity level of the `error_log` directive to suit the deployment environment
92
112
* Comment/uncomment the `auth_jwt_key_file` or `auth_jwt_key_request` directives based on whether `$oidc_jwt_keyfile` is a file or URI, respectively
93
-
* Modify all of the `set $oidc_` directives to match your IdP configuration
94
-
* Set a unique value for `$oidc_hmac_key` to ensure nonce values are unpredictable
95
113
96
114
***openid_connect.server_conf** - this is the NGINX configuration for handling the various stages of OpenID Connect authorization code flow
97
115
* No changes are usually required here
116
+
* Modify the `resolver` directive to match a DNS server that is capable of resolving the IdP defined in `$oidc_token_endpoint`
98
117
* If using [`auth_jwt_key_request`](http://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html#auth_jwt_key_request) to automatically fetch the JWK file from the IdP then modify the validity period and other caching options to suit your IdP
99
-
* Modify the `add_header Set-Cookie` directives with appropriate [cookie flags](https://en.wikipedia.org/wiki/HTTP_cookie#Terminology) to control the scope of single sign-on and security options, e.g. Domain; Path; Secure;
100
118
101
119
***openid_connect.js** - this is the JavaScript code for performing the authorization code exchange and nonce hashing
102
120
* No changes are required unless modifying the code exchange or validation process
103
121
104
122
### Configuring the Key-Value Store
105
123
106
-
The key-value store is used to maintain persistent storage for ID tokens and refresh tokens. The default configuration should be reviewed so that it suits the environment.
124
+
The key-value store is used to maintain persistent storage for ID tokens and refresh tokens. The default configuration should be reviewed so that it suits the environment. This is part of the advanced configuration in **openid_connect_configuration.conf**.
Each of the `keyval_zone` parameters are described below.
114
132
115
-
***zone** - Specifies the name of the key-value store and how much memory to allocate for it. Each session will typically occupy 1-2KB, depending on the size of the JWT, so scale this value to exceed the number of unique users that may authenticate.
133
+
***zone** - Specifies the name of the key-value store and how much memory to allocate for it. Each session will typically occupy 1-2KB, depending on the size of the tokens, so scale this value to exceed the number of unique users that may authenticate.
116
134
117
135
***state** (optional) - Specifies where all of the ID Tokens in the key-value store are saved, so that sessions will persist across restart or reboot of the NGINX host. The NGINX Plus user account, typically **nginx**, must have write permission to the directory where the state file is stored. Consider creating a dedicated directory for this purpose.
118
136
@@ -127,35 +145,60 @@ The [NGINX Plus API](http://nginx.org/en/docs/http/ngx_http_api_module.html) is
127
145
To query the current sessions in the key-value store:
The **openid_connect.server_conf** file defines several [`status_zone`](http://nginx.org/en/docs/http/ngx_http_api_module.html#status_zone) directives to collect metrics about OpenID Connect activity and errors. Separate metrics counters are recorded for:
168
+
169
+
***OIDC start** - New sessions are counted here. See step 2 in Figure 2, above. Success is recorded as a 3xx response.
170
+
171
+
***OIDC code exchange** - Counters are incremented here when the browser returns to NGINX Plus after authentication. See steps 6-10 in Figure 2, above. Success is recorded as a 3xx response.
172
+
173
+
***OIDC logout** - Requests to the /logout URI are counted here. Success is recorded as a 3xx response.
174
+
175
+
***OIDC error** - Counters are incremented here when errors in the code exchange process are actively detected. Typically there will be a corresponding error_log entry.
176
+
177
+
To obtain the current set of metrics:
178
+
179
+
```shell
180
+
$ curl localhost:8010/api/6/http/location_zones
145
181
```
146
182
183
+
In addition, the [NGINX Plus Dashboard](https://docs.nginx.com/nginx/admin-guide/monitoring/live-activity-monitoring/#dashboard) can be configured to visualize the monitoring metrics in a GUI.
184
+
147
185
## Troubleshooting
148
186
149
-
Any errors generated by the OpenID Connect flow are logged in a separate file, `/var/log/nginx/oidc_error.log`. Check the contents of this file as it may include error responses received by the IdP.
187
+
Any errors generated by the OpenID Connect flow are logged to the error log, `/var/log/nginx/error.log`. Check the contents of this file as it may include error responses received by the IdP. The level of detail recorded can be modified by adjusting the severity level of the `error_log` directive.
150
188
151
189
***400 error from IdP**
152
190
* This is typically caused by incorrect configuration related to the client ID and client secret.
153
-
* Check the values of the `$oidc_client` and `$oidc_client_secret` variables against the IdP configuration.
191
+
* Check the values of the `map…$oidc_client` and `map…$oidc_client_secret` variables against the IdP configuration.
192
+
193
+
***500 error from nginx after successful authentication**
194
+
* Check for `could not be resolved` and `empty JWK set while sending to client` messages in the error log. This is common when NGINX Plus cannot reach the IdP's `jwks_uri` endpoint.
195
+
* Check the `map…$oidc_jwt_keyfile` variable is correct.
196
+
* Check the `resolver` directive in **openid_connect.server_conf** is reachable from the NGINX Plus host.
154
197
155
198
***Authentication is successful but browser shows too many redirects**
156
199
* This is typically because the JWT sent to the browser cannot be validated, resulting in 'authorization required' `401` response and starting the authentication process again. But the user is already authenticated so is redirected back to NGINX, hence the redirect loop.
157
-
* Check the error log `/var/log/nginx/oidc_error.log` for JWT/JWK errors.
158
-
* Ensure that the JWK file (`$oidc_jwt_keyfile` variable) is correct and that the nginx user has permission to read it.
200
+
* Check the error log `/var/log/nginx/error.log` for JWT/JWK errors.
201
+
* Ensure that the JWK file (`map…$oidc_jwt_keyfile` variable) is correct and that the nginx user has permission to read it.
159
202
160
203
***Logged out but next request does not require authentication**
161
204
* This is typically caused by the IdP issuing its own session cookie(s) to the client. NGINX Plus sends the request to the IdP for authentication and the IdP immediately sends back a new authorization code because the session is still valid.
@@ -168,7 +211,6 @@ Any errors generated by the OpenID Connect flow are logged in a separate file, `
168
211
```nginx
169
212
proxy_set_header Host <IdP hostname>;
170
213
proxy_ssl_name <IdP hostname>;
171
-
proxy_ssl_server_name on;
172
214
```
173
215
174
216
## Support
@@ -182,4 +224,4 @@ This reference implementation for OpenID Connect is supported for NGINX Plus sub
182
224
***R17** Configuration now supports JSON Web Key (JWK) set to be obtained by URI
183
225
***R18** Opaque session tokens now used by default. Added support for refresh tokens. Added `/logout` location.
184
226
***R19** Minor bug fixes
185
-
227
+
***R22** Separate configuration file, supports multiple IdPs. Configurable scopes and cookie flags. JavaScript is imported as an indepedent module with `js_import`. Container-friendly logging. Additional metrics for OIDC activity.
0 commit comments