OAuth + SPA (Single Page Apps) Can We Just Use Code Flow Everywhere
OAuth + SPA (Single Page Apps) Can We Just Use Code Flow Everywhere
Tuesday 5H
Convener: David Waite
Notes-taker: David Waite
Tags for the session - technology discussed/ideas considered:
OAuth, SPA, Implicit, Code
Discussion notes, key understandings, outstanding questions, observations, and, if appropriate to this discussion: action items, next steps:
My motivation for hosting this session was that I have started to recommend customers avoid the implicit flow and use code flow for Single Page Apps (SPAs). I wanted to get feedback from the community at large, and get head nods (or objects thrown).
I started out by covering the reasons suspected for implicit flow:
- Avoiding an extra API call
- CORS (for allowing cross-domain API calls) not widely available in 2012 when OAuth was standardized
- Avoiding code leakage in URL for redirects, which can cause codes to be captured in browser history, potentially in referrer headers, and in server logs
- Fragment identifiers in URLs are modifiale by javascript without refreshing the page, allowing the code to be stripped after processing without redirecting
- Lack of faith in browser javascript to protect tokens
- Simplicity for clients, no refresh token
- Became the de facto “public client” flow
John Bradley commented that the primary motivator was client simplicity for connecting to large providers - a client redirect results in a token being sent back directly.
The consequences of implicit have been:
- lack of refresh tokens can lead to needing a different behavior for refreshing a session than for establishing a session (hidden iframe vs browser redirect), requiring duplication of oauth code
- Difficulty in refreshing token can cause an Authorization Server to implement different access token policy lifetimes for implicit clients, creating an entirely new policy requiring security considerations
- Browser behavior carries fragments on redirects, a relatively unknown behavior which causes token leakage if not handled
- With OpenID Connect, signed JWTs must be cryptographically verified to be secure in the implicit flow. While verifying the tokens over code is more secure, there is a baseline level of security just from receiving the token over the TLS channel for the code flow.
- Single page application may be wrapped via a framework like PhoneGap/Cordova into a native application. We have recommendations (BCP22) for native apps which recommend using code flow. This means that a common codebase may require implementing both flows for meeting all their deployment needs.
The room was pretty much unanimously in favor of recommending against use of implicit, with some concerns about technology issues and spec changes. The big changes since OAuth2 was published in 2012 were:
- BCP 22, native apps, pointing out to implementors that code flow does not require a client secret, and actively pushing for support of code flow without secrets
- Widespread CORS (cross origin resource sharing) support in browsers, allowing the code endpoint to be hit without significant implementation changes by an AS
- Content-Security-Policy and other mechanisms for isolating running javascript and limiting sources of javascript, allowing much greater protections from running arbitrary scripts
- PKCE, which allows a server to verify that a token request was made by the same client instance as an authorization request, limiting the ability to use a leaked code
- For clients which want to use fragments, OpenID connect added a response_mode=fragment which allows code to be sent via a fragment rather than a query parameter
John Bradley remarked on the last point that one justification for the multiple response specification was to allow an id_token to be returned immediately on the front channel, before the code was retrieved. This allows a client to immediately attempt to extract some information from the id_token to reduce perceived latency in the authentication/authorization process.
The speaker offered to help John in efforts to push for a best current practice (BCP) document which informed single page applications to use code flow vs implicit flow.