Managing authorization grants beyond OAuth 2
Why we're building a new IETF standard called GNAP
This article blog is a longer and preprint version of a peer-reviewed article co-authored with Justin Richer and Aaron Parecki, that has been accepted as a short paper at the Open Identity Summit 2021. The final paper shall be published by LNI.
The Grant Negotiation and Authorization Protocol, also known as GNAP, is currently being formulated in an IETF working group. Its objective is to take into account the experience from OAuth 2 and its large ecosystem. GNAP therefore gives the opportunity to reflect on the strengths and weaknesses of existing authorization frameworks (and OAuth 2 in particular), and highlights the new directions to improve digital access. We compare with the approach taken by OAuth 2 and show that designing authorization servers primarily as “token issuers” provides insightful consequences for security and privacy.
Before we dive into the serious stuff, you should know that GNAP is already widely used by some smurfs.
Lessons from OAuth2
A short history
The year was 2012, and an authorization protocol called OAuth 2 (Open Authorization 2) swept the web, allowing users to use security providers to easily log in to websites. Coupled with OpenID, OAuth 2 enables an end-user to “authenticate with” one of its providers (google, facebook, github, etc.) to a completely different website or application, therefore reducing the need to define yet another password.
OAuth 2 aims to solve the delegated authorization problem. Delegation happens when a third party application, acting on behalf of a natural person, requests access to a protected resource. The naive way to solve this problem is for the natural person to give its password to the third party, but sharing passwords is a security risk and must be avoided. OAuth 2 defines flows to grant access without having to share secrets. A typical flow (figure 1) between a client application and an authorization server involves a redirection to ask the consent of the resource owner, before an access token can be used to access a protected resource.
Fig. 1: high-level OAuth 2 flow (source: [Ri17])
Solving the delegation use case had such an impact because OAuth 2 landed at a time where Application Programming Interfaces (API) really became mainstream. In 2020, 83% of the internet traffic was due to APIs (compared to the remaining 17% through HTML). Cloud based companies in particular found it convenient to better secure the access to their protected API endpoints. As Gartner points out, this trend is accelerating [Ze19]: “90% of web-enabled applications have more surface area for attack in the form of exposed APIs rather than the UI, up from 40% in 2019.”
Relying on a common framework enabled easier integrations across services too, as exemplified by the widespread use of zapier amongst software as a service providers. It also reduces the risk of vendors inventing their own security mechanism. Most major services now support OAuth 2, often associated with OpenID Connect for single-sign on. OAuth 2 is heavily used to protect API first services, such as open banking (and the related PSD2 regulation in Europe). The decade experience that exists with OAuth 2 and its extensions got recently consolidated into an OAuth 2.1 draft version. If approved, this update will obsolete certain parts of OAuth 2.0 and mandate security best practices (as described in [Pa19]).
The “core” OAuth 2.0 spec, RFC 6749 [Ha12], isn’t a specification, it’s a “framework” you can use to build specifications from. It defines roles and a base level of functionality, but leaves a lot of implementation details unspecified or optional. The IETF OAuth Working Group has published many additional specifications (figure 3) to fill in the missing pieces. Implementers need to decide which grant types to support, whether or not refresh tokens are one-time use, and even whether access tokens should be bearer tokens or use some sort of signed token mechanism. One critical extension is OpenID Connect, which defines an ID Token for returning user information.
Fig. 2 : OAuth 2.0 as an extensible framework (source : [Pa19])
This maze has often been quoted as the biggest failure of OAuth 2, but the extensibility it shows also explains why OAuth 2 has been successfully deployed at scale.
OAuth 2 has been designed through an open standardisation process, managed by the IETF. OAuth 2 wasn’t the first authorization protocol. As the name suggests, OAuth 1 came before, and the two versions are not compatible. OAuth 1 had custom methods to deal with various attacks. Instead, OAuth 2 delegates its security model to the HTTP/1.1 protocol (and TLS) and makes it easier to carry out a formal analysis of its guarantees [Fe16]. OAuth 2 supports modern technologies such as REST and JSON. In particular, it relies on JSON Web Tokens [Jo15] as the default format for access tokens. The access token format is considered opaque to the client.
The protocol seeks to enable a separation of concerns, decoupling authentication from authorization. This is a significant difference to previous protocols, such as Kerberos, Radius or SAML. OpenID Connect (OIDC) is the de-facto identity layer on top of OAuth 2.0. Extensions are now emerging from the decentralized identity space, to support self-issued credentials (SIOP [Te20]). A complete introduction to the capabilities of OAuth2 is beyond the objective of this article, the interested reader may refer to the book “OAuth2 in Action”[Ri17].
Limitations and challenges
Despite its widespread use and impressive success, OAuth 2 also has downsides. The terminology is not clarified in the standard. It makes the concepts harder to understand by newcomers. Based on our teaching experience, it’s not intuitive for a developer to understand that his own application is called client and needs to register against an authorization server.
More fundamentally, the delegation model is only partially implemented. The core specification focuses on the case where the end-user connects to their own subscribed services. However, there are other important cases where the assumption end-user = resource owner doesn’t hold. A child may ask for parental agreement to watch a movie. A doctor may ask for one of a patient’s medical records. The patient is the owner of the resource and is asked whether they consent to grant access to their doctor. This specific case is handled by the UMA2 (User-Managed Access [Um18]) extension from the Kantara initiative, but handling the consent of a remote resource owner is generally unsolved.
In particular, a smooth interaction with end-users is of critical importance, but the choice of provider may look overwhelming (known as the “NASCAR problem”). As we’ll discuss in the next paragraphs, this inconvenience has led to the reliance on a few gatekeepers only.
Fig.3 : The NASCAR problem
OAuth 2 is also very browser-centric. While OAuth 2 introduced various flows to better support non-browser agents, the interaction still needs to start from a web browser. This complexifies integrations with native devices, such as mobile phones or connected things.
The internet of things (IoT) is not the main target of the standard, but the reliance on HTTP/1.1 has limited the applicability of the standard to that domain area. Due to the drastic energy and bandwidth constraints, the vast majority of IoT networks do not follow the internet model based on IP protocols and TLS based security. Due to the limitations of HTTP/1.1, a protocol called CoAP has been gaining in popularity and is used by some OAuth 2 profiles (such as ACE [Se20]). CoAP being specific, interoperability with the rest of the internet still requires the use of gateways. This not only presents an interoperability problem but a security issue too, since end-to-end encryption becomes harder when intermediaries are required, and leads to unnecessary least privilege access. In the future, HTTP/3 might allow a more natural fit for battery powered devices, thanks to more efficient congestion controls and header compression.
Access policies also come with their limitations. In Oauth 2, scopes are used to limit an application’s access to some owner’s data by issuing an authorization grant that is limited only to the scopes granted by the user. OAuth 2 scopes are merely strings (e.g. “read”, “write”, or whatever makes sense in a specific context, e.g. “dolphin”). Some business cases require more than a fixed string. If you want to authorize a payment, you need to pass an amount, a currency, a recipient, and the purpose to the authorization server. Otherwise, the authorization server cannot gather the user’s consent for that particular transaction and generate an access token that is really constrained to the transaction’s parameters (e.g., the amount).
Essentially, scopes are proxies for role based access (RBAC) or attribute based access (ABAC). Those access policies are convenient ways to handle the case where the resource owner is a corporate entity. For instance, an administrator end-user may be issued an “admin” role for a set of applications, and the corporate system grants privilege access based on that admin role. However, modern cloud architectures spread beyond the traditional network perimeter and require more dynamics rule engines than a static scope parameter. NIST has proposed a “next generation access control” (NGAC [Fe15]) standard, while the usage control model (UCON [Pa04]) formalized six core components: subjects (with attributes), objects (with attributes), rights, authorizations, obligations, and conditions. Despite their ease of use, JWT tokens effectively limit what is possible. For instance, in cloud environments, a single request could result in hundreds of internal requests between microservices or lambda functions, each requiring a verification of authorization, making it impractical due to latency issues.
Bearer tokens also tend to be abused by developers for stateful session handling. The revocation of access tokens is possible but its details depend on each implementation provider. OAuth 2 is more a framework than a protocol, as compatibility between two authorization service (AS) providers is not guaranteed, making it impossible to mix various ASs.
Therefore, in practice, applications stick to just a few digital gatekeepers. This poses a major privacy concern, as the gatekeepers are able to know what grant is asked by whom and when. There’s no mechanism within OAuth 2 to guarantee the privacy of end-users from a curious AS. The European Commission is now considering imposing legal obligations on digital platforms to remedy or prevent “commercial imbalances” [Re20]. This includes digital IDs, as customers using a single ID to login to a range of unrelated 3rd-party services could be locked in. “Restrictions or separations of digital ID services from platforms’ commercial operations may be necessary” [Re20]. This debate is amplified by the regulatory work currently being planned for the Digital Service Act. According to a position paper published by the EPP group [Ep21], the largest parliamentary group in the EU, “[We] firmly support the right to be anonymous on the Internet (as it is acknowledged by the GDPR) but at the same time reject the idea of being unidentifiable online (= what is illegal offline, is illegal online). To make sure that, while maintaining anonymity, everyone is digitally identifiable where this is necessary, a protected European digital identity should be created, using, for example, the blockchain technology. The level of responsibility of the platforms should be tailored to the identifiability of the users”. While it’s hard to tell if that is an awkward way of referring to the self-sovereign identity (SSI) space, the ethical questions raised by such a proposal shouldn’t be ignored [Im21]. As Sheldrake explains [Sh20], “in centralising identity on the individual, as SSI does, it removes some identification, authentication, and claims processes from being subject to law and organisational governance (e.g. the GDPR does not apply to individuals), and into the chaos of social groups and the formation and reformation of social norms and other societal structures.” Policy makers and technologists should reflect on the rationale and impact of decentralizing identities, essentially revisiting the “laws of identity” [Ca05], 15 years later.
The centralization of the authorization framework is also questioned. Would it make sense to deploy the AS on the end-user’s mobile phone, to protect sensitive consent requests? There have been early experiments [Jo20] to provide an openid:// deep linking scheme to a local HTTP server, with the caveats that browsers do not currently recognize this as a common scheme. The target architecture for a more decentralized framework is a work in progress, with the aim to enable interoperability between decentralized identity wallets and authorization servers.
Some of the mentioned challenges are gradually addressed in the OAuth 2 community by creating new complementary standards: an example is the RAR (Rich Authorization Request [Lo20]), which solves some of the issues related to fixed scopes, especially for open banking use cases. Yet, past design choices limit what can be improved. The healthcare use-case is again well suited to explain the advanced interactions which would be very hard to achieve through state-of-the-art delegation protocols:
- A credentialed doctor (Dr. Bob) uses a secure wallet (capable of a non-repudiable signature) to make a request (relying party credentials, scope of resource server access, purpose of access) to patient Alice's authorization server;
- The AS responds with a scoped capability and holds Bob accountable for its invocation;
- Dr. Bob passes that capability to his employer institution or to another healthcare partner. Dr. Bob may attenuate the capability before or after it is passed to the system;
- Another physician in the team, Dr. Carol, signs-in to the employer system and clicks on the capability associated with Alice;
- The client (e.g. a mobile application) used by the healthcare team (Dr. Bob or Dr. Carol) presents the capability to the protected information and gains scoped accesses to the resource. Organizational policies would likely require an audit trail that includes the doctors’ credentials and/or the root of trust of a software statement presented by the client to ensure its authenticity.
OAuth2 would have trouble handling such a complex but realistic and common scenario, possibly requiring coordination between several ASs and resource servers, and involving delegations and policies between multiple users (the doctors) distinct from the resource owner (the patient). By focusing on the usability of privacy and security protocols within the real-world contexts in which they have to operate, we target a human centric design [Sa05]. We therefore propose to take a fresh look at how to design a delegation protocol.
Alternative design principles with GNAP
In this section, we explain how a new protocol currently being specified within the IETF GNAP (Grant Negotiation and Authorization Protocol) working group, goes away from some of the current OAuth 2 assumptions and limitations. The core specification document is publicly available as a draft [Ie20]. Many changes are still expected before the specification is officially published, but the general design principles have received consensus from the project charter. A formal terminology [Ie21] has been approved. Early versions of the draft are already implemented as open source projects by different stakeholders, to ensure those concepts are practically sound (as per the unofficial IETF motto: "we believe in rough consensus and running code").
Non goals should be explicit. Just as with OAuth 2, GNAP doesn’t intend to specify the authentication process. Instead it integrates with existing standards, such as OIDC, WebAuthn/FIDO2 or decentralized identity protocols. OAuth 2 has shown the benefits of such a decoupling, but GNAP aims to enable better portability between various identity schemes. OAuth 2 comes with known benefits and GNAP also doesn’t intend to replace OAuth 2 or its extensions. An appendix in the GNAP core specification defines how to retrofit scopes and client_id from existing OAuth 2 systems and enable a progressive roll-out.
Cryptography based security
OAuth 2 uses shared bearer secrets, including the client_secret and access token, and advanced authentication and sender-constraining have been built on after the fact in inconsistent ways. In GNAP, all communication between the client instance and AS is bound to a key held by the client instance.
GNAP uses the same cryptographic mechanisms for both authenticating the client (to the AS) and binding the access token (to the resource server and the AS). It allows extensions to define new cryptographic protection mechanisms, as new methods are expected to become available over time. GNAP does not have a notion of “public clients” because key information can always be sent and used dynamically in addition to being pre-registered.
OAuth 2 generally assumes the user has access to a web browser. The type of interaction available is fixed by the grant type, and the most common interactive grant types start in the browser. OAuth 2 assumes that the user using the client software is the same user that will interact with the AS to approve access. GNAP is designed to allow these users to be two different people, but still works in the optimized case of them being the same party.
GNAP allows a client instance to list different ways that it can start and finish an interaction, and these can be mixed together as needed for different use cases. GNAP interactions can use a browser, but don’t have to. Methods can use inter-application messaging protocols, out-of-band data transfer, or anything else. GNAP also allows extensions to define new ways to start and finish an interaction, as new methods and platforms are expected to become available over time.
Intent registration and inline negotiation
OAuth 2 uses different “grant types” that start at different endpoints for different purposes. Many of these require discovery of several interrelated parameters.
GNAP requests all start with the same type of request to the same endpoint at the AS. Next steps are negotiated between the client instance and AS based on software capabilities, policies surrounding requested access, and the overall context of the ongoing request. GNAP defines a continuation API that allows the client instance and AS to request and send additional information from each other over multiple steps. This continuation API uses the same access token protection that other GNAP-protected APIs use. GNAP allows discovery to optimize the requests but it isn’t required thanks to the negotiation capabilities.
OAuth 2 requires all clients to be registered at the AS and to use a client_id known to the AS as part of the protocol. This client_id is generally assumed to be assigned by a trusted authority during a registration process, and OAuth 2 places a lot of trust on the client_id as a result and requires it throughout the protocol. Dynamic registration allows different classes of clients to get a client_id at runtime, even if they only ever use it for one request.
Instead of a client_id (related to a pre-registered client software), GNAP relies on client instances (identified by their key). GNAP allows the client instance to present an unknown key to the AS and use that key to protect the ongoing request. It also allows to define attestation mechanisms for the client software (for instance, the organization the client represents, a specific version, the posture of the device the client is installed on, etc.). GNAP’s client instance identifier mechanism allows for pre-registered clients and dynamically registered clients to exist as an optimized case without requiring the identifier as part of the protocol at all times.
OAuth 2 defines the “scope” parameter for controlling access to APIs. This parameter has been co-opted to mean a number of different things in different protocols, including flags for turning special behavior on and off, including the return of data apart from the access token. The “resource” parameter and RAR extensions expand on the “scope” concept in similar but different ways. GNAP defines a rich structure for requesting access and supports string references as an optimization.
GNAP defines methods for requesting directly-returned user information, separate from API access. This information includes identifiers for the current user and structured assertions. Like OAuth 2, GNAP can support various access token formats, including JWT which remains popular for its simplicity. Innovation provided by decentralized delegation and attenuation token mechanisms (such as macaroons [Bi14] or biscuits [Bi20][Im20]) enables more advanced behaviors.
Privacy by design
OAuth 2 has no protection against a curious AS.
GNAP intends to provide privacy preserving mechanisms based on two principles:
- data minimization: minimizing the amount of attributes being disclosed by an end-user to the minimum necessary to achieve a stated purpose, and minimizing the number of parties this information is exposed to (such as the web browser);
- untraceability: preventing an AS from knowing which resources are called by a client, and which operations are performed. For instance, hiding the url of protected resources from the AS.
Those mechanisms could either target a single AS or multiple ASs in order to reduce centralization and improve scalability.
This article provides a comparison of OAuth 2 and the more recent GNAP authorization protocol. The later covers simple delegation in a more consistent way but also enables advanced cases between various stakeholders involved in sensitive application domains.
In OAuth2, it is assumed that the AS is the device that’s authenticating the user, collecting consent, managing the client’s registration, and creating an access token based on whatever set of rights that are associated with all of those things. In UMA2, this is turned around by letting the resource owner present a bunch of “claims” interactively, but still at the AS. With both of these, a key aspect remains: the AS needs to gather necessary information, and issue the access token (or identifiers/assertions). Because of how GNAP works, the client software has a better opportunity to present information to the AS, either directly in the request, through external parties or by introducing the AS to another software component during the “interaction” phase. So GNAP asks, what if we think of authorization server(s) primarily as a “token issuer(s)”?
Beyond GNAP, reflecting on the current assumptions and limitations of OAuth 2 is a worthwhile exercise that would require a closer partnership between practitioners and academia. In particular, a better understanding of the security and privacy guarantees would benefit the general public and the regulatory bodies.
The opportunity to decentralize consent on the end-user’s devices still faces technical challenges. The applicability of those protocols to a broader class of devices, including the IoT, offers an avenue for further research.
- [Bi14] Birgisson A.; Gibbs, J.; Úlfar P.; Taly, A.; Vrable M.; Lentczner, M.; Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud, Network and Distributed System Security Symposium, Internet Society, 2014
- [Bi20] Biscuit authentication/authorization token, github.com/CleverCloud/biscuit
- [Ca05] Cameron K.; The laws of identity, identityblog.com/stories/2005/05/13/TheLaws.., accessed 15/01/2021
- [Ep21] EPP; Position on the Digital Services Act (DSA), google.com/url?q=https://www.eppgroup.eu/do.., accessed 15/01/21
- [Fe15] Ferraiolo D.; Gavrila S.; Jansen W.; Policy Machine: Features, Architecture, and Specification, NIST IR 7987 Revision 1, 2015
- [Fe16] Fett D.; Kuesters, R.; Schmitz, G.; A Comprehensive Formal Security Analysis of OAuth 2.0, Proc. Conference on Computer and Communications Security, pp. 1204-1215, 2016, doi.org/10.1145/2976749.2978385
- [Ha12] Hardt, D.; The OAuth 2.0 Authorization Framework; tools.ietf.org/html/rfc6749
- [Ie20] IETF; Grant Negotiation and Authorization Protocol (gnap), datatracker.ietf.org/wg/gnap/documents
- [Ie21] IETF GNAP wiki, Terminology, github.com/ietf-wg-gnap/gnap-core-protocol/..
- [Im20] Imbault, F.; biscuitsec.org; accessed 15/01/21
- [Im21] Imbault, F.; The ethical dilemma posed by Decentralized Identity, fimbault.medium.com/the-ethical-dilemma-pos.., accessed 15/01/21
- [Jo15] Jones, M.; Bradley, J.; Sakimura, N.; JSON Web Token (JWT), tools.ietf.org/html/rfc7519
- [Jo20] Jones, M.; Wallet UX Challenge for DHS, youtube.com/watch?v=Tq4hw7X5SW0, accessed 15/01/21
- [Lo20] Lodderstedt, T.; Richer, J.; Campbell, B.; OAuth 2.0 Rich Authorization Requests, IETF, draft 3, tools.ietf.org/html/draft-ietf-oauth-rar-03
- [Pa19] Parecki A.; It’s time for OAuth 2.1, aaronparecki.com/2019/12/12/21/its-time-for.., accessed 15/01/21
- [Pa04] Park J.; Sandhu, R., The UCON ABC Usage Control Model, ACM Transactions on Information and System Security, 2004, doi.org/10.1145/984334.984339
- [Re20] Reuters; EU's Breton eyes rules for online platforms acting as gatekeepers, reuters.com/article/eu-tech-breton-idUSB5N2.., accessed 15/01/21
- [Ri17] Richer, J.; Sanso, A.; OAuth2 in Action. Manning, 2017
- [Sa05] Sasse, A.; Flechais, I.; Usable Security. Why Do We Need It? How Do We Get It? In: Cranor, LF and Garfinkel, S, (eds.) Security and Usability: Designing secure systems that people can use, O'Reilly, 2005
- [Se20] Seitz L.; Selander G.; Wahlstroem E.; Erdtman S.; Tschofenig, H.; Authentication and Authorization for Constrained Environments (ACE) using the OAuth 2.0 Framework (ACE-OAuth), IETF, draft 37, tools.ietf.org/html/draft-ietf-ace-oauth-au..
- [Sh20] Sheldrake, P.; The dystopia of self-sovereign identity, sheldrake.medium.com/the-dystopia-of-self-s.., accessed 15/01/21
- [Te20] Terbu, O.; Self-Issued OpenID Connect Provider DID Profile v0.1, DIF, identity.foundation/did-siop
- [Um18] Kantara Initiative; User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization, docs.kantarainitiative.org/uma/wg/rec-oauth..
- [Ze19] Zumerle, D.; D’Hoinne J.; O’Neill, M.; API Security: What You Need to Do to Protect Your APIs, 2019