Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
338 changes: 338 additions & 0 deletions lws10-core/Authorization.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,338 @@
<p>
Linked Web Storage describes a mechanism for persisting and managing protected data on the Web. Authorization is the mechanism
by which agents request and present access tokens in order to access this protected data.
</p>

<section id="authorization-roles">
<h3>Roles</h3>

<p>
The roles in LWS authorization are the same as those defined by OAuth 2.0 Section 1.1 [[!RFC6749]]:
<dfn data-cite="RFC6749#section-1.1">resource owner</dfn>,
<dfn data-cite="RFC6749#section-1.1">resource server</dfn>,
client (called in this specification <dfn data-cite="RFC6749#section-1.1">authorization client</dfn> to avoid ambiguity), and
<dfn data-cite="RFC6749#section-1.1">authorization server</dfn>.
A storage server is a type of resource server that also conforms to the LWS storage specification.
</p>
</section>

<section id="authorization-protocol-flow">

<h3>Protocol Flow</h3>

<p>
This specification describes the interaction between a client and an authorization server as well as
the interaction between a client and a conforming storage server.
</p>

<p>
The interaction between the authorization server and the storage server is out of scope of this specification.
The authorization server may be the same server as the storage server or it may be a separate entity.
</p>

<section id="authorization-server-discovery">
<h4>Authorization Server Discovery</h4>

<p>
All protected resources managed by a storage server require a valid access token, generated by a trusted
authorization server. A client can discover the location of a trusted authorization server by making an
unauthorized HTTP request to a protected resource.
</p>

<p>
A storage server generating a 401 (Unauthorized) response MUST send a <code>WWW-Authenticate</code> header
field containing at least one conforming challenge. A conforming challenge will include the parameters described below:
</p>

<ul>
<li>
<strong><code>as_uri</code> REQUIRED</strong> — The value of this parameter is an absolute URI identifying the authorization server
where a client can retrieve an access token. The value of this parameter will be the same as the <code>iss</code> claim of a valid access token.
</li>
<li>
<strong><code>realm</code> REQUIRED</strong> — The value of this parameter is an absolute URI indicating the scope of protection.
This value will be included in the audience (<code>aud</code>) claim of an access token. A client MUST verify that
the URI of the originating request is logically contained within the <code>realm</code> presented in this response.
</li>
</ul>

<p>
Other headers and parameters MAY be included.
</p>

<p>
An example 401 response is included below.
</p>

<pre id="example-unauthorized-response" class="example">
HTTP/2 401 Unauthorized
Link: <https://storage.example/storage_1/metadata>; rel="storageDescription"
WWW-Authenticate: Bearer as_uri="https://authorization.example",
realm="https://storage.example/storage_1",
error="invalid_token"
</pre>
</section>

<section id="authorization-server-metadata">
<h4>Authorization Server Metadata</h4>

<p>
An authorization server MUST provide a metadata resource to allow clients to discover endpoint locations and capabilities as described
in [[!RFC8414]]. This metadata resource MUST be available at a URL with the path <code>/.well-known/lws-configuration</code>.
</p>

<p>
An authorization server SHOULD advertise the subject tokens that it supports by including a <code>subject_token_types_supported</code>
entry in the server metadata document. This entry is a JSON array containing a list of valid <code>subject_token_type</code> values
that can be supplied at the authorization server's token endpoint.
</p>

<p>
An example authorization server metadata resource is included below.
</p>

<pre id="example-authorization-server-metadata" class="example">
{
"issuer": "https://authorization.example",
"grant_types_supported": [
"urn:ietf:params:oauth:grant-type:token-exchange"],
"token_endpoint": "https://authorization.example/token",
"jwks_uri": "https://authorization.example/jwks",
"claims_supported": [
"sub",
"iss",
"client_id",
"aud"],
"response_types_supported": [
"token"],
"subject_token_types_supported": [
"urn:ietf:params:oauth:token-type:jwt",
"urn:ietf:params:oauth:token-type:id-token"]
}
</pre>

</section>

<section id="authorization-token-exchange">
<h4>Token Exchange</h4>

<p>
An LWS authorization server is a conforming OAuth 2.0 authorization server, capable of issuing access tokens to a client
for use with a storage server. In order to issue an access token, a client must first present a valid subject token,
such as an end-user credential, to the authorization server via OAuth 2.0 Token Exchange [[!RFC8693]].
</p>

<section id="authorization-token-exchange-request">

<h5>Request</h5>

<p>
The authorization server's token endpoint MUST support the <code>urn:ietf:params:oauth:grant-type:token-exchange</code>
grant type, as described in OAuth 2.0 Token Exchange [[!RFC8693]].
</p>

<p>
When performing the token exchange grant type, the following additional requirements apply:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert of RFC8693, but it seems to me that some of these requirements are directly "inherited" from RFC8693, while others are specific to LWS. It might be useful to clearly mark the difference.

</p>

<ul>
<li>The <code>resource</code> parameter is REQUIRED. The value of this parameter MUST be an absolute URI and will be used to populate the
<code>aud</code> (audience) claim in the resulting access token. The supplied value will be the same as the
<code>realm</code> parameter response in a <code>WWW-Authenticate</code> challenge. The authorization server
MUST reject any request in which the resource parameter identifies an unknown or untrusted storage.
</li>

<li>
The <code>subject_token</code> parameter is REQUIRED. The value of this parameter MUST include a valid subject token,
such as an end-user credential.
</li>

<li>
Before returning an access token to the client, the authorization server MUST successfully validate all presented tokens.
</li>
</ul>

<p>
Non-normative example of a token request (the <code>subject_token</code> parameter has been truncated).
</p>

<pre id="example-authorization-token-exchange-request" class="example">
POST /token HTTP/1.1
Host: authorization.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&amp;resource=https%3A%2F%2Fstorage.example%2Fstorage_1
&amp;subject_token=eyJ0eXAiOiJhcytqd3QiLCJhbGciO...fiK51VwhsxJ-siBMR-YFiA
&amp;subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aid_token
</pre>
</section>

<section id="authorization-token-exchange-response">
<h5>Response</h5>

<p>
If the token request is valid and the client is authorized to make the request, the authorization server response MUST
conform to Section 5.1 from the OAuth 2.0 Authorization Framework [[!RFC6749]]. The resulting access token MUST conform
to the JSON Web Token Profile for OAuth 2.0 Access Tokens [[!RFC9068]].
</p>

<p>
In addition, the access token must meet the following requirements:
</p>

<ul>
<li>
<code>sub</code> (subject) — <strong>REQUIRED</strong>. This claim MUST be an absolute URI identifying the agent performing the operation
</li>
<li>
<code>iss</code> (issuer) — <strong>REQUIRED</strong>. This claim MUST be the absolute URI of the authorization server
</li>
<li>
<code>client_id</code> (client id) — <strong>REQUIRED</strong>. This claim MUST be an absolute URI identifying the client.
</li>
<li>
<code>aud</code> (audience) — <strong>REQUIRED</strong>. This claim MUST include the absolute URI supplied by the client
in the resource parameter. This value will be used to restrict the entities for which the access token is valid. This will
be the same value as provided by a storage server in the <code>realm</code> parameter of a <code>WWW-Authenticate</code> challenge.
</li>
<li>
<code>exp</code> (expiration) — <strong>REQUIRED</strong>. Authorization servers SHOULD issue tokens with short lifetimes
(RECOMMENDED: 300 seconds or less) to limit exposure from token theft.
</li>
<li>
<code>iat</code> (issued at) — <strong>REQUIRED</strong>.
</li>
<li>
<code>jti</code> (JWT ID) — <strong>REQUIRED</strong>.
</li>
</ul>

<p>
A non-normative example of a successful token response is included below.
</p>

<pre id="example-authorization-token-exchange-successful-response" class="example">
HTTP/1.1 200 OK
Content-Type: application/json

{
"access_token":"eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso",
"token_type":"Bearer",
"expires_in":3600
}
</pre>

<p>
All invalid or unauthorized requests MUST result in an error response as described in Section 5.2 in
the OAuth 2.0 Authorization Framework [[!RFC6749]].
</p>

<pre id="example-authorization-token-exchange-error-response" class="example">
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error":"invalid_request"
}
</pre>
</section>

<section id="authorization-example-access-token" class="informative">
<h5>Example access token</h5>

<p>
An example access token issued by an authorization server is included below.
</p>

<pre id="example-authorization-access-token" class="example">
{
"kid": "ec51c6b2",
"kty": "EC",
"alg": "ES256",
"crv": "P-256",
"typ": "at+jwt"
}
.
{
"sub": "https://id.example/agent",
"iss": "https://authorization.example",
"client_id": "https://app.example/id",
"aud": "https://storage.example",
"exp": 1735686300,
"iat": 1735686000,
"jti": "550e8400-e29b-41d4-a716-446655440000"
}
.
signature
</pre>
</section>
</section>
<section id="authorization-token-validation">
<h4>Token Validation by a Storage Server</h4>

<p>
Once a client is in possession of an access token, it will present this token to a storage server.
The storage server is responsible for verifying this token before performing any operation.
</p>

<section id="authorization-token-validation-presentation">
<h5>Presentation</h5>

<p>
A client MUST present an access token to a storage server using the <code>Authorization</code> header
with an authentication scheme as defined in [[!RFC6750]].
</p>

<pre id="example-authorization-token-presentation" class="example">
Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the token is not the same as in the previous example. Is this deliberate?

While it is not clearly stated that this is a running example, I was assuming so far that the examples were making a consistent narrative.`

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't explicitly intended as a running example, but that is a good idea

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #51 for an adjustment of the access token so that this can be viewed as part of an authorization flow in a single session.

</pre>
</section>

<section id="authorization-token-validation-verification">
<h5>Validation</h5>

<p>
A storage server MUST validate an access token by performing the following checks, rejecting the request upon any failure:
</p>

<ul>
<li>
JWT Signature Validation: Verify the JWT signature using the authorization server's public key retrieved from the
<code>jwks_uri</code> specified in the authorization server metadata. Storage servers SHOULD cache these keys and
MUST support key rotation.
</li>
<li>
Issuer Validation: Verify the <code>iss</code> claim matches the expected authorization server identifier.
</li>
<li>
Audience Validation: Verify the <code>aud</code> claim contains exactly one value and this value is an absolute URI identifying the storage server which logically contains the target resource.
</li>
<li>
Temporal Validation, subject to an allowable clock skew between systems.
<ul>
<li>
Verify the current time is before the <code>exp</code> (expiration) claim.
</li>
<li>
Verify the current time is not before the <code>nbf</code> (not before) claim, if present.
</li>
<li>
Verify that the <code>iat</code> (issued at) claim is not in the future.
</li>
</ul>
</li>
</ul>

<p>
If validation fails, the storage server MUST return 401 Unauthorized with a <code>WWW-Authenticate</code> header
containing an appropriate error parameter (e.g., invalid_token, invalid_request, or insufficient_scope).
</p>

<p>
If the token is otherwise valid but an authorization policy does not allow the requested operation,
the storage server MUST reject the request.
</p>
</section>
</section>
</section>
45 changes: 45 additions & 0 deletions lws10-core/IANA-Considerations.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<section id="iana-well-known-registry">
<h3>well-known URI Registry</h3>

<p>
This specification adds the following value to the "Well-Known URIs" registry [[IANA.well-known]] established by RFC 5785 [[RFC5785]].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

</p>

<ul>
<li>
URI suffix: lws-configuration
</li>
<li>
Change controller: W3C
</li>
<li>
Specification document: Section 5 of LWS-Auth
</li>
<li>
Related information: (none)
</li>
</ul>
</section>

<section id="iana-oauth-authorization-server-metadata-registry">
<h3>OAuth Authorization Server Metadata Registry</h3>

<p>
This specification adds the following value to the "OAuth Authorization Server Metadata" registry [[IANA.OAuth.Parameters]] established by [[RFC8414]].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

</p>

<ul>
<li>
Metadata Name: token_subject_types_supported
</li>
<li>
Metadata Description: JSON array containing a list of the OAuth 2.0 "token_subject_type" values that this authorization server supports
</li>
<li>
Change Controller: W3C
</li>
<li>
Specification Document(s): Section 5 of LWS-Auth
</li>
</ul>
</section>
Loading