Background: a traditional webapp with a server backend and 3rd party sign in. For this we get a validated id_token
on our backend from the 3rd party, use that to identify an account in our system, and issue our own session cookie. We don't need access or refresh tokens from the 3rd party, and the front end doesn't need to see the id_token
.
We are adding a new identity provider (Apple), and we have the option of using either:
- Authorization code flow (without PKCE) & token exchange on backend using client secret
- Implicit flow with
response_mode=form_post
, no token exchange, and we validate theid_token
&nonce
The implicit flow seems as secure & more straightforward. Is there any reason I should use the code flow instead?
Note: Apple does not support PKCE. They also don't support the implicit flow, just the code & hybrid flows. Thus we would be using the hybrid flow here but ignoring the code
, so treating it as if it's an implicit flow. Sorry, it's confusing.
Example
GET /authorize
?response_type=code id_token
&response_mode=form_post
&redirect_uri=my_url
&state=the_state
&nonce=the_nonce
&scope=...
&client_id=...
The callback sends the token directly to my backend
POST my_url
?id_token=the_token
&code=ignored_code
&state=the_state
Additional information
Most recommendations I've found seem to recommend the authorization code flow with PKCE as being the most secure option because it keeps the tokens out of the url & browser history. However my understanding is that form_post
also accomplishes that in a simpler way (assuming that you have a backend to process the request & use a nonce). Furthermore, I suspect because form_post
is not universally applicable like code flow + pkce, that it is not discussed much, aside from these links I found:
- Auth0 suggests using
implicit
+form_post
flow is a good option
This way you can have an optimized authentication flow (no need to exchange the code for an ID Token)
- Mention of form post being simpler from openid foundation:
To aid the implementation of the best practice, we recommend that OPs consider supporting OAuth 2.0 Form Post Response Mode, as it makes it simpler for clients doing code id_token to get both the code and the ID Token on the backend for verification.
- In this draft document about OAuth security topics, using
form_post
is suggested a few times as a mitigation for some attacks. But in general it strongly recommends code flow with PKCE. - But if PKCE is not available, it doesn't mention what the next best thing is..
- Specification for form post response mode
state
should be used to carry a nonce/one-time use token to defend against CSRF. (PKCE helps with more than just CSRF, yes) and the client (your app) should verify it. The BCP mentions this.