What’s the right OAuth 2.0 flow for a mobile app

Clarification: Mobile App = Native App

As stated in other comments and a few sources online, implicit seems like a natural fit for mobile apps, however the best solution is not always clear cut (and in fact implicit is not recommended for reasons discussed below).

Native App OAuth2 Best Practises

Whatever approach you choose (there are a few trade offs to consider), you should pay attention to the best practices as outlined here for Native Apps using OAuth2: https://www.rfc-editor.org/rfc/rfc8252

Consider the following options

Implicit

Should I use implicit?

To quote from Section 8.2 https://www.rfc-editor.org/rfc/rfc8252#section-8.2

The OAuth 2.0 implicit grant authorization flow (defined in Section 4.2 of OAuth 2.0 [RFC6749]) generally works with the practice of performing the authorization request in the browser and receiving the authorization response via URI-based inter-app communication.
However, as the implicit flow cannot be protected by PKCE [RFC7636] (which is required in Section 8.1), the use of the Implicit Flow with native apps is NOT RECOMMENDED.

Access tokens granted via the implicit flow also cannot be refreshed without user interaction, making the authorization code grant flow —
which can issue refresh tokens — the more practical option for native app authorizations that require refreshing of access tokens.

Authorization Code

If you do go with Authorization Code, then one approach would be to proxy through your own web server component which enriches the token requests with the client secret to avoid storing it on the distributed app on devices.

Excerpt below from: https://dev.fitbit.com/docs/oauth2/

The Authorization Code Grant flow is recommended for applications that
have a web service. This flow requires server-to-server communication
using an application’s client secret.

Note: Never put your client secret in distributed code, such as apps
downloaded through an app store or client-side JavaScript.

Applications that do not have a web service should use the Implicit
Grant flow.

Conclusion

The final decision should factor in your desired user experience but also your appetite for risk after doing a proper risk assessment of your shortlisted approaches and better understanding the implications.

A great read is here https://auth0.com/blog/oauth-2-best-practices-for-native-apps/

Another one is https://www.oauth.com/oauth2-servers/oauth-native-apps/ which states

The current industry best practice is to use the Authorization Flow
while omitting the client secret, and to use an external user agent to
complete the flow. An external user agent is typically the device’s
native browser, (with a separate security domain from the native app,)
so that the app cannot access the cookie storage or inspect or modify
the page content inside the browser.

PKCE Consideration

You should also consider PKCE which is described here https://www.oauth.com/oauth2-servers/pkce/

Specifically, if you are also implementing the Authorization Server then https://www.oauth.com/oauth2-servers/oauth-native-apps/checklist-server-support-native-apps/ states that you should

  • Allow clients to register custom URL schemes for their redirect URLs.
  • Support loopback IP redirect URLs with arbitrary port numbers in order to support desktop apps.
  • Don’t assume native apps can keep a secret. Require all apps to declare whether they are public or confidential, and only issue client secrets to confidential apps.
  • Support the PKCE extension, and require that public clients use it.
  • Attempt to detect when the authorization interface is embedded in a native app’s web view, instead of launched in a system browser, and reject those requests.

Web Views Consideration

There are many examples in the wild using Web Views i.e. an embedded user-agent but this approach should be avoided (especially when the app is not first-party) and in some cases may result in you being banned from using an API as the excerpt below from here demonstrates

Any attempt to embed the OAuth 2.0 authentication page will result in
your application being banned from the Fitbit API.

For security consideration, the OAuth 2.0 authorization page must be
presented in a dedicated browser view. Fitbit users can only confirm
they are authenticating with the genuine Fitbit.com site if they have
the tools provided by the browser, such as the URL bar and Transport
Layer Security (TLS) certificate information.

For native applications, this means the authorization page must open
in the default browser. Native applications can use custom URL schemes
as redirect URIs to redirect the user back from the browser to the
application requesting permission.

iOS applications may use the SFSafariViewController class instead of
app switching to Safari. Use of the WKWebView or UIWebView class is
prohibited.

Android applications may use Chrome Custom Tabs instead of app
switching to the default browser. Use of WebView is prohibited.

To further clarify, here is a quote from this section of a previous draft of the best practise link provided above

Embedded user-agents, commonly implemented with web-views, are an
alternative method for authorizing native apps. They are however
unsafe for use by third-parties by definition. They involve the user
signing in with their full login credentials, only to have them
downscoped to less powerful OAuth credentials.

Even when used by trusted first-party apps, embedded user-agents
violate the principle of least privilege by obtaining more powerful
credentials than they need, potentially increasing the attack surface.

In typical web-view based implementations of embedded user-agents, the
host application can: log every keystroke entered in the form to
capture usernames and passwords; automatically submit forms and bypass
user-consent; copy session cookies and use them to perform
authenticated actions as the user.

Encouraging users to enter credentials in an embedded web-view without
the usual address bar and other identity features that browsers have
makes it impossible for the user to know if they are signing in to the
legitimate site, and even when they are, it trains them that it’s OK
to enter credentials without validating the site first.

Aside from the security concerns, web-views do not share the
authentication state with other apps or the system browser, requiring
the user to login for every authorization request and leading to a
poor user experience.

Due to the above, use of embedded user-agents is NOT RECOMMENDED,
except where a trusted first-party app acts as the external user-
agent for other apps, or provides single sign-on for multiple first-
party apps.

Authorization servers SHOULD consider taking steps to detect and block
logins via embedded user-agents that are not their own, where
possible.

Some interesting points are also raised here: https://security.stackexchange.com/questions/179756/why-are-developers-using-embedded-user-agents-for-3rd-party-auth-what-are-the-a

Leave a Comment