Skip to content

Commit

Permalink
scope-picker and scope-info endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
michielbdejong committed Mar 26, 2024
1 parent 530611a commit b7429d8
Showing 1 changed file with 32 additions and 57 deletions.
89 changes: 32 additions & 57 deletions phase-2/spec/draft.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,42 @@
# OAuth Scope Picker
# Scope Picker Plugin for OAuth Authorization Servers

In this spec we propose to extend OAuth to support dynamically picked scopes. We propose two flows,
the 'predance', which is pretty close to existing work on GNAP and OAuth for bank payments, and the 'subdance' in which the auth server plays a role in decoupling the client from the resource server.
We propose a generic plugin APIs for customisable authorization servers that allows for fine-grained and/or single-use scopes.

## Predance Flow
In this flow, the client first interacts with the resource server to pick a scope. This scope is assigned a URL which it can be dereferenced to obtain its machine-readable and human-readable descriptions. After this predance is completed, the client initiates a normal authorization code flow with this URL as the scope.
Authorization servers that are tightly coupled to resource servers can already define fine-grained and single-use scopes since the scopes parameter that the client sees does not need
to contain all the precise information about the authorization. For instance, the "scope" parameter in the [access token response](https://datatracker.ietf.org/doc/html/rfc6749#section-5.1) may be something as generic as "payment", but behind the scenes, fine-grained and/or single-use details would be linked to the authorization.

The auth server can fetch the JSON document from this URL using an `Authorization: Bearer <scope_secret>` request header and display the text from the `humanReadable[locale]` field, so the user knows which scope is meant. The client can fetch the same document to discover the protocol and API endpoint for interacting with the resource server.
Generic authorization servers can often be customised with "custom scopes", but these need to be defined at installation time, so allowing for fine-grained and/or single-use scopes
would require the definition of a large if not infinite number of such custom scopes.

Example:
Step 1) the client redirects the user to the scope picking GUI of the resource server, with a `redirect_uri` and a `pick=` query parameter referring to the requirements of the resource and scope to be picked. For instance, `pick=photo`.
Step 2) the resource server shows a GUI where the user can select a (structured) scope.
Step 3) the details of what the user selected are stored in a JSON document at a URL
Step 4) this URL is returned as a `scope` query parameter to the `redirect_uri` from step 1, along with a `scope_secret`.
Step 5) the `scope` is used in a standard OAuth flow
Step 6) even though the auth server has presumably never seen this `scope` before, it can still
display a description of it, but fetching the JSON document from this URL using an `Authorization: Bearer <scope_secret>` request header and taking the `humanReadable[locale]` field from there.
The [Lodging Intent Pattern](https://curity.io/resources/videos/lodging-intent-pattern/) provides a good way for OAuth deployments to support fine-grained and single-use scopes with
generic authorization servers because the complexity of the scope selection stays between the client and a custom GUI provided by the resource server. A downside of this approach is that it requires changes to the client and to the interaction between client and authorization server.

```
Client Auth Resource
| | |
|--------1--->|
| | 2
| | 3
|<--4---------|
|---5->| |
|<-----| |
| | |
```
We therefore propose the "scope picker plugin", which exposes the following functionality to the authorization server:

* the scope picker, which acts as an authorization server and grants access to scope definitions.
* the scopes API which acts as a resource server, providing labels for display in the main authorization server's main consent dialog, as ad-hoc custom scopes

## Subdance Flow
The subdance flow works slightly differently:
1) the client initiates an OAuth authorization code flow request where instead of a `scope` parameter, there is a `pick` parameter.
2) based on the `pick` parameter the auth server offers one or more options for the user to be redirected to a scope picker
3) the interaction with the scope picker is identical to steps 2 to 4 of the predance flow, except that the `redirect_uri` now points to the auth server instead of to the client
4) the auth server can now continue as from step 5 of the predance flow.
We separately propose the scope-info endpoint for authorization servers, where clients can discover information about the token they received, beyond the information that was
encoded in the scopes response parameter. For instance, the client may discover the internet address of the resource server, supported protocol versions, and/or the identifier
of the resource that was selected. There may still be information hidden, so the Venn diagram is:

```
Client Auth Resource
| | |
|---1->| |
| 2 |
| |---3->|
| |<-----|
|<--4--| |
| | |
/-----------------\
| |
| hidden from |
| client |
| |
| /-------------\ |
| | | |
| | get from | |
| | scope-info | |
| | | |
| | /---------\ | |
| | | in resp | | |
| | | param | | |
| | \---------/ | |
| | | |
| \-------------/ |
| |
\-----------------/
```

## Security considerations
The client and authorization server have a way to access the scope document using the `scope_secret` which should, for privacy reasons, not be exposed to the public internet.

The resource server is responsible for:
* making sure that the `humanReadable[locale]` string in the scope document is easy for the auth server to display and for the user to recognise as describing the scope they just picked
* making sure the access instructions are sufficient for the client to successfully access the scope/resource
* making sure the access it ends up granting corresponds with what the user intended in the scope selection interaction

Even though the auth server has a trust relationship with the scope picker of the resource server, it is important that it treats the `humanReadable[locale]` description as input from an untrusted source and not as a trusted part of itself. It is responsible for:
* protecting against code injection
* protecting against click-jacking
* protecting against misinformation
* clearly displaying the `humanReadable` description to the user

The client is responsible for:
* for the predance flow, ensuring the resource server is a trusted one
* for both the predance and the subdance flow, ensuring that the auth server is a trusted one

0 comments on commit b7429d8

Please sign in to comment.