Last year I wrote about an IETF draft describing best practices for implementation of OAuth 2.0 flows on native application. That draft just went RFC and is a must read for any mobile developer working in this subject. Also, check out client libraries for Android, iOS and .NET.
Tag Archives: oauth
OAuth 2.0 library for .NET native apps
A few months ago I wrote about OAuth 2.0 for native apps, mentioning App Auth, an OAuth 2.0 client library for native Android and iOS applications. Recently I discovered that a similar library has been release for .NET! It is a PCL (Xamarin included) and it features the same security concerns as App Auth, following the IETF recommendations for native OAuth 2.0 clients. In addition, it also supports OpenId Connect features, such as validating identity tokens. Very nice!
OAuth 2.0 mind map
Since the publication of The OAuth 2.0 Authorization Framework (RFC 6749) in 2012, both the IETF OAuth work group and the OpenID Foundation have released many other RFCs that extend/complement the base framework and the OAuth 2.0 ecosystem. I found this variety a bit confusing, so I figured I’d do a mind map and short summary of the specs for future reference. Here it goes.
RFC 6749 – The OAuth 2.0 Authorization Framework
This is the core OAuth 2.0 standard. It defines the different roles (resource owner, client, authorization server, etc.) and the main authorization endpoints, flows and artifacts. Extensibility rules are also defined in this document. The “framework” on the RFC title is important: there are multiple authorization scenarios and a lot of aspects are left unspecified, which somehow justifies all the satellite specs. This was also the reason for heavy criticism on the early days of OAuth 2.0.
RFC 6750 – Bearer Token Usage
The main spec doesn’t define the format of access tokens nor how they should be used to access protected resources. The most commonly deployed tokens, however, are bearer tokens. As the name implies, the possession of such tokens is sufficient to access the associated resources. RFC 6750 defines how bearer tokens should be sent to resource servers.
RFC 7009 – Token Revocation
Authorization servers usually allow resource owners to revoke previously granted authorizations. This RFC proposes an additional endpoint for authorization servers that clients can use to invalidate tokens they no longer need.
RFC 7662 – Token Introspection
The main spec doesn’t cover the actual usage of access tokens nor the procedure that resource servers should apply to verify them. More than verifying if a token is valid, resource servers are likely to need the associated metadata (e.g. the granted scopes) for authorization decisions. In a common deployment scenario, both authorization and resource servers are under the same domain, hence being able to somehow share the token validation logic. For more loose scenarios, RFC 7662 defines a token introspection endpoint that resource servers may use to query the authorization server to obtain the status and metadata of a token that is presented by an OAuth 2.0 client.
RFC 7519 – JSON Web Token (JWT)
“JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object.” JWTs can be used with JSON Web Signature (JWS) and JSON Web Encryption (JWE), enabling the claims to be integrity protected and/or encrypted. The spec includes a set of predefined claims – such as the issuer, subject and audience identifiers – as well as processing rules. JWTs can be used as self-contained access/refresh tokens.
More on obtaining authorization grants
RFC 7636 – Proof Key for Code Exchange by OAuth Public Clients (PKCE)
Clients that can’t keep their credentials private are called public clients. This is the case of most native applications. As such, the authorization code grant cannot be securely used by this type of clients. This spec defines a proof of possession extension that makes the code grant usable by these clients. Read this post for more details on PKCE and the underlying vulnerability.
Device Flow (draft)
Defines an authorization flow for clients executing on devices with limited input and/or browsing capabilities (e.g. TVs, STBs). It is based on out-of-band codes that the user provides to the authorization server using another device with better user-agent capabilities (e.g. a tablet).
Multiple Response Type Encoding Practices
Defines rules to encode authorization response parameters when multiple response types are used. Also defines response mode, a new authorization request parameter that allows the client to specify how the response should be delivered (query-string, fragment, etc.).
Form Post Response Mode
Based on the previous spec, this document defines a new response mode on which the authorization response is returned to the client via a auto-submit HTML form using an HTTP POST. This is different from the redirects (HTTP GET) defined on the core OAuth spec, with the advantage of reducing the likelihood of codes and tokens being logged as part of URLs.
RFC 7591 – Dynamic Client Registration Protocol
Clients are usually registered by their developers in the intended authorization servers. This spec defines a means of dynamically registering clients Registration requests include items such as redirect URIs, intended grant types and web page URLs, and the response contains the assigned client ID and secret. There’s also a complementary experimental spec for subsequent changes to the client metadata.
Authorization Server Discovery Metadata (draft)
This draft defines the format of a JSON document that a client can use to obtain the different endpoints and capabilities of an authorization server. This metadata includes items such as the URL of the token endpoint and the supported response types. Besides this draft there’s also the OpenID Connect version, which is final and actually appeared first. The draft is compatible with the later.
Other types of authorization grants
RFC 7521 – Assertion Framework for Client Authentication and Authorization Grants
Defines mechanisms for OAuth 2.0 to work with other identity systems using assertions. The spec defines processing rules and message flows for using assertion-based client authentication and authorization grants when interacting with the token endpoint. This means that authorization grants are obtained by other means, instead of using the common OAuth flows. There’s a profile using SAML 2.0 assertions and another using JWT assertions.
Informational & best practices
RFC 6819 – Threat Model and Security Considerations
Defines a set of threats to the authorization flows and the corresponding countermeasures. Since OAuth 2.0 doesn’t include any “message security” on the base flows, being aware of those security aspects is very important to ensure the protocols’ security.
OAuth 2.0 for Native Apps (draft)
Native clients – such as mobile applications – can’t keep their credentials private. This spec defines a set of best practices for implementing such clients, namely the usage of the device’s native browser for authorization flows. I’ve discussed this subject in detail on a previous post.
OpenID Connect Core 1.0
“OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol“. Actually it’s not that simple; it’s a whole new subject, but this post wouldn’t be complete without mentioning it. The spec defines extensions to OAuth 2.0 that enable clients to verify the identity of the user that authenticated on the authorization server.
OAuth 2.0 for native apps
When a native application needs access to a user’s account on a given online service, there are two main alternatives: 1) rely on accounts previously configured on the device; 2) interact directly with the online service to get the needed authorization. The former approach builds directly on features exposed by the OS and usually requires the app to have specific permissions. This is the case of Android’s AccountManager. The latter usually relies on some authorization protocol supported by the target service, which nowadays is likely to be OAuth 2.0. In this case the application will require some sort of user-agent to perform the authorization flow.
Google’s Identity team recently open sourced AppAuth for Android and iOS, a client library that enables native applications to perform OAuth 2.0 authorization flows in a secure and usable manner. AppAuth follows the recent IETF draft of best practices for authorization flows on native applications.
The OAuth 2.0 RFC already includes a section around native applications, reminding that these clients can’t keep their credentials confidential and providing two main approaches to perform the authorization flow: embedded user-agents and external user-agents (e.g. system default browser).
Embedded user-agents are usually a native component that the application directly communicates with. This is the case of WebViews in Android. Embedded user-agents are a very common option because they don’t require the user to switch context and there wasn’t a better approach to overcome this aspect (not anymore, as we’ll see later on). However, this approach has many usability and security drawbacks. Regarding usability, embedded user agents don’t share the authentication state with other apps or the system browser, meaning the user might have to re-authenticate. On the other hand, users are authenticating on an unidentified window without the usual browser features, which makes it harder for them to know if they are singing in to the legitimate site and educates them in the wrong way. Worst than that, the host application has access to the whole user-agent context, such as cookies and key strokes. Finally, since embedded user-agents are native components they might not be so easily updated as an external user-agent, which is likely to be just another application on the OS.
When using external user-agents, in order to perform an OAuth authorization request, an application needs to somehow activate the external browser. Most environments provide URI-based inter-app communication (e.g. Intent on Android) which fit OAuth 2.0, since authorization requests are HTTP URIs. In this case, the authorization flow is executed in the browser, which is registered on the OS as knowing how to handle HTTP URIs. The authentication state is shared, avoiding re-authentications, and the user faces a familiar experience and may rely on browser features for authentication (stored credentials, extensions, etc). In order to get the authorization response, the most common approach is to use custom schemes on OAuth redirect URIs. All the major platforms have support for binding custom URI schemes to applications. When the browser (on any other application) attempts to follow such an URI, the corresponding application is activated. This is how the last redirect on the authorization flow is delivered to the initiator.
The IETF draft of best practices for authorization flows on native applications adds some restrictions and recommendations for this scenario:
- Authorization flows should be delegated to external user-agents via URI-based communication. Embedded user-agents are not recommended.
- Whenever possible in-app browser tabs should be used. In-app browser tabs are provided by a browser in the system but displayed within the application with limited navigation capabilities. However, they cannot be directly accessed by the application and they share the browser’s authentication state and security features. On iOS this feature is available via SFSafariViewController and iOS 9+. On Android, the feature is available via Chrome Custom Tabs since Chrome 45 (Sep 2015) from Jellybean on. Both versions support some customization, such as changing the navigation bar color, adding custom share buttons and going back to the application in one tap..Note that this feature can be supported by other browsers installed on the devices. Also note that this feature is not restricted to authorization flows. In-app tabs are already used by some applications, such as Facebook and Twitter, to display generic external web content.
- Applications should use custom URI schemes that are globally unique for their redirect URIs. The recommend strategy is using the reverse domain name pattern applied to a domain under the application publisher control.
- Applications must use Proof Key for Code Exchange by OAuth Public Clients (PKCE) when using custom URI schemes. Since multiple applications might register the same custom scheme, the OS could activate a malicious application to receive the authorization response. PKCE “is a Proof of Possession extension to OAuth 2.0 that protects the code grant from being used if it is intercepted“. Read this post for more details on PKCE and the underlying vulnerability (applies to public clients, which is the case of most native applications).
The recently open sourced AppAuth library for Android and iOS was implemented with all these considerations in mind, so I think it’s worth mentioning. In addition, it supports custom extensions on OAuth requests and includes fallback to the default browser if a browser supporting custom tabs is not found. Seems to do all the plumbing to support a uniform and secure authorization experience.