Since PKCE is now the recommended method of authorisation over the implicit flow, I'm looking for best practice on handling code verifier and recommendations on how this might be done. On high level PKCE Authorisation flow consist of:
code_verifier
on client sidecode_challenge
from (1)/authorise
with code_challenge
which redirect to select idp and in callback there's a code
code
from (3) along with code_verifier
to exchange for access tokenQuestion is, in step 3, before the application redirect to authorisation server and then the idp, one has to store the code_verifier
somewhere. Where is that somewhere?
Seems like libraries like okta-oidc-js
store the code_verifier
in sessionStorage. Doesn't that expose you to XSS attack? i.e. if I was store the code_verifier
in sessionStorage before the application goes into the Authorisation flow and redirects, on the callback, what stops some rouge extension from reading the code
from the URL and code_verifier
from sessionStorage? Combination of which can be used to exchange for a access token.
What you describe is the standard SPA way of doing things - it could potentially be abused by malicious code, but there is some protection in the fact that an authorization code can only be used once and that the verifier is not stored for long.
A related XSS attack is to run a complete OAuth authorization redirect + code exchange on a hidden iframe - there is no protection against that, regardless of whether a back end or client secret is involved.
If you want to be strict about security, the emerging trend is more of a back end for front end approach, where the back end is a 'Proxy API' running at https://api.mywebdomain.com
The result of OAuth authorization is a same site cookie issued by the API, to prevent the above iframe attack
The SPA can then either use the auth cookie to get an access token or double hop API requests via the proxy API.
There is a good recent video on SPA security here that discusses these threats in further depth. The browser is a difficult place to implement security and redirects come with risks.
It is still recommended to separate Web and API concerns however - eg the above proxy API should not get in the way of a company wanting to deploy their SPA via a content delivery network.
LOGIN DANCE
In my opinion the preferred approach is summarized below, for full control and no issues with recent browser changes:
SPA calls a URL such as https://api.mywebdomain.com/login/start, which writes an HTTP only encrypted cookie for .mywebdomain.com containing the state and code_verifier, and also returns the authorization request URL
SPA then does the redirect itself, and saves page location / state to session storage beforehand if needed
SPA then receives the response URL with code and state, then POSTs them to a URL such as https://api.mywebdomain.com/login/end. Afterwards the SPA can restore its page location and state, so that usability is good.
API completes the login by verifying the state against that in the state cookie, then using the code_verifier from the state cookie. The result of all of this is to write an auth cookie (containing a refresh token) that could not be abused on an iframe.