When I read the oauth 2.0 flows, the user-agent flow states itself to be used when the application is unable to protect the secret.

But in the user-agent flow it is okay to have a refresh token which can last very long - even indefinitely based on settings. How come it is okay for the user-agent to keep that refresh token?

And also, what is the major difference between a refresh token and an authentication code? I know this might sound stupid, but to me, it seems both of them can be used to apply for access token?


TL;DR - It's not okay, don't use it. Instead, go with the authorization code grant type (aka Web Server flow in Salesforce world).

Full story:

The user-agent flow in Salesforce is based on oAuth implicit grant type with one difference - refresh token.

You only get the refresh token if you ask for it explicitly with scope = refresh_token and your flow meets other documented constraints such as custom protocol on the callback URL. This is a Salesforce "extension", it is not compliant with implicit grant type in oAuth spec. If memory serves, it was created by SF for mobile apps a while ago. While some might still be using it, it's more or less a legacy option as of now.

Even if you don't ask for a refresh token and use spec-compliant implicit grant type (which is possible via User-Agent in Salesforce), this option is no longer recommended. From oAuth Security Best Current Practice (BCP):

The implicit grant (response type "token") and other response types causing the authorization server to issue access tokens in the authorization response are vulnerable to access token leakage and access token replay

...and another relevant note in oAuth Browser-based Apps BCP:

9.8.4. Historic Note

Historically, the Implicit flow provided an advantage to single-page apps since JavaScript could always arbitrarily read and manipulate the fragment portion of the URL without triggering a page reload. This was necessary in order to remove the access token from the URL after it was obtained by the app.

Modern browsers now have the Session History API which provides a
mechanism to modify the path and query string component of the URL
without triggering a page reload. This means modern browser-based
apps can use the unmodified OAuth 2.0 authorization code flow, since
they have the ability to remove the authorization code from the query string without triggering a page reload thanks to the Session History API.

The oAuth Security BCP goes on to say you might be able to use it if you mitigate certain issues. Salesforce helps you with some of these issues by e.g. enforcing same-origin on user agent. Still, the threat model is extensive and mitigation strategies are fragile. Thus, the authorization code grant with PKCE is the recommended way to go nowadays for any public client, native mobile or browser-based. See oAuth 2.1 draft for updated guidance. (The language in 2.1 is not "law" since it's still a draft but aside from brand new 2.1 stuff, the rest of it applies wholesale to any oAuth 2.0 solution).

Now let's look at the recommended option - authorization code grant (aka Web Server flow in Salesforce). In this flow there are 3 types of tokens or codes being used:

An authorization code is a credential representing the resource owner's authorization (to access its protected resources) used by the client to obtain an access token. It's an intermediary construct in the authorization flow sequence, you don't need to "manage" it in your application.

Access tokens are credentials used to access protected resources. Example of a protected resource is a REST API exposed by Salesforce.

Refresh tokens are credentials used to obtain access tokens. Refresh tokens are issued to the client by the authorization server and are used to obtain a new access token when the current access token becomes invalid or expires.

See oAuth 2.0 spec (RFC 6749) for more details on these.

The term authentication code is ambiguous, it probably refers to authorization code in the flow above.

  • Thank you for your response. But I kind of disagree with you in this case. I do agree that implicit sharing is suboptimal in oauth 2.0 in general, but user-agent is kind of implicit sharing model and kind of not since it has some of its own kind of verification like single origin. On the contrast, User agent flow is one of the most frequently used flow in Salesforce. But thank you for the detailed response though – Lance Shi Aug 15 '19 at 4:59
  • Plus, I would say Salesforce recommends using Web server flow only if the web server is capable to protecting the secret, which means in most cases this is not applicable. – Lance Shi Aug 15 '19 at 5:02
  • 1. user-agent is kind of implicit sharing - if you cut out the refresh token extension, it is exactly like implicit grant in the oAuth spec. The same-origin verification is a countermeasure, it doesn't affect oAuth messages, so no, it's not "kind of not". This countermeasure is hardly enough to protect against documented attacks, see the extensive link above for more details. – identigral Aug 15 '19 at 5:27
  • Regarding the Web Server flow, SF doc's terminology is confusing. If your app is a standard webapp that is reachable via HTTP, that's a "web server". The assumption is that if your app lives on the server, it can protect a secret. This is the most common scenario. Authorization code grant in oAuth and associated threat model do not assume that all apps are webapps. For, say, a native mobile app, protecting a secret would be tough. That's why the secret is optional in authorization grant type, the connected app in SF allows you to make it required. – identigral Aug 15 '19 at 5:46
  • This is the paragraph I copied from Salesforce Doc: These apps can protect per-user secrets. But, because the apps are widely distributed, the client secret can’t be confidential. Authentication is based on the user-agent’s same-origin policy. This section is coming from User-agent flow. It seems to me that Salesforce is not recommending Web-server flow in this widely distributed scenario though. Although I kind of agree with you that User-Agent might still be insecure in this case – Lance Shi Aug 15 '19 at 7:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.