Internet-Draft | OAuth for First-Party Native Apps | July 2023 |
Parecki, et al. | Expires 8 January 2024 | [Page] |
This document defines the Authorization Challenge Endpoint, which supports a first-party native client that wants to control the process of obtaining authorization from the user using a native experience.¶
In many cases, this can provide an entirely browserless OAuth 2.0 experience suited for native applications, only delegating to the browser in unexpected, high risk, or error conditions.¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://aaronpk.github.io/oauth-first-party-native-apps/draft-parecki-oauth-first-party-native-apps.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-parecki-oauth-first-party-native-apps/.¶
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/aaronpk/oauth-first-party-native-apps.¶
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 8 January 2024.¶
Copyright (c) 2023 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 extends the OAuth 2.0 Authorization Framework [RFC6749] with
a new endpoint, authorization_challenge_endpoint
, to support first-party native
applications that want to control the process of obtaining authorization from
the user using a native experience.¶
The client collects any initial information from the user and POSTs that information as well as information about the client's request to the Authorization Challenge Endpoint, and receives either an authorization code or an error code in response. The error code may indicate that the client can continue to prompt the user for more information, or can indicate that the client needs to launch a browser to have the user complete the flow in a browser.¶
The Authorization Challenge Endpoint is used to initiate the OAuth flow in place of redirecting or launching a browser to the authorization endpoint.¶
While a fully-delegated approach using the redirect-based Authorization Code grant is generally preferred, this draft provides a mechanism for the client to directly interact with the user. This requires a high degree of trust between the authorization server and the client, as there typically is for first-party applications. It should only be considered when there are usability concerns with a redirect-based approach, such as for native mobile or desktop applications.¶
This draft also extends the token response (typically for use in response to a refresh token request) and resource server response to allow the authorization server or resource server to indicate that the client should re-request authorization from the user. This can include requesting step-up authentication by including parameters defined in [I-D.ietf-oauth-step-up-authn-challenge] as well.¶
This specification MUST only be used by first-party applications, which is when the authorization server and application are operated by the same entity and the user understands them both as the same entity.¶
This specification MUST NOT be used by third party applications, and the authorization server SHOULD take measures to prevent use by third party applications. (e.g. only enable this grant for certain client IDs, and take measures to authenticate first-party apps when possible.)¶
Using this specification in scenarios other than those described will lead to unintended security and privacy problems for users and service providers.¶
This specification is designed to be used by native applications, which includes both mobile and desktop applications.¶
If you provide multiple apps and expect users to use multiple apps on the same device, there may be better ways of sharing a user's login between the apps other than each app implementing this specification or using an SDK that implements this specification. For example, [OpenID.Native-SSO] provides a mechanism for one app to obtain new tokens by exchanging tokens from another app, without any user interaction. See Section 9.5 for more details.¶
The scope of this specification is limited to first-party native applications. Please review the entirety of Section 9, and when more than one first-party native application is supported, Section 9.5.¶
While this draft provides the framework for a native OAuth experience, each implementation will need to define the specific behavior that it expects from OAuth clients interacting with the authorization server. While this lack of clearly defining the details would typically lead to less interoperability, it is acceptable in this case since we intend this specification to be deployed in a tightly coupled environment since it is only applicable to first-party applications.¶
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.¶
This specification uses the terms "Access Token", "Authorization Code", "Authorization Endpoint", "Authorization Server" (AS), "Client", "Client Authentication", "Client Identifier", "Client Secret", "Grant Type", "Protected Resource", "Redirection URI", "Refresh Token", "Resource Owner", "Resource Server" (RS) and "Token Endpoint" defined by [RFC6749].¶
TODO: Replace RFC6749 references with OAuth 2.1¶
There are three primary ways this specification extends various parts of an OAuth system.¶
When the client uses a refresh token to obtain a new access token, the authorization server MAY respond with an error to indicate that re-authorization of the user is required.¶
When making a resource request to a resource server, the resource server MAY respond with an error according to OAuth 2.0 Step-Up Authentication Challenge Protocol [I-D.ietf-oauth-step-up-authn-challenge], indicating that re-authorization of the user is required.¶
The token endpoint is used by the client to obtain an access token by presenting its authorization grant or refresh token, as described in Section 3.2 of OAuth 2.0 [RFC6749].¶
This specification extends the token endpoint response to allow the authorization server to indicate that further authentication of the user is required.¶
The client makes a request to the token endpoint using the authorization code it obtained from the authorization challenge endpoint.¶
This specification does not define any additional parameters beyond the token request parameters defined in Section 4.1.3 of [RFC6749]. However, notably the redirect_uri
parameter will not be included in this request, because no redirect_uri
parameter was included in the authorization request.¶
Upon any request to the token endpoint, including a request with a valid refresh token, the authorization server can respond with an authorization challenge instead of a successful access token response.¶
An authorization challenge error response is a particular type of error response as defined in Section 5.2 of OAuth 2.0 [RFC6749] where the error code is set to the following value:¶
The authorization grant is insufficiently authorized, but another access token request may succeed if an additional authorization grant is presented.¶
OPTIONAL. The optional device session value allows the authorization server to
associate subsequent requests by this client with an ongoing
authorization request sequence. The client MUST include
the device_session
in follow-up requests to the challenge
endpoint if it receives one along with the error response.¶
For example:¶
HTTP/1.1 403 Forbidden Content-Type: application/json;charset=UTF-8 Cache-Control: no-store { "error": "authorization_required", "device_session": "uY29tL2F1dGhlbnRpY" }¶
Step-Up Authentication [I-D.ietf-oauth-step-up-authn-challenge] defines a mechanism for resource servers to tell the client to start a new authorization request, including acr_values
and max_age
, and scope
from RFC6750. Upon receiving this request, the client starts a new authorization request according to this specification, and includes the acr_values
, max_age
and scope
returned in the error response.¶
This specification does not define any new parameters for the resource server error response beyond those defined in [I-D.ietf-oauth-step-up-authn-challenge].¶
Because this specification enables a client application to interact directly with the end user, and the application handles sending any information collected from the user to the authorization server, it is expected to be used only for first-party applications when the authorization server also has a high degree of trust of the client.¶
First-party applications are applications that the user recognizes as belonging to the same brand as the authorization server. For example, a bank publishing their own mobile application.¶
There are two ways using this specification increases the risk of phishing.¶
With this specification, the client interacts directly with the end user, collecting information provided by the user and sending it to the authorization server. If an attacker impersonates the client and successfully tricks a user into using it, they may not realize they are giving their credentials to the malicious application.¶
In a traditional OAuth deployment using the redirect-based authorization code flow, the user will only ever enter their credentials at the authorization server, and it is straightforward to explain to avoid entering credentials in other "fake" websites. By introducing a new place the user is expected to enter their credentials using this specification, it is more complicated to teach users how to recognize other fake login prompts that might be attempting to steal their credentials.¶
Because of these risks, the authorization server MAY decide to require that the user go through a redirect-based flow at any stage of the process based on its own risk assessment.¶
Typically, mobile and desktop applications are considered "public clients" in OAuth, since they cannot be shipped with a statically configured set of client credentials [RFC8252]. Because of this, client impersonation should be a concern of anyone deploying this pattern. Without client authentication, a malicious user or attacker can mimick the requests the application makes to the authorization server, pretending to be the legitimate client.¶
Because this specification is intended for first-party applications, it is likely that the intent is to also avoid prompting the user with a consent screen as recommended by [RFC6749].¶
Implementers SHOULD consider additional measures to limit the risk of client impersonation, such as using attestation APIs available from the operating system.¶
Tokens issued to native apps SHOULD be sender constrained to mitigate the risk of token theft and replay.¶
Proof-of-Possession techniques constrain tokens by binding them to a cryptographic key. Whenever the token is presented, it should be accompanied by a proof that the client presenting the token also controls the cryptographic key bound to the token. If a proof-of-possession sender constrained token is presented without valid proof of possession of the cryptographic key, it MUST be rejected.¶
DPoP is an application-level mechanism for sender-constraining OAuth [RFC6749] access and refresh tokens [I-D.ietf-oauth-dpop]. If DPoP is used to sender constrain tokens, the native client SHOULD use DPoP for every token request to the authorization Server and interaction with the Resource Server.¶
DPoP includes an optional capability to bind the authorization code to the DPoP key to enable end-to-end binding of the entire authorization flow. If an attacker can access the Authorization Code and PKCE code verifier as described in Section 11.9 of [I-D.ietf-oauth-dpop], Authorization Code binding SHOULD be used.¶
To bind the authorization code using the Authorization Challenge Endpoint, the JWK Thumbprint of the DPoP key MUST be communicated to the Authorization Server by including the dpop_jkt
parameter defined in section 10 of [I-D.ietf-oauth-dpop] alongside other authorization request parameters in the POST body of the first Authorization Challenge Request. If it is included in subsequent Authorization Challenge Requests, the value of this parameter must be the same as in the initial request. If the JWK Thumbprint in the dpop_jkt
differ at any point, the Authorization Server MUST reject the request. If the dpop_jkt
parameter is not included in the first request, but added in subsequent requests, the Authorization Server MUST reject the request (do we need to define a specific error code for that?).¶
It may be possible to use other proof of possession mechanisms to sender constrain access and refresh tokens. Defining these mechanisms are out of scope for this specification.¶
When there there is more than one 1st-party native applications supported by the AS, then it is important to consider a number of additional risks. These risks fall into two main categories: Experience Risk and Technical Risk which are described below.¶
Any time a user is asked to provide the authentication credentials in user experiences that differ, it has the effect of increasing the likelihood that the user will fall prey to a phishing attack because they are used to entering credentials in different looking experiences. When multiple native applications are support, the implementation MUST ensure the native experience is identical across all the 1st party native applications.¶
Another experience risk is user confusion caused by different looking experiences and behaviors. This can increase the likelihood the user will not complete the authentication experience for the 1st party native application.¶
In addition to the experience risks, multiple implementations in 1st party native applications increases the risk of an incorrect implementation as well as increasing the attack surface as each implementation may expose it's own weaknesses.¶
To address these risk, when multiple 1st party native applications must be supported, and other methods such as [OpenID.Native-SSO] are not applicable, it is RECOMMENDED that a client-side SDK be used to ensure the implementation is consistent across the different native apps and to ensure the user experience is identical for all 1st party apps.¶
IANA has (TBD) registered the following values in the IANA "OAuth Authorization Server Metadata" registry of [IANA.OAuth.Parameters] established by [RFC8414].¶
Metadata Name: authorization_challenge_endpoint¶
Metadata Description: URL of the authorization server's authorization challenge endpoint.¶
Change Controller: IESG¶
Specification Document: Section 4.1 of [[ this specification ]]¶
This section provides non-normative examples of how this specification may be used to support specific use cases.¶
In a passwordless One-Time Password (OTP) scheme, the user is in possession of a one-time password generator. This generator may be a hardware device, or implemented as an app on a mobile phone. The user provides a user identifier and one-time password, which is verified by the Authorization Server before it issues an Authorization Code, which can be exchanged for an Access and Refresh Token.¶
A user may be required to provide an e-mail confirmation code as part of an authentication ceremony to prove they control an e-mail address. The user provides an e-mail address and is then requried to enter a verification code sent to the e-mail address. If the correct verification code is returned to the Authorization Server, it issues Access and Refresh Tokens.¶
"error": "authorization_required"
, "device_session"
and a custom error code indicating that an e-mail verification code must be entered.¶
device_session
parameter returned in the previous Error Response.¶
device_session
to maintain the session and verifies the e-mail verification code before issuing an Authorization Code to the Client.¶
A user may be required to provide an SMS confirmation code as part of an authentication ceremony to prove they control a mobile phone number. The user provides a phone number and is then requried to enter a SMS confirmation code sent to the phone. If the correct confirmation code is returned to the Authorization Server, it issues Access and Refresh Tokens.¶
"error": "authorization_required"
, "device_session"
and a custom error code indicating that a SMS confirmation code must be entered.¶
device_session
parameter returned in the previous Error Response.¶
device_session
to maintain the session context and verifies the SMS code before issuing an Authorization Code to the Client.¶
A client may be in possession of an Access and Refresh Token as the result of a previous succesful user authentication. The user returns to the app a week later and accesses the app. The Client presents the Access Token, but receives an error indicating the Access Token is no longer valid. The Client presents a Refresh Token to the Authorization Server to obtain a new Access Token. If the Authorization Server requires user interaction for reasons based on its own policies, it rejects the Refresh Token and the Client re-starts the user authentication flow to obtain new Access and Refresh Tokens.¶
device_session
.¶
device_session
in an Authorization Challenge Request (Section 5.1) to the Authorization Challenge Endpoint (Section 4.1).¶
device_session
and OTP, and returns an Authorization Code.¶
A Client previously obtained an Access and Refresh Token after the user authenticated with an OTP. When the user attempts to access a protected resource, the Resource Server determines that it needs an additional level of authentication and triggers a step-up authentication, indicating the desired level of authentication using acr_values
and max_age
as defined in the Step-up Authentication specification. The Client initiates an authorization request with the Authorization Server indicating the acr_values
and max_age
parameters. The Authorization Server responds with error messages promptng for additional authentication until the acr_values
and max_age
values are satisfied before issuing fresh Access and Refresh Tokens.¶
acr
claim in the Access Token is insufficient given the resource the user wants to access and responds with an insufficient_user_authentication
error code, along with the desired acr_values
and desired max_age
.¶
device_session
, acr_values
and max_age
parameters.¶
device_session
and determines which authentication methods must be satisfied based on the acr_values
, and responds with an Error Response (Section 5.2.2) including "error": "authorization_required"
and a custom error code indicating that an OTP must be entered.¶
device_session
and OTP.¶
acr
value along with the Refresh Token.¶
acr
value meets its requirements before granting access to the prtoected resource.¶
This example describes how to use the mechanisms defined in this draft to create a complete user registration flow starting with an email address. In this example, it is the Authorization Server's policy to allow these challenges to be sent to email and phone number that were previously unrecognized, and creating the user account on the fly.¶
"error": "authorization_required"
, "device_session"
, and a custom error code indicating that an e-mail address must be collected.¶
device_session
parameter.¶
"error": "authorization_required"
, "device_session"
and a custom error code indicating that an e-mail verification code must be entered.¶
device_session
parameter returned in the previous Error Response.¶
device_session
to maintain the session context, and verifies the e-mail verification code. It determines that it also needs a phone number for account recovery purposes and returns an Error Response including "error": "authorization_required"
, "device_session"
and a custom error code indicating that a phone number must be collected.¶
device_session
.¶
device_session
parameter to link the previous requests. It sends a confirmation code to the phone number and returns an Error Response including "error": "authorization_required"
, "device_session"
and a custom error code indicating that a SMS confirmation code must be entered.¶
device_session
parameter returned in the previous Error Response.¶
device_session
to maintain the session context, and verifies the SMS verification code before issuing an Authorization Code to the Client.¶
In order to successfully implement this specification, the Authorization Server will need to define its own specific requirements for what values clients are expected to send in the Authorization Challenge Request (Section 5.1), as well as its own specific error codes in the Authorization Challenge Response (Section 5.2).¶
Below is an example of parameters required for a complete implementation that enables the user to log in with a username and OTP.¶
The client prompts the user to enter their username, and sends the username in an initial Authorization Challenge Request.¶
POST /authorize HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded username=alice &scope=photos &client_id=bb16c14c73415¶
The Authorization Server sends an error response indicating that an OTP is required.¶
HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store { "error": "otp_required", "device_session": "ce6772f5e07bc8361572f" }¶
The client prompts the user for an OTP, and sends a new Authorization Challenge Request.¶
POST /authorize HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded device_session=ce6772f5e07bc8361572f &otp=555121¶
The Authorization Server validates the device_session
to find the expected user, then validates the OTP for that user, and responds with an authorization code.¶
HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store { "authorization_code": "uY29tL2F1dGhlbnRpY" }¶
The client sends the authorization code to the token endpoint.¶
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id=bb16c14c73415 &code=uY29tL2F1dGhlbnRpY¶
The Authorization Server responds with an access token and refresh token.¶
HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store { "token_type": "Bearer", "expires_in": 3600, "access_token": "d41c0692f1187fd9b326c63d", "refresh_token": "e090366ac1c448b8aed84cbc07" }¶
TODO acknowledge.¶