Skip to content

Enable PKCE Support #25

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

Merged
merged 4 commits into from
Dec 8, 2020
Merged

Enable PKCE Support #25

merged 4 commits into from
Dec 8, 2020

Conversation

tippexs
Copy link
Contributor

@tippexs tippexs commented Dec 2, 2020

This feature updates introduces the PKCE support for the OIDC reference implementation.

enable it by setting $oidc_pkce_enable to 1. To use the authorization code grant set the switch to 0

var h = c.createHmac('sha256', r.variables.oidc_hmac_key).update(noncePlain);
var nonceHash = h.digest('base64url');

// Redirect the client to the IdP login page with the cookies we need for state
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be for the r.return line in the auth function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"auth_redir=" + r.variables.request_uri + "; " + r.variables.oidc_cookie_flags,
"auth_nonce=" + noncePlain + "; " + r.variables.oidc_cookie_flags ];

if ( r.variables.oidc_pkce_enable == 1 ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/==/=== ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NGINX handles variables always as strings. Therfore === will not work here. Possible solution would be something like String(r.variables.oidc_pkce_enable) === "1". But looks a little bit to hacky to me.

"auth_nonce=" + noncePlain + "; " + r.variables.oidc_cookie_flags ];

if ( r.variables.oidc_pkce_enable == 1 ) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: unnecessary empty line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

return authZUri;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: unnecessary empty line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -7,6 +7,36 @@ var newSession = false; // Used by oidcAuth() and validateIdToken()

export default {auth, codeExchange, validateIdToken, logout};


function authZUriHandler(r) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For discussion, should this function appear below the exported ones? I like the idea of being able to follow the logic by looking at this file. So when you initially see a helper function, it might be confusing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its now at the bottom of the js file.

var pkce_code_challenge = c.createHash('sha256').update(pkce_code_verifier).digest('base64url');
r.variables.pkce_code_verifier = pkce_code_verifier;

authZUri = "?response_type=code&scope=" + r.variables.oidc_scopes + "&code_challenge_method=S256&code_challenge="+pkce_code_challenge+"&client_id=" + r.variables.oidc_client + "&state="+ r.variables.pkce_id +"&redirect_uri="+ r.variables.redirect_base + r.variables.redir_location + "&nonce=" + nonceHash;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: spaces between strings and + are inconsistent. Recommend single whitespace between the + concatenation operator

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


authZUri = "?response_type=code&scope=" + r.variables.oidc_scopes + "&code_challenge_method=S256&code_challenge="+pkce_code_challenge+"&client_id=" + r.variables.oidc_client + "&state="+ r.variables.pkce_id +"&redirect_uri="+ r.variables.redirect_base + r.variables.redir_location + "&nonce=" + nonceHash;
} else {
authZUri = "?response_type=code&scope=" + r.variables.oidc_scopes + "&client_id=" + r.variables.oidc_client + "&state=0&redirect_uri="+ r.variables.redirect_base + r.variables.redir_location + "&nonce=" + nonceHash;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the common parts be prepared in advance, so that we're only appending the special parts?

var pkce_code_verifier = c.createHmac('sha256', r.variables.oidc_hmac_key).update(String(Math.random())).digest('hex');
r.variables.pkce_id = c.createHash('sha256').update(String(Math.random())).digest('base64url');
var pkce_code_challenge = c.createHash('sha256').update(pkce_code_verifier).digest('base64url');
r.variables.pkce_code_verifier = pkce_code_verifier;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment would be helpful to show that this variable assignment is actually creating a keyval entry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactoring done

var internalTokenEndpoint = null;
var internalTokenEndpointUri = null;

if ( r.variables.oidc_pkce_enable == 1 ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not pass these as query params instead of needing a completely separate location block? Seems to be adding a lot of extra config lines unnecessarily, but I might have missed something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree. Let me rewrite this part and use a single location instead of two.

@@ -1,5 +1,6 @@
# Advanced configuration START
set $internal_error_message "NGINX / OpenID Connect login failure\n";
set $pkce_id "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? Add a comment to explain

@@ -63,11 +67,13 @@ proxy_cache_path /var/cache/nginx/jwk levels=1 keys_zone=jwk:64k max_size=1m;
# Change timeout values to at least the validity period of each token type
keyval_zone zone=oidc_id_tokens:1M state=conf.d/oidc_id_tokens.json timeout=1h;
keyval_zone zone=refresh_tokens:1M state=conf.d/refresh_tokens.json timeout=8h;
keyval_zone zone=pkce:1M state=conf.d/pkce.json timeout=2m;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a state file for pkce? Suggest separating this from the other keyvals because as ask the customer to adjust the timeouts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed! Will change this.

Timo Stark added 3 commits December 8, 2020 11:18
- Code cleanup and refactoring
- New function for setting IdP Client Auth variables
- Code cleanup and refactoring
- New function for setting IdP Client Auth variables
- Added PKCE documentation to README
- Adjusted pkce keyvalue zones size and timeout
@tippexs tippexs marked this pull request as ready for review December 8, 2020 12:14
@lcrilly
Copy link
Contributor

lcrilly commented Dec 8, 2020

Looks good, squashing

@lcrilly lcrilly merged commit 60ea2c2 into nginxinc:master Dec 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants