Internet-Draft | Native OAuth App2App | June 2025 |
Zehavi | Expires 27 December 2025 | [Page] |
This document describes a protocol connecting 2 native apps via the OAuth [App2App] pattern, to achieve native user navigation (no web browser required), regardless of any number of OAuth brokers federating the request across trust domains.¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://yaron-zehavi.github.io/oauth-app2app-browserless/draft-zehavi-oauth-app2app-browserless.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-zehavi-oauth-app2app-browserless/.¶
Discussion of this document takes place on the Web Authorization Protocol Working Group mailing list (mailto:oauth@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/oauth/. Subscribe at https://www.ietf.org/mailman/listinfo/oauth/.¶
Source for this draft and an issue tracker can be found at https://github.com/yaron-zehavi/oauth-app2app-browserless.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 27 December 2025.¶
Copyright (c) 2025 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
This document, OAuth 2.0 App2App Browserless Flow (Native App2App), presents a protocol enabling native OAuth [App2App] browser-less navigation across apps.¶
It addresses the challenges presented when using a web browser to navigate through one or more Brokering Authorization Servers:¶
Such OAuth Brokers are required when Client App is not an OAuth client of the User-Interacting Authorization Server and so they federate the flow across trust domains.¶
Since no app owns OAuth Brokers' urls, App2App flows involving brokers require a web browser, which degrades the user experience.¶
This document specifies:¶
A new parameter to the authorization endpoint: native_callback_uri.¶
A new scope value: app2app.¶
A new error_description value: native_callback_uri_not_claimed.¶
[OpenID.Native-SSO] also offers a native SSO flow across apps. However, it is limited to apps:¶
In addition to the terms defined in referenced specifications, this document uses the following terms:¶
In this document, "OAuth" refers to OAuth 2.0, [RFC6749] and [RFC6750] as well as [OpenID], both in their authorization code flow.¶
Proof Key for Code Exchange (PKCE) [RFC7636], a mechanism to prevent various attacks on OAuth authorization codes.¶
A component acting as an Authorization Server for its clients, as well as an OAuth Client towards Downstream Authorization Servers. Brokers are used to facilitate a trust relationship when there is no direct relation between an OAuth Client and the final Authorization Server where end-user authenticates and authorizes. This pattern is in current use to establish trust in federation use cases in Academia and in the business world, across corporations. Note: It is possible OAuth Brokers will be superseded in the future by [OpenID.Federation], offering dynamic trust establishment.¶
A Native app implementing "OAuth 2.0 for Native Apps" [RFC8252] as an OAuth client of Initial Authorization Server. Client's redirect_uri is claimed by the app.¶
The Authorization Server of Client App which acts as an OAuth Broker as an OAuth client of a Downstream Authorization Server.¶
An Authorization Server which may be an OAuth Broker or a User-Interacting Authorization Server.¶
The Authorization Server which interacts with end-user to perform authentication and authorization.¶
Native App of User-Interacting Authorization Server.¶
A url claimed by a native application.¶
Client App's redirect_uri, claimed as a deep link. This deep link is invoked by User-Interacting App to natively return to Client App.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
Since no native app claims OAuth Brokers' urls, OAuth requests and redirect_uri responses to and from OAuth Brokers are handled by a web browser as the User Agent.¶
Using a web browser may degrade the user experience in several ways:¶
Some browser's support for deep links is limited by design, or by the settings used.¶
The browser may prompt end-user for consent before opening deep links, introducing additional friction.¶
Browser's loading of urls and redirecting may be noticeable by end-user, rendering the UX less smooth.¶
App developers cannot control which browser will handle the response redirect_uri. This poses a risk that necessary cookies used to bind session identifiers to the user agent (nonce, state or PKCE verifier) will be unavailable, which may break the flow.¶
After the flow is complete, "orphan" browser tabs might remain. While they do not directly impact the flow, they can be regarded as unnecessary "clutter".¶
End-user's device may not have an app claiming User-Interacting Authorization Server's urls, when:¶
User-Interacting Authorization Server offers no native app.¶
Or such an app is offered, but is not installed on the end-user's device.¶
In such case interacting with User-Interacting Authorization Server's MUST use the browser as user agent. This is similar to the flow described in "OAuth 2.0 for Native Apps" [RFC8252], and referred to in [App2App] as App2Web, and is therefore not discussed further in this document.¶
(1) Client App presents an authorization request to Initial Authorization Server, indicating app2app flow using new scope value app2app.¶
(2) Initial Authorization Server returns an authorization request for Downstream Authorization Server, including Client App's redirect_uri as native_callback_uri.¶
(3) Client App checks if the returned authorization request url is claimed by an app on the device and if so proceeds to the next step. Otherwise it loops through Downstream Authorization Servers, calling their authorization endpoints and processing their HTTP 3xx redirect responses, until a url claimed by an app on the device is reached.¶
(4) Client App natively invokes User-Interacting App.¶
(5) User-Interacting App authenticates user and authorizes the request.¶
(6) User-Interacting App natively invokes native_callback_uri (overriding the request's redirect_uri), providing as a parameter the redirect_uri with its response parameters.¶
(7) Client App loops through Authorization Servers in reverse order, starting from the redirect_uri it received from the User-Interacting App. It calls the first redirect_uri and any subsequent uri obtained as 3xx redirect directive, until it obtains a location header indicating its own redirect_uri.¶
(8) Client App exchanges code for tokens and the flow is complete.¶
The protocol described in this document requires User-Interacting App to natively navigate end-user back to Client App, for which it requires Client App's native_callback_uri.¶
Therefore this document defines new parameters and values.¶
New scope value, used by Client App to request an app2app flow from Initial Authorization Server.¶
Initial Authorization Server, processing an app2app flow according to this document, MUST provide Client App's redirect_uri as Native Callback uri to Downstream Authorization Server using one of the following options:¶
OPTIONAL. New authorization endpoint request parameter. When native_callback_uri is provided, structured scope app2app:native_callback_uri MUST NOT be provided.¶
OPTIONAL. New structured scope value including the app2app flag as well as the Client's native_callback_uri, separated by a colon. When structured scope app2app:{native_callback_uri} is provided, native_callback_uri MUST NOT be provided.¶
native_callback_uri accepts the following query parameter when invoked by User-Interacting Authorization Server's App:¶
url-encoded OAuth redirect_uri with its response parameters.¶
Downstream Authorization Server, processing an app2app flow according to this document:¶
Validation of native_callback_uri by User-Interacting Authorization Server and its App is RECOMMENDED, to mitiagte open redirection attacks.¶
A validating Authorization Server MAY use various mechanisms outside the scope of this document. For example, validation using [OpenID.Federation] is possible:¶
Client App is natively invoked by User-Interacting Authorization Server App, with the request's redirect_uri.¶
Client App MUST validate this url, and any url subsequently obtained via a 3xx redirect instruction, against the Allowlist it previously generated, and MUST fail if any url is not included in the Allowlist.¶
Client App SHALL invoke the url it received using HTTP GET:¶
Once Client App's own redirect_uri is returned in a redirect 3xx directive, the traversal of OAuth Brokers is complete.¶
Client App SHALL proceed according to OAuth to exchange code for tokens, or handle error responses.¶
Native Apps on iOS and Android MAY use OS SDK's to detect if an app owns a url. The general method is the same - App calls an SDK to open the url as deep link and handles an exception thrown if no matching app is found.¶
App SHALL invoke Android [android.method.intent] method with FLAG_ACTIVITY_REQUIRE_NON_BROWSER, which throws ActivityNotFoundException if no matching app is found.¶
App SHALL invoke iOS [iOS.method.openUrl] method with options [iOS.option.universalLinksOnly] which ensures URLs must be universal links and have an app configured to open them. Otherwise the method returns false in completion.success¶
It is RECOMMENDED that Client App acts as a confidential OAuth client.¶
If Client App uses a Backend it is RECOMMENDED to communicate with it securely:¶
It is RECOMMENDED that all apps in this specification shall use https-scheme deep links (Android App Links / iOS universal links). Apps SHOULD implement the most specific package identifiers mitigating deep link hijacking by malicious apps.¶
Client App SHALL construct an Allowlist of DNS domains it traverses while processing the request, used to enforce all urls it later traverses during response processing. This mitigates open redirection attacks as urls not in this Allowlist SHALL be rejected.¶
In addition Client App MUST ignore any invocation for response processing which is not in the context of a request it initiated. It is RECOMMENDED the Allowlist be managed as a single-use object, destructed after each protocol flow ends.¶
It is RECOMMENDED Client App allows only one OAuth request processing at a time.¶
This document has no IANA actions.¶
The authors would like to thank the following individuals who contributed ideas, feedback, and wording that shaped and formed the final specification: Henrik Kroll, Grese Hyseni. As well as the attendees of the OAuth Security Workshop 2025 session in which this topic was discussed for their ideas and feedback.¶