GNAP is an attempt to pull together functionality from many different extensions and deployments of OAuth 2. Here, we'll try to map specific concepts from these different protocols into the GNAP system.
The scope
parameter in OAuth 2 lets a client specify a set of strings to describe the kind of access it wants. While GNAP allows for a much richer set of authorization details to be requested, scopes are a nice simplification for client developers talking to a known API.
GNAP allows this simplification through the use of resource handles, which can be specified by the AS and used in lieu of a resources object. After all, a scope value is nothing more than a shorthand for a specific set of authorizations being requested. So to translate an OAuth 2 request of scope=foo bar baz
, you simply request access=[foo, bar, baz]
instead.
The redirect
interaction start mechanism with a redirect
finish method allows a client to send a user to interact at the AS using HTTP redirects, and for the most part this should be indistinguishable from the authorization code flow in OAuth 2. The key difference is what gets sent in the front channel. In OAuth 2, the client has to send a lot of sensitive information through the browser, including the scopes it's asking for and the client's own identity. In GNAP, the client simply goes to an opaque URL that it is given in direct response to its request. The client doesn't add any parameters to this URL. The interaction reference returned is equivalent to the authorization code, and this is useful only in the context of continuing a request. Furthermore, the hash cryptographically binds the interaction reference to a set of nonces known to the client and AS at runtime.
This type of interaction can be used for web servers, SPA's, and native applications without modification. In fact, most of the differences between these types of clients are in the ways that they can manage keys and secrets. Since the binding of keys and the mode of interaction are separated in GNAP, they can be combined in ways that make the most sense for the client at hand without changing to a different grant type like in OAuth 2.
Similarly to the authorization code grant, the device grant simply makes use of the user_code
interaction start mechanism along with polling. There is no longer a need for a separate "device" endpoint because the request endpoint covers both this functionality as well as token endpoint functionality. There also does not need to be a separate URL that combines the user code and its delivery URL because the arbitrary URL in the redirect
method can fill this need without the same security issues that a combined URL would have.
The client credentials grant in GNAP is simply a request that does not require user interaction, nor does it require any information about the user from the client. In other words, neither a user
nor interact
section are included in the request.
The resource owner grant could be replicated in GNAP by presenting the user's credentials as part of the user
section of the transaction request, or by doing a challenge-response to present the user's credentials. This would be particularly useful with cryptographic credentials like FIDO tokens. Such multi-step patterns could be written as extensions to the interaction start methods for the client to make use of.
However, even more powerfully, the client can present a wide variety of verifiable assertions in the user
section for the AS to validate and interpret as it sees fit. Chained authorization and authentication are possible in this way, as are forms of linked delegation for cases where the client already knows who the user is and has the authority to do something on their behalf, but needs to translate the authentication to something that can be used further downstream.
The client ID in OAuth 2 is important to the protocol because it allows the client to identify itself during the initial front channel requests where it cannot authenticate itself, for the most common grant types. In GNAP, the client starts talking in the back channel where it can always authenticate itself using its keys. If the AS recognizes the authentication of a specific key, it can tie the request to a set of policies bound to that key's ID. If the key has been registered with the server, the client can send a reference instead. In this way, the client instance_id acts much like the client ID used to. However, in GNAP, the key referred to by the identifier is what fundamentally defines a client instance.
OAuth 2 makes the assumption that all clients have been registered with the authorization server ahead of time, and that this registration includes a wide swath of information about the client software, including its capabilities, its keys, its identity, and other items. This assumption lead to the development of the dynamic registration protocol to allow client instances to be managed at runtime, but at the cost of an additional round trip and, in some cases, a client_id that sits around long after the ephemeral client has disappeared.
In GNAP, the client has the opportunity to present all of this client information during the request. This dynamic request can be bound to keys during the transaction itself, and these keys can be created by the client instance (as would be likely in a native application). These keys identify the instance, and the AS can return an instance_id that the client can use to identify itself in future transactions.
Static registration is of course still possible, with the client or developer being issued an instance_id out of band and the client presenting that instance_id during its transaction request instead of passing client information by value. This pre-registered identifier is bound to keys and interaction methods, effectively locking down a client's runtime behavior when such a lock is desired by the AS.
And finally, an AS can decide to treat clients differently depending on if it's seen the keys before. While OAuth 2 doesn't differentiate between a static and a dynamic client, most implementations flag dynamically registered clients and allow them a lesser level of access to resources. In GNAP, the AS gets to decide this based on how much it trusts the key, and for what purposes.
UMA's pattern of giving the client a ticket
to present claims for, either proactively or interactively, closely matches GNAP's transactional model. UMA's more complex resource description can be incorporated into GNAP's access_token
request section. If the client wants to represent the same user over time, the AS can issue a user handle much like UMA's PCT. Additionally, the RS can present a set of possible resources to the AS and get a resource reference identifier to hand back to the client, mimicking UMA's resource registration endpoint.
The main addition that OpenID Connect brings is the ability to pass identity information to the client directly. A fully-specified GNAP-based identity protocol could be as simple as returning an identity assertion alongside the access token using the subject
request, much in the same way the ID Token is returned in OpenID Connect today. Similarly, the UserInfo Endpoint remains a standardized resource server that behaves the same as it does today, but requested using the access_token
structure and a standardized access
type.
Many of the additional mechanisms in OpenID Connect can be incorporated into the GNAP request instead of being passed through the browser, including any prompt
, login_hint
, or vectors of trust parameters. Additionally, the claims
mechanism's query language can be incorporated into the access
and subject
portion of the request, or grafted on as its own separate parameter.
Due to changes in the workings of the protocol, many other mechanisms in OpenID Connect become unnecessary additions, including the request object and hybrid signed response modes. Many of these components were intend to overcome shortcomings in the OAuth 2 protocol that GNAP does not share.
CIBA maps to GNAP's user_code
style interaction method, since the user is going to interact with the AS using a secondary application. User information and hints about the intended account can be pushed in the user
section of the transaction request. CIBA provides additional hints to verify the device, and these could be added as either extensions or additional parameters in the core interaction methods.
OpenID Connect's Request Object was born of a need to protect a client's request through the browser, and the hybrid flow (later generalized into JARM) provided a means to protect the authorization server's response through the browser. Both of these methods additionally allow a more rich data request through the use of a JSON object instead of plain request parameters. Pushed Authorization Requests (PAR) allow the request side of this equation to be sent in the back channel using an intent registration pattern.
GNAP's transactional model protects this same information by not sending it through the browser redirects in the first place, being built on an intent registration pattern from the ground up.
PKCE effectively creates an ephemeral key that the client can prove possession of at a later part of the process. With GNAP, the same results are an automatic side effect of the transactional process. The continuation access token is something known only to the client and is never passed through the front channel, and any interaction reference returned from the interaction endpoint makes sense only in the context of a specific transaction. Furthermore, the client's own keys are bound to the transaction, making it even more difficult for an attacker to make use of a stolen interaction reference. Finally, the interaction hash prevents insertion of interaction references to unwitting clients, closing a related exploitable loophole that PKCE is a partial solution for.
The main goal of of OAuth 2's various Proof of Possession extension work is to bind a set of runtime keys that the client can prove possession of to the token issued to the client. In GNAP, the various proof of possession mechanisms are not extensions, but a core part of the design. GNAP requires a client to bind keys during its request, and these keys are further bound to the access token by default.
Additionally, GNAP defines flexibility around different proofing mechanisms. As new methods become available across different platforms, GNAP will be able to incorporate them.
The Rich Authorization Request (RAR) specification is being developed in parallel with GNAP, and the content of the authorization_details
parameter is mimics the access
field of a GNAP request. A key difference is that GNAP does not also have to contend with scope
, resource
, aud
, and other values that the RAR specification has to deal with in OAuth 2.