PKCE stands for “Proof Key for Code Exchange” and is a way to make OAuth 2.0 and OpenID Connect operations using an authorization code more secure. It is specified in RFC 7636.
PKCE applies to authorization/token requests whenever the code grant type is involved – e.g. plain OAuth 2.0 authorization code flow as well as (the superior) OpenID Connect hybrid flow (e.g. code id_token).
It mitigates an attack where the authorization response can be intercepted and the “stolen” code can be used to request access tokens. It introduces a per-request secret between the legitimate client and the authorization server, that is unknown to an attacker that can only see authorization responses. This is mainly useful for mobile/native clients.
IdentityServer3 as of v2.4 fully supports PKCE and the authorization and token endpoint documentation has the new parameters. Also the discovery endpoint now includes the code_challenge_methods_supported entry.
IdentityModel v1.5 includes the client pieces to interact with PKCE. You can e.g. use the following code to construct an authorization request:
var nonce = CryptoRandom.CreateRandomKeyString(64); var verifier = CryptoRandom.CreateRandomKeyString(64); var challenge = verifier.ToCodeChallenge(); var request = new AuthorizeRequest("https://my.server/authorization"); var url = request.CreateAuthorizeUrl( clientId: "myclient", responseType: "code id_token", scope: "openid myapi", redirectUri: "https://my.client/cb", nonce: nonce, codeChallenge: challenge, codeChallengeMethod: OidcConstants.CodeChallengeMethods.Sha256);
and the TokenClient to exchange the code with the token:
var tokenClient = new TokenClient( "https://my.server/token", "client", "secret"); var response = await tokenClient.RequestAuthorizationCodeAsync( code: code, redirectUri: "https://my.client/cb", codeVerifier: verifier);
Pingback: OAuth 2.0 and PKCE | Pedro Félix's shared memory
Quick question – is it possible to use this via the OpenIdConnectAuthentication middleware? Would it just be a case of using the Notifications to add the necessary url parameters?
Haven’t tried it – but would probably work.
Cool, thanks Dominick. It’s on my list to do soon so if it works I’ll post about it somewhere as I’m sure I won’t be the only one wanting to do it.
What about while refreshing tokens? It seems this spec does not say anything regarding using PKCE while using refresh token to renew access token.
PKCE is about securing the link between the app and the browser. Refreshing a token does not involve a browser.
We can combine authorization code with client credentials flow (i.e. same client can be used for both flows). Is it possible to combine PKCE flow with client credentials flow too? Can we use same client?
We have a need to call APIs secured by IS4 from a Mobile app that has legacy login pages. The login pages cannot easily be moved to IS4. What would be the most appropriate method for getting and access token from IS4 using the username/password of an already “”authenticated” user ? I know that Resource Owner Password is a NoNo. Is there a way to use Authorization Code flow and bypass the login process ?
In the end, we need the token to be populated with the proper scopes/claims so they are available in the APIs to perform Authorization through existing Policies.
Also, we will be using PKCE
Sorry – I don’t know a good way besides moving the authentication to the token issuer…