Skip to content
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

PKCE support #28

Closed
stupiduglyfool opened this issue Oct 11, 2017 · 25 comments

Comments

@stupiduglyfool
Copy link

commented Oct 11, 2017

The readme specifies:

https://github.com/openid/AppAuth-JS/blob/master/README.md

The library also supports the PKCE extension to OAuth

However I cannot find any specification of code_challenge within the source code, therefore I would like some guidance of how to enable this?

For example if I look at the similarly named project AppAuth-Android I do find references to this expected PKCE parameter:

https://github.com/openid/AppAuth-Android/blob/de0ed1ad9b2362c1b27dfb3c1d2e6c8f13d699b4/library/java/net/openid/appauth/AuthorizationRequest.java#L959

Thanks.

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Oct 11, 2017

So currently, PKCE is supported via additional parameters 1, 2 that you can pass to both the AuthorizationRequest and the TokenRequest. I will update the library to add first class support for it.

@tikurahul tikurahul self-assigned this Oct 11, 2017

@stupiduglyfool

This comment has been minimized.

Copy link
Author

commented Oct 11, 2017

If it helps anyone I created a CodeVerifier for now: codeverifier-ts

Then provided the results to tokenHandler.performTokenRequest, and authorizationHandler.performAuthorizationRequest. eg: performauthorizationrequest-ts

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Oct 11, 2017

Thanks for sharing your code snippet. This works in the context of Node / Electron. We will need WebCrypto in the browser based implementation (which requires the use of a secure context). I am going to make that a part of the library.

@Jenan

This comment has been minimized.

Copy link

commented Nov 11, 2017

Is there any sample for PKCE? What package of crypto is available for this purpose? Thx

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Nov 12, 2017

crypto is a part of Node. For the web, you should be able to use WebCrypto as long as it’s a secure context.

@Jenan

This comment has been minimized.

Copy link

commented Nov 12, 2017

In electron app is possible to use nodejs crypto package or for website? Thx

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Nov 12, 2017

Yes. Electron has access to all Node APIs. Electron can use crypto.

@nmocruz

This comment has been minimized.

Copy link

commented Mar 27, 2018

any sample with WebCrypto ??? I was trying to use @stupiduglyfool sample with WebCrypto but is not working well, is not producing a valid pair to use against identity server 4

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Mar 27, 2018

I can add some support for it.

@someone1

This comment has been minimized.

Copy link
Contributor

commented Apr 6, 2018

My apologies if I'm wrong here, but I think the example given by @stupiduglyfool as-is will pass the code_verifier in the initial auth request, thus leaking the value that should otherwise be kept hidden. I think instead, for PKCE, you need to manage the challenge/verifier outside this package, as in store the verifier on your own (e.g. localStorage) and know to pass it in to the token request after receiving a code to initiate the exchange with.

Here is how I have PKCE generated and working in the browser (doesn't work with Google OpenID Connect as PKCE is only supported for native applications that redirect to a custom scheme or localhost address):

import { cryptoGenerateRandom, } from '@openid/appauth';
import TextEncodingShim from 'text-encoding'; // shimmed with 'text-encoding' package
const crypto = window.crypto; // shimmed with the 'webcrypto-shim' package

// Based off of the 'google-auth-library-nodejs' package: https://github.com/google/google-auth-library-nodejs/blob/master/src/auth/oauth2client.ts
async function generateCodeVerifier() {
    const codeVerifier = cryptoGenerateRandom(128);
    const codeChallenge = base64ArrayBuffer(await sha256(codeVerifier))
      .split('=')[0]
      .replace(/\+/g, '-')
      .replace(/\//g, '_');
    return { codeVerifier, codeChallenge };
  }

export function sha256(str: string) {
  // We transform the string into an arraybuffer.
  return crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(str)).then((buffer) => {
    return buffer;
  });
}

// base64ArrayBuffer taken from: https://gist.github.com/jonleighton/958841
@stupiduglyfool

This comment has been minimized.

Copy link
Author

commented Apr 6, 2018

@someone1 Thats correct (spec: rfc7636),

In the performAuthorizationRequest you just send the code_challenge + code_challenge_method.

In the subsequent token request you send the code_verifier.

Updated example

@twinklekumarp

This comment has been minimized.

Copy link

commented May 9, 2018

I am struggling to work AppAuth-Js with Identityserver3 to implement AuthorizationCode with PKCE. I am able to launch Login page but after successful login it is not redirecting but coming back to login page only. If you have completed your ionic example with PKCE can you please share it? There are so many days i have spent but totally stuck..please

@stupiduglyfool

This comment has been minimized.

Copy link
Author

commented May 11, 2018

I have it working with IdentityServer, how have you configured it, you should have a Client with a RedirectUri, the IdentityServer log may be able to provide useful information.

@nmocruz

This comment has been minimized.

Copy link

commented May 11, 2018

@stupiduglyfool

This comment has been minimized.

Copy link
Author

commented May 11, 2018

You need to add a client to IdentityServer here is an example:

IdentityServer Example:

new Client
{
ClientName = "Native Client (Code Flow with PKCE)",
ClientId = "NativeClient",
Enabled = true,
RequireConsent = true,
Flow = Flows.AuthorizationCodeWithProofKey,
ClientSecrets = new List
{
new Secret("non-secret-secret".Sha256())
},
AllowedCorsOrigins = _ioc.CoreModel.Service().GetCorsOrigins().ToList(),
PostLogoutRedirectUris = new List
{
$"https://{ServicePrefixConstants.Www}.{domainName}/#/logout"
},
RedirectUris = new List
{
$"http://127.0.0.1:8000"
},
AllowedScopes = new List
{
StandardScopes.OfflineAccess.Name,
"api"
} ,
RefreshTokenUsage = TokenUsage.ReUse,
AccessTokenType = AccessTokenType.Jwt,
AccessTokenLifetime = (int)TimeSpan.FromDays(1).TotalSeconds
}

In IdentityServer3 its not possible to have a client without a secret even though this flow doesn't require it.. (IdentityServer4 fixes this), thus you need to supply that secret with the request on the client..

typescript:

//required in electron if you're using self signed certs..
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

let config = { "clientId": "NativeClient"
"clientSecret": "non-secret-secret",
"openidUri": "https://localhost:5000",
"redirectUri": "http://127.0.0.1:8000",
"scope": "openid api offline_access" }

new AuthFlow(config)

@twinklekumarp

This comment has been minimized.

Copy link

commented May 17, 2018

the example you showed is i think for AuthorizationCode flow, I am looking for AuthroizationWithProofKey flow. Moreover, what is openidUri?

@stupiduglyfool

This comment has been minimized.

Copy link
Author

commented May 18, 2018

What part of the my example makes you think it is for AuthorizationCode flow?

Flow = Flows.AuthorizationCodeWithProofKey,

opeiduri is the uri for your identity server.

The AuthFlow typescript sample is based on the electron example repository that goes along with this project that demonstrates how to do pkce with electron:

appauth-js-electron-sample

@glerchundi

This comment has been minimized.

Copy link

commented Aug 23, 2018

@tikurahul it would be more than interesting if you could update the library with a full example, do you have a ETA for this?

Thanks!

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Aug 24, 2018

@glerchundi Sorry have been swamped with other things the last couple of weeks. I am going to try to get to this soon.

@glerchundi

This comment has been minimized.

Copy link

commented Sep 1, 2018

@mraible

This comment has been minimized.

Copy link

commented Sep 17, 2018

Hello everyone! I published a blog post today that shows how to use AppAuth-JS with PKCE. https://developer.okta.com/blog/2018/09/17/desktop-app-electron-authentication

I use Okta as the IdP in this example, but it should work with anyone that supports PKCE. Thanks to everyone who posted code in this thread, it helped a lot!

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Sep 17, 2018

The article looks great. Also support for PKCE is coming out of the box very soon. 😀

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Sep 18, 2018

OOTB support for PKCE is here. (#79). Marking this as fixed.

@tikurahul tikurahul closed this Sep 18, 2018

@aberasarte

This comment has been minimized.

Copy link
Contributor

commented Sep 19, 2018

This is great! thanks @tikurahul

@tikurahul

This comment has been minimized.

Copy link
Collaborator

commented Sep 19, 2018

For PKCE the interesting bits are:

This is called by the AuthorizationRequestHandler implementations when toJson() or setupCodeVerifier() is called on the AuthorizationRequest. Notice both return Promise's.


Full end to end examples are at:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants
You can’t perform that action at this time.