22 * nginScript functions for providing OpenID Connect authorization
33 * code flow with NGINX Plus.
44 *
5- * Copyright (C) 2018 Nginx, Inc.
5+ * Copyright (C) 2019 Nginx, Inc.
66 */
77
88var auth_token = "" ;
99
10- function oidcCodeExchange ( req , res ) {
10+ function oidcCodeExchange ( r ) {
1111 // First check that we received an authorization code from the IdP
12- if ( req . variables . arg_code . length == 0 ) {
13- if ( req . variables . arg_error ) {
14- req . error ( "OIDC error receiving authorization code from IdP: " + req . variables . arg_error_description ) ;
12+ if ( r . variables . arg_code . length == 0 ) {
13+ if ( r . variables . arg_error ) {
14+ r . error ( "OIDC error receiving authorization code from IdP: " + r . variables . arg_error_description ) ;
1515 } else {
16- req . error ( "OIDC expected authorization code from IdP but received: " + req . variables . uri ) ;
16+ r . error ( "OIDC expected authorization code from IdP but received: " + r . variables . uri ) ;
1717 }
18- res . return ( 502 ) ;
18+ r . return ( 502 ) ;
1919 return ;
2020 }
2121
2222 // Pass the authorization code to the /_token location so that it can be
2323 // proxied to the IdP in exchange for a JWT
24- req . subrequest ( "/_token" , "code=" + req . variables . arg_code ,
24+ r . subrequest ( "/_token" , "code=" + r . variables . arg_code ,
2525 function ( reply ) {
2626 if ( reply . status == 504 ) {
27- req . error ( "OIDC timeout connecting to IdP when sending authorization code" ) ;
28- res . return ( 504 ) ;
27+ r . error ( "OIDC timeout connecting to IdP when sending authorization code" ) ;
28+ r . return ( 504 ) ;
2929 return ;
3030 }
3131
3232 if ( reply . status != 200 ) {
3333 try {
34- var errorset = JSON . parse ( reply . body ) ;
34+ var errorset = JSON . parse ( reply . responseBody ) ;
3535 if ( errorset . error ) {
36- req . error ( "OIDC error from IdP when sending authorization code: " + errorset . error + ", " + errorset . error_description ) ;
36+ r . error ( "OIDC error from IdP when sending authorization code: " + errorset . error + ", " + errorset . error_description ) ;
3737 } else {
38- req . error ( "OIDC unexpected response from IdP when sending authorization code (HTTP " + reply . status + "). " + reply . body ) ;
38+ r . error ( "OIDC unexpected response from IdP when sending authorization code (HTTP " + reply . status + "). " + reply . responseBody ) ;
3939 }
4040 } catch ( e ) {
41- req . error ( "OIDC unexpected response from IdP when sending authorization code (HTTP " + reply . status + "). " + reply . body ) ;
41+ r . error ( "OIDC unexpected response from IdP when sending authorization code (HTTP " + reply . status + "). " + reply . responseBody ) ;
4242 }
43- res . return ( 502 ) ;
43+ r . return ( 502 ) ;
4444 return ;
4545 }
4646
4747 // Code exchange returned 200, check response
4848 try {
4949 // Send the ID Token to auth_jwt location for validation
50- var tokenset = JSON . parse ( reply . body ) ;
51- req . subrequest ( "/_id_token_validation" , "token=" + tokenset . id_token ,
50+ var tokenset = JSON . parse ( reply . responseBody ) ;
51+ r . subrequest ( "/_id_token_validation" , "token=" + tokenset . id_token ,
5252 function ( reply ) {
5353 if ( reply . status != 204 ) {
54- res . return ( 500 ) ; // validateIdToken() will log errors
54+ r . return ( 500 ) ; // validateIdToken() will log errors
5555 return ;
5656 }
5757
5858 // ID Token is valid
59- req . subrequest ( "/_create_session" , "key=" + req . variables . request_id + "&val=" + tokenset . id_token ,
59+ r . subrequest ( "/_create_session" , "key=" + r . variables . request_id + "&val=" + tokenset . id_token ,
6060 function ( reply ) {
6161 if ( reply . status != 201 ) {
62- req . error ( "OIDC error creating session in keyval (" + reply . status + ") " + reply . body ) ;
63- res . return ( 500 ) ;
62+ r . error ( "OIDC error creating session in keyval (" + reply . status + ") " + reply . responseBody ) ;
63+ r . return ( 500 ) ;
6464 return ;
6565 }
6666
6767 // Session created
68- req . log ( "OIDC success, creating session " + req . variables . request_id ) ;
69- auth_token = req . variables . request_id ; // Export as NGINX variable
70- res . return ( 302 , req . variables . cookie_auth_redir ) ;
68+ r . log ( "OIDC success, creating session " + r . variables . request_id ) ;
69+ auth_token = r . variables . request_id ; // Export as NGINX variable
70+ r . return ( 302 , r . variables . cookie_auth_redir ) ;
7171 }
7272 ) ;
7373 }
7474 ) ;
7575 } catch ( e ) {
76- req . error ( "OIDC authorization code sent but token response is not JSON. " + reply . body ) ;
77- res . return ( 502 ) ;
76+ r . error ( "OIDC authorization code sent but token response is not JSON. " + reply . responseBody ) ;
77+ r . return ( 502 ) ;
7878 }
7979 }
8080 ) ;
8181}
8282
83- function getAuthToken ( req , res ) {
83+ function getAuthToken ( r ) {
8484 return auth_token ;
8585}
8686
87- function hashRequestId ( req ) {
87+ function hashRequestId ( r ) {
8888 var c = require ( 'crypto' ) ;
89- var h = c . createHmac ( 'sha256' , req . variables . oidc_hmac_key ) . update ( req . variables . request_id ) ;
89+ var h = c . createHmac ( 'sha256' , r . variables . oidc_hmac_key ) . update ( r . variables . request_id ) ;
9090 return h . digest ( 'base64url' ) ;
9191}
9292
93- function validateIdToken ( req , res ) {
93+ function validateIdToken ( r ) {
9494 // Check mandatory claims
9595 var required_claims = [ "aud" , "iat" , "iss" , "sub" ] ;
9696 var missing_claims = [ ] ;
9797 for ( var i in required_claims ) {
98- if ( req . variables [ "jwt_claim_" + required_claims [ i ] ] . length == 0 ) {
98+ if ( r . variables [ "jwt_claim_" + required_claims [ i ] ] . length == 0 ) {
9999 missing_claims . push ( required_claims [ i ] ) ;
100100 }
101101 }
102102 if ( missing_claims . length ) {
103- req . error ( "OIDC ID Token validation error: missing claim(s) " + missing_claims . join ( " " ) ) ;
104- res . return ( 403 ) ;
103+ r . error ( "OIDC ID Token validation error: missing claim(s) " + missing_claims . join ( " " ) ) ;
104+ r . return ( 403 ) ;
105105 return ;
106106 }
107107 var valid_token = true ;
108108
109109 // Check iat is a positive integer
110- var iat = Math . floor ( Number ( req . variables . jwt_claim_iat ) ) ;
111- if ( String ( iat ) != req . variables . jwt_claim_iat || iat < 1 ) {
112- req . error ( "OIDC ID Token validation error: iat claim is not a valid number" ) ;
110+ var iat = Math . floor ( Number ( r . variables . jwt_claim_iat ) ) ;
111+ if ( String ( iat ) != r . variables . jwt_claim_iat || iat < 1 ) {
112+ r . error ( "OIDC ID Token validation error: iat claim is not a valid number" ) ;
113113 valid_token = false ;
114114 }
115115
116116 // Check iss relates to $oidc_authz_endpoint
117- if ( ! req . variables . oidc_authz_endpoint . startsWith ( req . variables . jwt_claim_iss ) ) {
118- req . error ( "OIDC ID Token validation error: iss claim (" + req . variables . jwt_claim_iss + ") is not found in $oidc_authz_endpoint" ) ;
117+ if ( ! r . variables . oidc_authz_endpoint . startsWith ( r . variables . jwt_claim_iss ) ) {
118+ r . error ( "OIDC ID Token validation error: iss claim (" + r . variables . jwt_claim_iss + ") is not found in $oidc_authz_endpoint" ) ;
119119 valid_token = false ;
120120 }
121121
122122 // Audience matching
123- if ( req . variables . jwt_claim_aud != req . variables . oidc_client ) {
124- req . error ( "OIDC ID Token validation error: aud claim (" + req . variables . jwt_claim_aud + ") does not match $oidc_client" ) ;
123+ if ( r . variables . jwt_claim_aud != r . variables . oidc_client ) {
124+ r . error ( "OIDC ID Token validation error: aud claim (" + r . variables . jwt_claim_aud + ") does not match $oidc_client" ) ;
125125 valid_token = false ;
126126 }
127127
128128 // If we receive a nonce in the ID Token then we will use the auth_nonce cookie
129129 // to check that the JWT can be validated as being directly related to the
130130 // original request by this client. This mitigates against token replay attacks.
131131 var client_nonce_hash = "" ;
132- if ( req . variables . cookie_auth_nonce ) {
132+ if ( r . variables . cookie_auth_nonce ) {
133133 var c = require ( 'crypto' ) ;
134- var h = c . createHmac ( 'sha256' , req . variables . oidc_hmac_key ) . update ( req . variables . cookie_auth_nonce ) ;
134+ var h = c . createHmac ( 'sha256' , r . variables . oidc_hmac_key ) . update ( r . variables . cookie_auth_nonce ) ;
135135 client_nonce_hash = h . digest ( 'base64url' ) ;
136136 }
137- if ( req . variables . jwt_claim_nonce != client_nonce_hash ) {
138- req . error ( "OIDC ID Token validation error: nonce mismatch" ) ;
137+ if ( r . variables . jwt_claim_nonce != client_nonce_hash ) {
138+ r . error ( "OIDC ID Token validation error: nonce mismatch" ) ;
139139 valid_token = false ;
140140 }
141141
142142 if ( valid_token ) {
143- res . return ( 204 ) ;
143+ r . return ( 204 ) ;
144144 } else {
145- res . return ( 403 ) ;
145+ r . return ( 403 ) ;
146146 }
147- }
147+ }
0 commit comments