No More Secrets: Using PKCE in OAuth for your JavaScript apps
Tags: development, authentication, security, web
Published: 2021-04-07 22:28:25

---
title: No More Secrets: Using PKCE in OAuth for your JavaScript apps
published: true
date: 2021-04-07 22:17:25 UTC
tags: development,authentication,security,web
canonical_url: https://craignicol.wordpress.com/2021/04/07/no-more-secrets-using-pkce-in-oauth-for-your-javascript-apps/
cover_image: https://craignicol.files.wordpress.com/2019/04/december-15-2018-at-0725pm.jpg
---

_Thanks to everyone who came to Scottish Developers to see myself and Christos talking about identity. If you missed it, be sure to [watch again on YouTube](https://youtu.be/UXP6uLMIi5o). Many thanks to Carole and Andrew for getting Scottish Developers back and running again._

{%youtube UXP6uLMIi5o %}

<iframe width="580" height="327" src="https://www.youtube.com/embed/UXP6uLMIi5o?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en&amp;autohide=2&amp;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

_If you want to [review the slides, they’re available here](https://craignicol.github.io/presentations/no-more-secrets/no-more-secrets.html#1) – if you want to use them yourself, please let me know._

> Don’t share secrets in your SPA. Use PKCE instead.
> 
> [Tweet](http://twitter.com/share?&text=%3Ci%3E%20%3C%2Fi%3EDon't%20share%20secrets%20in%20your%20SPA.%20Use%20PKCE%20instead.&url=https://craignicol.wordpress.com/2021/04/07/no-more-secrets-using-pkce-in-oauth-for-your-javascript-apps/&via=craignicol)

During the session, a few questions came up that I want to put here for the permanent record.

## _Pop-up vs redirect flow_

If you were watching myself and Christos closely, you may have noticed that I was using the redirect flow in my examples, whereas Christos, and most of the Microsoft examples, use the pop-up flow.

The key difference here is that the pop-up flow leaves the app intact, does the auth in a separate window, then returns the token to the app from JavaScript. The redirect flow leaves the app, does the login, then redirects back to the app.

The popup flow is thus easier to develop and work with, but it doesn’t work on browsers with strict pop-up settings. I’ve had to change Firefox to get it working, and I’ve never seen it work reliably with an iOS or Android browser. If you need to support IE, MSAL will fallback to redirect flow anyway.

To get the redirect flow to work reliably, you need to be able to restore state when your app gets reloaded. The best way to do this will depend on your app, but common methods would be to persist state (or just current route) in localStorage if there’s nothing sensitive, or pass the current route/state as a data parameter to the login call, and this will be returned to your callback URL, for you to handle appropriately.

## Storing Access Tokens

Access Tokens are your secrets. Treat them as securely as passwords. Don’t use local storage for access tokens.

> DON’T USE LOCAL STORAGE. DON’T USE LOCAL STORAGE.

Best option is to keep them in memory, and rely on the browser process sandboxing to keep the secret safe.

As Christos mentioned, if you use the MSAL library, it has its own credential cache that will handle this for you.

## Passwordless login

If you can, definitely prefer passwordless login. Chances are your website, or your intranet, isn’t important enough to your users for them to create a unique, secure password. Azure AD supports passwordless as well as 2FA and Hardware auth (including biometric on supported devices).

[Auth0 supports passwordless login too](https://auth0.com/passwordless)

## More technical details

- [View the PKCE spec here](https://oauth.net/2/pkce/) 
- [Auth0 writeup on the PKCE flow](https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce) 
- [Auth0 writeup on building a client, if you can’t use an existing library](https://auth0.com/docs/flows/add-login-using-the-authorization-code-flow-with-pkce) 

## Is there a use case for server-side secrets?

Yes. For backend services that don’t have an interactive login (such as timer-based jobs), and can keep the secret secure. However, where a service supports it, please use the Managed Principle approach as shown by Christos. If the service never knows the password, it cannot lose it. Let the identity provider grant trusted access on demand.

Where there is an interactive component, the OAuth flow allows the user to verify and control access to whichever subset of their data they choose.