Skip to content

Commit

Permalink
Merge pull request #18 from elf-pavlik/as-sequence
Browse files Browse the repository at this point in the history
Add RS associated AS issuing Access Token
  • Loading branch information
elf-pavlik authored Jan 12, 2022
2 parents 9ac921a + 8a19057 commit 6151e62
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 256 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.html
*.mmd.svg
publish
node_modules
Binary file removed basic-flow-diagram.png
Binary file not shown.
174 changes: 93 additions & 81 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ that additional functionality is required.

The additional functionality documented herein aims to address:

1. Resource servers having no existing trust relationship with identity providers.
1. Resource servers and their Authorization servers having no existing trust relationship with identity providers.
2. Ephemeral Clients as a first-order use-case.

## Out of Scope ## {#intro-out-of-scope}
Expand All @@ -81,8 +81,9 @@ This specification uses the terms "access token", "authorization server", "resou
"grant type", and "client" as defined by The OAuth 2.0 Authorization Framework [[!RFC6749]].

Throughout this specification, we will use the term Identity Provider (IdP) in line with the
terminology used in the Open ID Connect Core 1.0 specification (OIDC) [[!OIDC.Core]]. It should be noted that
The OAuth 2.0 Authorization Framework (OAuth) [[!RFC6749]] refers to this same entity as an Authorization Server.
terminology used in the Open ID Connect Core 1.0 specification (OIDC) [[!OIDC.Core]].
It should be noted that this is distinct from the entity referred to as an Authorization Server
by the OAuth 2.0 Authorization Framework (OAuth) [[!RFC6749]].

This specification also uses the following terms:

Expand Down Expand Up @@ -145,23 +146,11 @@ Solid and are used as a primary identifier for Users in this specification.

*This section is non-normative*

The basic authentication and authorization flow is as follows:

1. The Client requests a non-public resource from the RS.
2. The RS returns a 401 with a `WWW-Authenticate` HTTP header containing parameters that inform the
Client that a DPoP-bound Access Token is required.
3. The Client presents its Client Identifier and the associated Secret, if any, to the IdP and requests an
Authorization Code.
4. If granted, the Client presents the Authorization Code and a DPoP proof, to the Token Endpoint.
5. The Token Endpoint returns a DPoP-bound Access Token and OIDC ID Token, to the Client.
6. The Client presents the DPoP-bound Access Token and DPoP proof, to the RS.
7. The RS gets user's WebID Document and check for designated OIDC issuers
8. The RS gets the public key from the IdP and uses it to validate the signature on the DPoP-bound Access Token (JWS).
9. If IdP is designated by the user and Access Token is valid, then the RS returns the requested resource.
Details of the flow are available in [[!Solid.OIDC.Primer]]

<figure id="fig-signature">
<img src="sequence.mmd.svg" />
<figcaption>Basic sequence of authentication and authorization as described above.</figcaption>
<figcaption>Basic sequence of authenticating the user and the client.</figcaption>
</figure>

# Client Identifiers # {#clientids}
Expand All @@ -180,9 +169,6 @@ provided at `https://www.w3.org/ns/solid/oidc-context.jsonld` such that the resu
document produces a JSON serialization of an OIDC client registration, per the
definition of client registration metadata from [[!RFC7591]] section 2.

Issue: [Related Issue](https://github.com/solid/authentication-panel/issues/75)
Solid-OIDC requirements for client description document

Also, the IdP MUST dereference the Client ID Document and match any Client-supplied parameters
with the values in the Client ID Document.

Expand All @@ -192,7 +178,7 @@ list.
This example uses [JSON-LD ](https://www.w3.org/TR/json-ld11/) for the Client ID Document:

<div class='example'>
<p>https://app.example/id
<p>https://app.example/id</p>

<pre highlight="jsonld">
{
Expand Down Expand Up @@ -317,58 +303,35 @@ Assuming one of the following options
- Client ID and Secret, and valid DPoP Proof (for dynamic and static registration)
- Dereferencable Client Identifier with a proper Client ID Document and valid DPoP Proof (for a Solid client identifier)

the IdP MUST return two tokens to the Client:

1. A DPoP-bound Access Token
2. An OIDC ID Token

## DPoP-bound Access Token ## {#tokens-access}
the IdP MUST return A DPoP-bound OIDC ID Token.

The DPoP-bound Access Token MUST be a valid JWT. See also: [[!RFC7519]].
## DPoP-bound OIDC ID Token ## {#tokens-id}

When requesting a DPoP-bound Access Token, the Client MUST send a DPoP proof JWT
When requesting a DPoP-bound OIDC ID Token, the Client MUST send a DPoP proof JWT
that is valid according to the [[DPOP#section-5]]. The DPoP proof JWT is used to
bind the access token to a public key. See also: [[!DPOP]].
bind the OIDC ID Token to a public key. See also: [[!DPOP]].

With the `webid` scope, the DPoP-bound Access Token payload MUST contain these claims:
With the `webid` scope, the DPoP-bound OIDC ID Token payload MUST contain these claims:
* `webid` — The WebID claim MUST be the user's WebID.
* `iss` — The issuer claim MUST be a valid URL of the IdP
instantiating this token.
* `aud` — The audience claim MUST either be the string `solid` or be an array
of values, one of which is the string `solid`. In the decentralized world
of Solid OIDC, the principal of an access token is not a specific endpoint,
but rather the Solid API; that is, any Solid server at any accessible address
* `aud` — The audience claim MUST be an array of values,
one of which is the ClientID claim is used to identify the client.
(See also: [section 5. Client Identifiers](#clientids)).
another one is the string `solid`.
In the decentralized world
of Solid OIDC, the audience of an ID Token is not only the client,
but also a Solid Authorization Server;
that is, any Solid Authorization Server at any accessible address
on the world wide web. See also: [[RFC7519#section-4.1.3]].
* `azp` - The ClientID claim is used to identify the client.
(See also: [section 5. Client Identifiers](#clientids)).
* `iat` — The issued-at claim is the time at which the DPoP-bound
Access Token was issued.
OIDC ID Token was issued.
* `exp` — The expiration claim is the time at which the DPoP-bound
Access Token becomes invalid.
OIDC ID Token becomes invalid.
* `cnf` — The confirmation claim is used to identify the DPoP Public
Key bound to the Access Token. See also: [[DPOP#section-7]].
* `client_id` - The ClientID claim is used to identify the client. See also:
[section 5. Client Identifiers](#clientids).

<div class="example">
<p>An example DPoP-bound Access Token:

<pre highlight="json">
{
"webid": "https://janedoe.com/web#id",
"iss": "https://idp.example.com",
"aud": "solid",
"iat": 1541493724,
"exp": 1573029723,
"cnf":{
"jkt":"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"
},
"client_id": "https://client.example.com/web#id"
}
</pre>
</div>

## OIDC ID Token ## {#tokens-id}

When requesting the `webid` scope, the user's WebID MUST be present in the ID Token as the `webid` claim.
Key bound to the OIDC ID Token. See also: [[DPOP#section-7]].

<div class="example">
<p>An example OIDC ID Token:
Expand All @@ -378,45 +341,74 @@ When requesting the `webid` scope, the user's WebID MUST be present in the ID To
"webid": "https://janedoe.com/web#id",
"iss": "https://idp.example.com",
"sub": "janedoe",
"aud": "https://client.example.com/web#id",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"aud": ["https://client.example.com/web#id", "solid"],
"azp": "https://client.example.com/web#id",
"iat": 1311280970,
"exp": 1311281970,
"cnf":{
"jkt":"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"
}
}
</pre>
</div>

# Resource Access # {#resource}

## Authorization Server Discovery ## {#authorization-server-discovery}

When a Client performs an unauthenticated request to a protected resource,
the Resource Server MUST respond with the HTTP <code>401</code> status code,
and a <code>WWW-Authenticate</code> HTTP header. See also: [[RFC7235#section-4.1]]

The <code>WWW-Authenticate</code> HTTP header MUST include an <code>as_uri</code>
parameter unless the authentication scheme requires a different mechanism
for discovering an associated authorization server.

Authorization Servers SHOULD implement User-Managed Access (UMA) 2.0 Grant for
OAuth 2.0 Authorization [[!UMA]].

## Obtaining an Access Token ## {#obtaining-access-token}

For Authorization Servers that conform to [[!UMA]], the
<code>http://openid.net/specs/openid-connect-core-1_0.html#IDToken</code> profile MUST
be supported. This profile MUST be advertised in the <code>uma_profiles_supported</code>
metadata of the Authorization Server discovery document [[UMA#rfc.section.2]].

When using the <code>http://openid.net/specs/openid-connect-core-1_0.html#IDToken</code>
profile with an UMA-based Authorization Server, the Authorization Server MUST be capable
of exchanging a valid Solid-OIDC ID Token [[#tokens-id]] for an OAuth 2.0 Access Token.

Note: Clients can push additional claims by requesting an upgraded RPT [[UMA#rfc.section.3.3.1]]

## DPoP Proof Validation ## {#resource-dpop-validation}

A DPoP Proof that is valid according to
[DPoP Internet-Draft, Section 4.3](https://tools.ietf.org/html/draft-ietf-oauth-dpop-04#section-4.3),
MUST be present when a DPoP-bound Access Token is used.
MUST be present when a DPoP-bound OIDC ID Token is used.

## Access Token Validation ## {#resource-access-validation}
## OIDC ID Token Validation ## {#resource-access-validation}

The DPoP-bound Access Token MUST be validated according to
The DPoP-bound OIDC ID Token MUST be validated according to
[DPoP Internet-Draft, Section 6](https://tools.ietf.org/html/draft-ietf-oauth-dpop-04#section-6),
but the RS MAY perform additional verification in order to determine whether to grant access to the
but the AS MAY perform additional verification in order to determine whether to grant access to the
requested resource.

The user's WebID in the `webid` claim MUST be dereferenced and checked against the `iss` claim in the
Access Token. If the `iss` claim is different from the domain of the WebID, then the RS MUST check
OIDC ID Token. If the `iss` claim is different from the domain of the WebID, then the AS MUST check
the WebID document for the existence of a statement matching `?webid <http://www.w3.org/ns/solid/terms#oidcIssuer> ?iss.`,
where `?webid` and `?iss` are the values of the `webid` and `iss` claims respectively.
This prevents a malicious identity provider from issuing valid Access Tokens for arbitrary WebIDs.
This prevents a malicious identity provider from issuing valid OIDC ID Tokens for arbitrary WebIDs.

Unless the RS acquires IdP keys through some other means, or the RS chooses to reject tokens issued by this IdP,
the RS MUST follow OpenID Connect Discovery 1.0 [[!OIDC.Discovery]] to find an IdP's signing keys (JWK).
Unless the AS acquires IdP keys through some other means, or the AS chooses to reject tokens issued by this IdP,
the AS MUST follow OpenID Connect Discovery 1.0 [[!OIDC.Discovery]] to find an IdP's signing keys (JWK).

### WebID Issuer Discovery via Link Headers ### {#webid-issuer-discovery}

A server hosting a WebID document MAY transmit the `http://www.w3.org/ns/solid/terms#oidcIssuer` values via Link Headers but it MUST be the same as in the RDF representation. A client MUST treat the RDF in the body of the WebID document as canonical but MAY use the Link Header values as an optimization.

<div class="example">
<pre highlight="http">
Link: <https://oidc.example>; rel="http://www.w3.org/ns/solid/terms#oidcIssuer"; anchor="#id"
Link: &lt;https://oidc.example&gt;; rel="http://www.w3.org/ns/solid/terms#oidcIssuer"; anchor="#id"
</pre>
</div>

Expand Down Expand Up @@ -460,7 +452,7 @@ All tokens, Client, and User credentials MUST only be transmitted over TLS.

## Client IDs ## {#security-client-ids}

An RS SHOULD assign a fixed set of low trust policies to any client identified as anonymous.
An AS SHOULD assign a fixed set of low trust policies to any client identified as anonymous.

Implementors SHOULD expire ephemeral Client IDs that are kept in server storage to mitigate the
potential for a bad actor to fill server storage with unexpired or otherwise useless Client IDs.
Expand All @@ -479,15 +471,15 @@ among other factors, are what makes Client trust challenging.

# Privacy Considerations # {#privacy}

## Access Token Reuse ## {#privacy-token-reuse}
## OIDC ID Token Reuse ## {#privacy-token-reuse}

*This section is non-normative*

With JWTs being extendable by design, there is potential for a privacy breach if Access Tokens get
reused across multiple resource servers. It is not unimaginable that a custom claim is added to the
Access Token on instantiation. This addition may unintentionally give other resource servers
consuming the Access Token information about the user that they may not wish to share outside of the
intended RS.
With JWTs being extendable by design, there is potential for a privacy breach if OIDC ID Tokens get
reused across multiple authorization servers. It is not unimaginable that a custom claim is added to the
OIDC ID Token on instantiation. This addition may unintentionally give other authorization servers
consuming the OIDC ID Token information about the user that they may not wish to share outside of the
intended AS.

# Acknowledgments # {#acknowledgments}

Expand Down Expand Up @@ -562,6 +554,16 @@ Verborgh, Ricky White, Paul Worrall, Dmitri Zagidulin.
"title": "Solid Protocol",
"publisher": "W3C Solid Community Group"
},
"Solid.OIDC.Primer": {
"authors": [
"Jackson Morgan",
"Aaron Coburn",
"Matthieu Bosquet"
],
"href": "https://solid.github.io/solid-oidc/primer/",
"title": "Solid-OIDC Primer",
"publisher": "W3C Solid Community Group"
},
"WebID": {
"authors": [
"Andrei Sambra",
Expand All @@ -571,6 +573,16 @@ Verborgh, Ricky White, Paul Worrall, Dmitri Zagidulin.
"href": "https://www.w3.org/2005/Incubator/webid/spec/identity/",
"title": "WebID 1.0",
"publisher": "WebID Incubator Group"
},
"UMA": {
"authors": [
"Eve Maler",
"Maciej Machulak",
"Justin Richer"
],
"href": "https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html",
"title": "User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization",
"publisher": "Kantara Initiative, Inc"
}
}
</pre>
Loading

0 comments on commit 6151e62

Please sign in to comment.