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:

  1. Authorization code flow (without PKCE) & token exchange on backend using client secret
  2. Implicit flow with response_mode=form_post, no token exchange, and we validate the id_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.


GET /authorize
  ?response_type=code id_token

The callback sends the token directly to my backend

POST my_url

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)

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.

  • Without PKCE, 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.
    – identigral
    Aug 15, 2019 at 20:45

2 Answers 2


I don't see any security advantage of using the authorization code flow in your case (traditional web application). Indeed, form_post is not vulnerable to referrer leaking or browser history leaking. Posting tokens is nothing new, it's how SAML2, the predecessor of OpenID Connect, worked well without bringing in any specific security weaknesses.

And form_post indeed avoids one round-trip to the AS to authenticate the user. It's just that it cannot be used with javascript SPAs or mobile applications.

  • Why can't form_post be used with SPAs?
    – jmrah
    Jul 17, 2020 at 15:03
  • Because the tokens are sent to the backend, and not to the SPA i.e. the web page. With the query and fragment methods, the tokens are set in the URI which can be read by javascript.
    – Tangui
    Jul 17, 2020 at 15:26

Despite the additional round trip to the AS to exchange the code for an ID Token, the code flow has several security advantages over the Implicit or Hybrid Flow:

  1. The client / RP can be authenticated, since it is an confidential client and thus can be equipped with client credentials (asymmetric keys in the case of Apple). This is a security improvement, since the client credentials are necessary to redeem the code.
  2. The claims about the user can be obtained via UserInfo endpoint and don't need to be included in the ID Token, which has several advantages:
    • the ID Token can be much smaller
    • the ID Token is not necessarily exposed to the front channel (→ the end user’s browser)
    • in case the ID Token is provided in the id_token_hint parameter to request a specific user or in the RP-Initiated Logout, a smaller ID Token with less sensitive data is better
  3. If Apple only supports the Hybrid Flow and not the Implicit Flow, they might not include all claims about the user in the ID Token, since the client has the ability to use the Access Token to request them from the UserInfo endpoint. IdentityServer uses this behaviour.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .