Aggregator Specification

Living Document,

Previous Versions:
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Ghent University - imec)

Abstract

This document has the specification of the aggregator.

1. Introduction

The introduction for the Aggregator specification will be expanded in future revisions.

2. Definitions

NOTE: that this is different from the Authorization Server (AS) that issues UMA RPT tokens. The IDP Servers are used to provide identity to users. The Authorization Servers checks this identity and issues RPT tokens for resource servers.

4. Public Metadata

5. Aggregator Registration

This section describes how aggregators are managed on the Aggregator Server level. The authorization for these endpoints is defined by the implementation and up to the Aggregator provider to decide. The user requires authenticated requests to manage their aggregator accounts on wich the Aggregator provider can base their authorization decisions. The tokens used in these requests (IPD_client_token) prove the identity of the user and the client (ClientID) used to access the aggregator.

5.1. Aggregator Creation

This section describes how clients can create an Aggregator. There exists different flows to create an aggregator depending on the registration type.

TODO where to add versioning info?

TODO where to use DPOP tokens?

TODO what about HTTP error handling?

5.1.1. provision Flow

The provision flow allows clients to create an Aggregator with its own identity. This lets resource owners target access-control policies at the aggregator’s dedicated WebID instead of having the aggregator impersonate another user’s WebID.

1. Client starts flow with Aggregator Server

The client calls the registration endpoint authenticated with its IPD_client_token.

POST /registration HTTP/1.1
Authorization: Bearer <IPD_client_token>
Content-Type: application/json

{
  "registration_type": "provision",
}

2. Aggregator Server provisions a WebID and registers it at the IDP

The Aggregator Server creates a WebID document and registers a new account with an IDP for that WebID. It also registers (or reuses) a confidential client that represents the aggregator itself and stores the associated client_id/client_secret. Using those credentials the Aggregator Server performs a client credentials grant to obtain the IDP_aggregator_token (and accompanying refresh token) that authorize the aggregator acting under its own WebID.

3. Aggregator Server creates an aggregator

Using the obtained tokens, the Aggregator Server creates an aggregator linked to the user, and returns the aggregator metadata and newly created WebID.

5.1.2. authorization_code Flow

The authorization_code flow allows clients to create an aggregator that acts on behalf of the end-user, but with a token that is scoped specifically for the aggregator.

PlantUML Diagram

1. Client starts flow with Aggregator Server

The client begins by asking the Aggregator to bootstrap an authorization_code registration and indicate which authorization server should be used. The Aggregator responds with the public parameters required for the OIDC authorization request.

POST /registration HTTP/1.1
Authorization: Bearer <IPD_client_token>
Content-Type: application/json

{
  "registration_type": "authorization_code",
  "authorization_server": "https://as.example"
}

1.1 Aggregator dereferences the WebID to discover the IDP

Using the UMA authorization context, the Aggregator dereferences the user’s WebID profile document to locate the Solid/OIDC issuer metadata and determine which IDP endpoints must be used for the next steps.

1.2 Aggregator responds with public parameters

After finishing WebID discovery and storing the PKCE verifier/state, the Aggregator returns the public parameters required for the IDP authorization request.

HTTP/1.1 201 Created
Content-Type: application/json

{
  "client_id": "https://aggregator.example/client.jsonld",
  "code_challenge": "1uLSZp2...",
  "code_challenge_method": "S256",
  "state": "1eb7c8f5..."
}

The Aggregator generates the PKCE verifier/challenge pair plus a random state, persists them together with the pending registration, and returns only the public portions (client_id, code_challenge, state) to the client application. The authorization_server value identifies the UMA Authorization Server (AS) that governs resource policies; once the Aggregator evaluates the user’s authorization token it can dereference its WebID and determine which Identity Provider (IDP) must be used for the subsequent OIDC exchange.

TODO How does the aggregator register with the AS?

2. Client sends the end-user through the IDP authorization endpoint

Using the information supplied by the Aggregator, the client constructs an authorization request against the Identity Provider. The redirect_uri is under control of the client application and MUST already be registered in the JSON-LD client metadata document hosted at the dereferenceable client_id.

GET https://idp.example/authorize?
    response_type=code&
    client_id=https%3A%2F%2Faggregator.example%2Fclient.jsonld&
    redirect_uri=https%3A%2F%2Fapp.example%2Fcallback&
    scope=openid%20webid%20offline_access&
    code_challenge=1uLSZp2...&
    code_challenge_method=S256&
    state=1eb7c8f5...

3. User authenticates and consents at the IDP

The IDP performs its usual login and consent screens, after which it issues an authorization_code tied to the Aggregator’s confidential client.

4. IDP redirects the user agent back to the client’s redirect_uri

HTTP/1.1 302 Found
Location: https://app.example/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=1eb7c8f5...

5. Client posts the authorization code back to the Aggregator

The client sends the code, redirect URI, and echoed state to the registration endpoint so the Aggregator can finish the flow.

POST /registration HTTP/1.1
Authorization: Bearer <IPD_client_token>
Content-Type: application/json

{
  "registration_type": "authorization_code",
  "code": "SplxlOBeZQQYbYS6WxSbIA",
  "redirect_uri": "https://app.example/callback",
  "state": "1eb7c8f5..."
}

5.1 Aggregator dereferences the client metadata

The Aggregator dereferences the client_id JSON-LD document to confirm the registered redirect URIs, contact metadata, and other security requirements, then verifies that the supplied redirect_uri belongs to that set and that the returned state matches the stored nonce.

5.2 Aggregator redeems the authorization code at the IDP token endpoint

POST /token HTTP/1.1
Host: idp.example
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <aggregator-client-auth>

grant_type=authorization_code&
code=SplxlOBeZQQYbYS6WxSbIA&
redirect_uri=https%3A%2F%2Fapp.example%2Fcallback&
client_id=https%3A%2F%2Faggregator.example%2Fclient.jsonld&
code_verifier=Hjs8...stored...

The IDP verifies the authorization_code, ensures the redirect_uri matches the original authorization request, and recomputes the PKCE challenge from the supplied code_verifier. If everything matches, it returns:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "<IDP_aggregator_token>",
  "refresh_token": "<refresh_token>",
  "token_type": "Bearer",
  "expires_in": 3600
}

5.3 Aggregator finalizes the account and responds

Using the issued tokens, the Aggregator creates the aggregator account linked to the user and returns the aggregator account details to the client.

HTTP/1.1 201 Created
Content-Type: application/json

{
  "aggregator_id": "agg-7890",
  "authorization_server": "https://as.example",
  "webid": "https://aggregator.example/webids/agg-7890#id",
  "token_expires_in": 3600
}

5.1.3. client_credentials Flow

The client_credentials flow allows clients to create an aggregator by using the OAuth2 Client Credentials Flow to obtain an OIDC token from an Identity Provider (IDP) server.

NOTE: This flow gives the aggregator complete access to the user’s resources and policies without user consent. This flow should only be used in trusted environments, or when a user creates an account for the aggregator.

1. Client starts flow with Aggregator Server

The client explicitly asks the Aggregator to act with full credentials for the provided WebID, indicating which UMA Authorization Server manages the protected resources. Because this flow hands the Aggregator long-lived credentials, it should only be used when the user intentionally provisions the Aggregator as a trusted service account.

POST /registration HTTP/1.1
Authorization: Bearer <IPD_client_token>
Content-Type: application/json

{
  "registration_type": "client_credentials",
  "authorization_server": "https://as.example",
  "webid": "https://user.example/webid#me",
  "username": "alice@example.org",
  "password": "s3cr3t-password"
}

2. Aggregator Server performs credential bootstrap with the IDP

The Aggregator uses the supplied username/password (plus the WebID context) to authenticate against the Identity Provider’s management or token endpoint, registering (or reusing) a confidential client that represents the Aggregator’s service account for that user. It then runs an OAuth 2.0 client_credentials grant using the obtained client_id/client_secret to mint an IDP_aggregator_token scoped to the user’s WebID.

POST /token HTTP/1.1
Host: idp.example
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <aggregator-client-auth>

grant_type=client_credentials&
webid=https%3A%2F%2Fuser.example%2Fwebid%23me&
scope=openid%20webid%20offline_access

The IDP issues access and refresh tokens that grant the Aggregator the same capabilities as the user’s own credentials.

HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "<IDP_aggregator_token>",
  "refresh_token": "<refresh_token>",
  "token_type": "Bearer",
  "expires_in": 7200
}

3. Aggregator Server creates (or updates) the aggregator account

Armed with the IDP_aggregator_token, the Aggregator persists the account for the specified WebID, associates it with the requesting user, and returns the aggregator account metadata (aggregator identifier, token expiry, UMA AS linkage, etc.) to the client.

5.1.4. device_code Flow

NOTE: TODO This flow is not yet specified.

5.2. Aggregator Login

The login flow allows users to update the tokens of their existing aggregator. This flow can be used to refresh the tokens in case they have expired. The flow is the same as with creating an aggregator but a aggregator_id parameter is provided in step 1. The exact steps depend on the registration_type used when creating the aggregator. For example for the authorization_code flow:
POST /registration HTTP/1.1
Authorization: Bearer <IPD_client_token>
Content-Type: application/json
{
    "registration_type": "authorization_code",
    "aggregator_id": "agg-7890"
}

5.3. Aggregator Deletion

The delete flow allows users to delete their existing aggregator. This flow is done by doing a DELETE request to the registration endpoint with the aggregator_id parameter.
DELETE /registration HTTP/1.1
Authorization: Bearer <IPD_client_token>
Content-Type: application/json
{
    "aggregator_id": "agg-7890"
}

6. Authentication and Authorization

The Aggregator relies on the Authorization for Data Spaces (A4DS) specification to authenticate clients and authorize access to resources. The Aggregator Service authenticates the Client using OIDC and obtains access tokens for upstream Resource Servers.

6.1. Client Flow

The Aggregator Service authenticates the Client with OIDC to obtain an access token for a Resource Server. The Aggregator Service relies on an OIDC access token linked to the Aggregator’s client identifier. The Aggregator SHOULD request the additional scope urn:knows:uma:scopes:derivation-creation from the Authorization Server of a Resource Server to enable the Aggregator functionality. The Authorization Server MUST return a derivation_resource_id together with the access token. The Aggregator MAY delete the derivation_resource_id when it is no longer needed. The Aggregator Service MUST update the resource registration at its Authorization Server to signal that it used this resource identifier to create derived resources.

{
  "resource_scopes": [ ... ],
  "resource_relations": {
    "prov:wasDerivedFrom": {
      "issuer": "https://as.example.org",
      "derivation_resource_id": "handle-id-1"
    }
  }
}

The Authorization Server MUST invalidate previous access tokens (for example by marking them inactive) if they are linked to a derived resource whose identifier has been consumed.

TODO: clarify whether polling for a new derivation_resource_id is necessary, or whether the Aggregator can request the Authorization Server for a normal scope referencing the identifier or supply the identifier as a hint when requesting with a ticket.

6.2. Resource Server Flow

When a Client requests access to a derived resource from the Aggregator Service, a normal UMA flow follows. During ticket creation, the Aggregator validates that the derivation_resource_id used to create the derived resource is still valid. If it is invalid, the Aggregator MUST recreate the Aggregator Service. The Aggregator Authorization Server MAY respond with a need_info error requesting access tokens for upstream resources. In that case, the Authorization Server MUST add the issuer, derivation_resource_id, and resource_scopes entries to the required_claims array. The issuer identifies the upstream Authorization Server. The derivation_resource_id contains the identifier (or identifiers) provided when the Aggregator Service requested an upstream access token. The resource_scopes list enumerates the scopes required to access the upstream resource and MUST include a derivation scope.

{
  "error": "need_info",
  "ticket": "tkt-A2",
  "required_claims": [
    {
      "claim_token_format": "urn:ietf:params:oauth:token-type:access_token",
      "details": {
        "issuer": "https://a.example.org",
        "derivation_resource_id": "handle-id-1",
        "resource_scopes": [ "urn:knows:uma:scopes:derivation-read" ]
      }
    }
  ]
}

The Client SHOULD then request access tokens from the Authorization Server of the upstream Resource Server with the required scopes, including the derivation scope.

{
  "grant_type": "urn:ietf:params:oauth:grant-type:uma-ticket",
  "permissions": [
    {
      "resource_id": "handle-id-1",
      "scopes": [ "urn:knows:uma:scopes:derivation-read" ]
    }
  ],
  "claim_token": "OIDC_token",
  "claim_token_format": "http://openid.net/specs/openid-connect-core-1_0.html#IDToken"
}

Finally, the Client retries the request to the Aggregator Service with the access tokens it received from the upstream Resource Servers.

{
  "grant_type": "urn:ietf:params:oauth:grant-type:uma-ticket",
  "ticket": "tkt-A2",
  "claim_tokens": [
    {
      "claim_token": "OIDC_token",
      "claim_token_format": "http://openid.net/specs/openid-connect-core-1_0.html#IDToken"
    },
    {
      "claim_token_format": "urn:ietf:params:oauth:token-type:access_token",
      "claim_token": "as-at-2"
    }
  ]
}

The Aggregator Authorization Server MUST verify the provided access tokens with the upstream Authorization Servers to confirm that the Client is authorized to access the upstream resources.

7. Creating an Aggregator Service

This section will describe how to create an Aggregator Service in more detail.

8. Using an Aggregator Service

Guidance for using an Aggregator Service will follow as the specification matures.

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

References

Normative References

[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119

Issues Index

TODO where to add versioning info?
TODO where to use DPOP tokens?
TODO what about HTTP error handling?
TODO How does the aggregator register with the AS?