Internet-Draft | Native OAuth App2App | July 2025 |
Zehavi | Expires 1 February 2026 | [Page] |
This document describes a protocol allowing a Client App to obtain an OAuth grant from a Native App using the [App2App] pattern, providing native app navigation user-experience (no web browser required), despite both apps residing on different 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:[email protected]), 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 1 February 2026.¶
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.¶
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.¶
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.¶
An Authorization Server federating to other trust domains by acting as an OAuth Client of Downstream Authorization Servers.¶
A Native app acting as client of Initial Authorization Server. In accordance with "OAuth 2.0 for Native Apps" [RFC8252], Client's redirect_uri is claimed by the app.¶
Authorization Server of Client App. As an OAuth Broker it is a client of Downstream Authorization Servers, to which it federates requests.¶
An Authorization Server downstream of Initial Authorization Server. It may be an OAuth Broker or the User-Interacting Authorization Server.¶
An Authorization Server which interacts with end-user. The interaction may be interim navigation (e.g: user input is required to guide where to redirect), or performs user authentication and request 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.¶
This document, OAuth 2.0 App2App Browser-less Flow, describes a protocol enabling native (Browser-less) app navigation of an [App2App] OAuth grant across different Trust Domains.¶
When Clients and Authorization Servers are located on different Trust Domains, authorization requests are routedusing federation, involving Authorization Servers acting as clients of Downstream Authorization Servers.¶
Such federation setups create trust networks, for example in Academia and in the business world across corporations.¶
However in [App2App] scenarios the web browser must serve as user-agent, because federating Authorization Servers url's are not claimed by any native app.¶
The use of web browsers in App2App flows, degrades the user experience somewhat.¶
This document specifies:¶
A Native App2App Profile Authorization Servers SHOULD follow to support browser-less App2App flows.¶
A new Authorization Server metadata property: native_authorization_endpoint, indicating an Authorization Server supports the Native App2App Profile.¶
A new [RFC9396] Authorization Details Type: https://scheme.example.org/native_callback_uri.¶
A new error code value: native_app2app_unsupported¶
Since no native app claims the urls of redirecting Authorization Servers (OAuth Brokers), mobile Operating Systems default to using the system 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.¶
Browsers may prompt end-user for consent before opening apps claiming deep links, introducing additional friction.¶
Browsers are noticeable by end-users, rendering the UX less smooth.¶
Client app developers don't control which browser the User-Interacting App uses to provide its response to redirect_uri. Opinionated choices pose a risk that different browsers will use, making necessary cookies used to bind session identifiers to the user agent (nonce, state or PKCE verifier) unavailable, which may break the flow.¶
After flow completion, "orphan" browser tabs may remain. They do not directly impact the flow, but can be regarded as unnecessary "clutter".¶
[OpenID.Native-SSO] also offers a native SSO flow across apps. However, it is limited to apps:¶
[OAuth.First-Party] also deals with native apps, but it MUST only be used by first-party applications, which is when the authorization server and application are controlled by the same entity, which is not true in the case described in this document.¶
While this document also discusses a mechanism for Authorization Servers to guide Client App in obtaining user's input to guide routing the request across trust domains, the [OAuth.First-Party] required high degree of trust between the authorization server and the client is not fulfilled.¶
(1) Client App presents an authorization request to Authorization Server's native_authorization_endpoint, including the native_callback_uri Authorization Details Type.¶
(2) Authorization Server returns either a native authorization request url for Downstream Authorization Server which includes the original native_callback_uri Authorization Details, or a Routing Instructions Response.¶
(3) Client App handles obtained Routing Instructions Response by prompting end-user and providing their response to Authorization Server, which then responds with a native authorization request url. Client App handles obtained native authorization request urls by seeking an app on the device claiming the url. If not found, Client App loops through invocations of obtained native authorization request urls, until a claimed url is reached.¶
(4) Once a claimed url is reached Client App natively invokes User-Interacting App.¶
(5) User-Interacting App authenticates end-user and authorizes the request.¶
(6) User-Interacting App natively invokes native_callback_uri, providing as a parameter a url-encoded redirect_uri with its response parameters.¶
(7) Client App invokes the obtained redirect_uri.¶
(8) Client App calls any subsequent uri obtained as 30x redirect directive, until it reaches a location header to its own redirect_uri.¶
(9) Client App exchanges code for tokens and the flow is complete.¶
This specification MUST NOT be used when Client App detects Initial Authorization Server's url is claimed by an app on the device.¶
In such case Client App SHOULD natively invoke the authorization request url.¶
Authorization servers providing a native_authorization_endpoint MUST follow the Native App2App Profile's requirements:¶
Accept the [RFC9396] Authorization Details Type: https://scheme.example.org/native_callback_uri.¶
Forward the Authorization Details Type to Downstream Authorization Servers.¶
Ensure Downstream Authorization Servers it federates to, support the Native App2App profile, otherwise return error=native_app2app_unsupported.¶
Redirect using HTTP 30x (avoid redirecting using HTTP Form Post or scripts embedded in HTML).¶
Avoid challenging end-user with bot-detection such as CAPTCHAs when invoked without cookies.¶
MAY provide Routing Instructions Response.¶
Authorization servers supporting the Native App2App profile, but requiring end-user input to guide request routing, MAY provide a Routing Instructions Response.¶
Example prompting end-user for multiple-choice:¶
HTTP/1.1 200 OK Content-Type: application/vnd.oauth.app2app.routing+json { "id": "request-identifier-1", "logo": "uri or base64-encoded logo of Authorization Server", "userPrompt": { "options": { "bank": { "title": "Bank", "description": "Choose your Bank", "values": { "bankOfSomething": { "name": "Bank of Something", "logo": "uri or base64-encoded logo" }, "firstBankOfCountry": { "name": "First Bank of Country", "logo": "uri or base64-encoded logo" } } }, "segment": { "title": "Customer Segment", "description": "Choose your Customer Segment", "values": { "retail": "Retail", "smb": "Small & Medium Businesses", "corporate": "Corporate", "ic": "Institutional Clients" } } } }, "response": { "post": "url to POST to using application/x-www-form-urlencoded", "get": "url to use for a GET with query params" } }¶
Example prompting end-user for input entry:¶
HTTP/1.1 200 OK Content-Type: application/vnd.oauth.app2app.routing+json { "id": "request-identifier-2", "logo": "uri or base64-encoded logo of Authorization Server", "userPrompt": { "inputs": { "email": { "hint": "Enter your email address", "title": "E-Mail", "description": "Lore Ipsum" } } }, "response": { "post": "url to POST to using application/x-www-form-urlencoded", "get": "url to use for a GET with query params" } }¶
logo is OPTIONAL and used to brand the interaction and represent the Authorization Server.¶
userPrompt MUST specify at least options or inputs and MAY specify both.¶
options specifies 1..n multiple-choice prompts.¶
inputs specifies free-form input.¶
Client App provides end-user's input using response which specifies HTTP GET or POST urls. If provided, Client App includes "id" as interaction identifier.¶
Example Client App response following end-user multiple-choice:¶
POST /native/routing HTTP/1.1 Host: example.as.com Content-Type: application/x-www-form-urlencoded id=request-identifier-1 &bank=bankOfSomething &segment=retail¶
Example Client App response following end-user input entry:¶
POST /native/routing HTTP/1.1 Host: example.as.com Content-Type: application/x-www-form-urlencoded id=request-identifier-2 &[email protected]¶
Client App SHALL terminate the protocol flow if it obtains:¶
An error response.¶
Or an HTTP 2xx response other than a Routing Instructions Response.¶
A Routing Instructions Response, in case Client App does not support it.¶
If a Routing Instructions Response was obtained and is supported, Client App interacts with end-user and provides their response to Authorization Server.¶
If an HTTP 30x redirect response was obtained, Client App SHALL use OS SDK's to locate an app claiming the url in the Location header, and if found SHALL natively invoke it to process the native authorization request.¶
If a suitable app is not found, Client App SHALL use HTTP to call the authorization request url and process the response as described herein.¶
Client App repeats these actions until a native app is reached, or an error occurs.¶
As the Client App performs HTTP calls, it SHALL maintain a list of all the DNS domains it interacts with, serving as an Allowlist for later invocations as part of the response handling.¶
As Authorization Servers MAY use Cookies to bind security elements (state, nonce, PKCE) to the user agent, causing the flow to break if required cookies are missing from subsequent HTTP requests, Client App MUST handle cookies:¶
Once Client App's own redirect_uri is reached, the traversal of Authorization Servers is complete and Client App proceeds to process the response:¶
The Native App2App flow described in this document MAY fail when:¶
An error response is obtained.¶
Client App doesn't support an obtained Routing Instructions Response.¶
An HTTP 2xx response other than a Routing Instructions Response is obtained.¶
In case of such failures, Client App MAY recover by launching a new (non-native) authorization request on a web browser, in accordance with "OAuth 2.0 for Native Apps" [RFC8252].¶
Note - Failure because an HTTP 2xx response, other than a Routing Instructions Response was obtained, suggests the User-Interacting App is not installed on end-user's device. Client App MAY choose in future to retry the Native App2App flow, to benefit if in the meantime the missing app has been installed.¶
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.¶
[RFC8252] Security Considerations advises against using embedded user agents. The main concern is preventing theft through keystroke recording of end-user's credentials such as usernames and passwords.¶
This risk does not apply to this draft as Client App acts as User Agent only for the purpose of flow redirection, and does not interact with end-user's credentials in any way.¶
The mechanism for providing routing instructions MUST NOT be used to request end-user to provide any authentication credentials.¶
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: George Fletcher, Arndt Schwenkschuster, 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.¶
[[ To be removed from the final specification ]]¶
-latest * removed error native_callback_uri_not_claimed * Added Routing Instructions Response * Added native_authorization_endpoint and matching AS profile * Added Authorization Details Type as container for native_callback_uri¶
-04¶
Phrased the challenge in Trust Domain terminology¶
Discussed interim Authorization Server interacting the end-user, which is not the User-Authenticating Authorization Server¶
Moved Cookies topic to Protocol Flow¶
Mentioned that Authorization Servers redirecting not through HTTP 30x force the use of a browser¶
Discussed Embedded user agents security consideration¶
-03¶
-02¶
-01¶
-00¶
initial working group version (previously draft-zehavi-oauth-app2app-browserless)¶