) .
+package "Non-normative Example 2: Combined Issuer and Broker" {
+
+component "Visa Assertion Source (1)\norganization" as VisaSource1
+component "Visa Assertion Source (2)\norganization" as VisaSource2
+component "Visa Assertion Source (...)\norganization" as VisaSourceN
+
+component "Visa Issuer and Broker\nservice" as Broker
+component "Client\napplication" as Client
+component "Passport\nClearinghouse\nservice" as ClearingHouse
+}
-3. Conform to [revocation requirements](#token-revocation).
+VisaSource1 --> Broker
+VisaSource2 --> Broker
+VisaSourceN --> Broker
+Broker --> Client
+Client --> ClearingHouse
-4. Protection of Confidential Information
+@enduml
+
+
+{% hr2 %}
+
+## Profile Requirements
+
+### Conformance for Clients/Applications
+
+Clients are applications which want to access data on behalf of users, and are responsible for using the standard described here to do so securely.
+
+1. OAuth defines two client types in [section 2.1](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1) of [[RFC6749]](#ref-rfc6749).
+ 1. Confidential clients (which are able to keep the client secret secure, typically server-side web-applications)
+ MUST implement OAuth2 Authorization Code
+ Flow (see OIDC Basic Client Implementer's Guide 1.0 [[OIDC-Client]](#ref-oidc-client)).
+
+ 2. Public clients (single pages apps or mobile apps) SHOULD implement Authorization Code Flow
+ with [[PKCE]](#ref-rfc7636).
+
+2. Protection of Confidential Information
1. Sensitive information (e.g., including client secrets,
- authorization codes, id_tokens, access_tokens) will be passed over
- encrypted channels as per
- [OpenIDC Implementation Guide](https://openid.net/specs/openid-connect-basic-1_0.html).
+ authorization codes, id_tokens, access_tokens) MUST be passed over
+ encrypted channels as per [[OIDC-Client]](#ref-oidc-client).
2. All responses that contain tokens, secrets, or other sensitive
information MUST include the following HTTP response header fields and
- values (as per [OpenIDC Implementation Guide](https://openid.net/specs/openid-connect-basic-1_0.html)).
+ values as per [[OIDC-Client]](#ref-oidc-client).
- 1. Cache-Control: no-store
+ 1. `Cache-Control: no-cache, no-store`
- 2. Pragma: no-cache
-
-5. MUST provide protection against Client attacks as outlined in
- [RFC 6819](https://tools.ietf.org/html/rfc6819).
+ 2. `Pragma: no-cache`
-#### Conformance for Brokers
+3. Clients MUST provide protection against client attacks as outlined in
+ [[RFC6819]](#ref-rfc6819).
-1. Brokers operate downstream from IdPs or provide their own IdP service. They
- issue id_tokens and access_tokens (and potentially refresh tokens) for
- consumption within the GA4GH compliant environment.
+{% hr3 %}
- 1. A Broker MUST issue both [Passport-Scoped Access Tokens](#term-passport-scoped-access-token)
- (access_tokens) and id_tokens.
+### Conformance for Brokers
+Brokers operate downstream from IdPs or provide their own IdP service. They issue id_tokens
+and access_tokens (and potentially refresh tokens) for consumption within the GA4GH compliant environment.
- 1. This document makes no specifications for id_tokens.
+1. Broker MUST be an OpenID Provider
+
+ 1. Broker MUST conform to the OIDC Core specification [[OIDC-Core]](#ref-oidc-core).
- 2. Access_tokens MUST be in JWS format
+ 2. Broker MUST support the OIDC Discovery specification [[OIDC-Discovery]](#ref-oidc-discovery)
+ and provide proper [metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata)
+ (i.e. must have a `jwks_uri` as required that’s reachable by a Passport Clearinghouse)
- 1. Access tokens for GA4GH use MUST be a [GA4GH JWT](#ga4gh-jwt-format) using
- [Passport-Scoped Access Token format](#passport-scoped-access-token-issued-by-broker).
+ 3. A Broker MUST issue [Passport-Scoped Access Tokens](#term-passport-scoped-access-token)
+ (access_tokens).
- 2. Access tokens do not contain GA4GH Claims directly in the access token.
+ 1. This document makes no specifications beyond those in [[OIDC-Core]](#ref-oidc-core).
- 3. Access tokens MAY contain non-GA4GH Claims directly in the access token.
+ 4. Access tokens MUST be in JWS format
-2. Broker MUST support [OIDC Discovery
- spec](https://openid.net/specs/openid-connect-discovery-1_0.html)
+ 1. Access tokens for GA4GH use MUST be a [GA4GH JWT](#ga4gh-jwt-formats) using
+ [Passport-Scoped Access Token format](#passport-scoped-access-token).
- 1. MUST include and support proper
- [Metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata)
- (i.e. must have a `jwks_uri` as required that’s reachable by a Claim
- Clearinghouse)
+ 2. Access tokens MUST NOT contain [GA4GH Claims](#term-ga4gh-claim) directly in the access token.
-3. Broker MUST support public-facing /userinfo endpoint as per [section 5.3 of the OIDC
- specification](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo).
+ 3. Access tokens MAY contain additional non-GA4GH Claims directly in the access token.
- 1. When presented with a valid access token, the /userinfo endpoint MUST return
- claims in the specified
- [User Info Format](#claims-sent-to-data-holder-by-a-broker-via-userinfo) using
- either an `application/json` or `application/jwt` encoding.
+2. Broker MUST support a [Token Endpoint](#term-token-endpoint) and [UserInfo Endpoint](#term-userinfo-endpoint).
- 2. The Broker MUST include the claims_parameter_supported in the discovery service
- to indicate whether or not the Broker supports the [OIDC claims request
- parameter](https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter)
- on /userinfo to subset which claim information will be returned. If the Broker
- does not support the OIDC claims request parameter, then all claim information
- for the provided scopes eligible for release to the requestor MUST be returned.
-
-4. Broker MUST provide protection against attacks as outlined in
- [RFC 6819](https://tools.ietf.org/html/rfc6819).
+ 1. [Token Exchange](#term-token-exchange) at the Token Endpoint SHOULD be used for [Visas](#term-visa) in
+ preference to the UserInfo Endpoint.
+
+ 2. When presented with a valid [Passport-scoped Access Token](#term-passport-scoped-access-token),
+ the UserInfo endpoint MUST provide [Visas](#term-visa) as described in the section
+ [Visas provided by a Broker via UserInfo Endpoint](#visas-provided-by-a-broker-via-userinfo-endpoint).
-5. The user represented by the identity of the access token MUST have agreed to
- release claims related to the requested scopes as part of generating tokens
- that can expose GA4GH Claims that represent user data or permissions.
+3. Brokers operate downstream from IdPs or provide their own IdP service. They
+ issue id_tokens and access_tokens (and potentially refresh tokens) for
+ consumption within the GA4GH compliant environment.
+
+4. Broker MAY support [Token Exchange](#term-token-exchange). If implemented, it MUST behave as described
+ for passport issuance in [Conformance For Passport Issuers](#conformance-for-passport-issuers).
+
+5. Broker MUST provide protection against attacks as outlined in
+ [[RFC6819]](#ref-rfc6819).
+
+6. The user represented by the identity of the access token MUST have agreed to
+ release claims related to the requested scopes as part of generating tokens.
Brokers MUST adhere to
- [section 3.1.2.4 of the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#Consent).
+ [section 3.1.2.4](https://openid.net/specs/openid-connect-core-1_0.html#Consent)
+ of [[OIDC-Core]](#ref-oidc-core).
- 1. The user represented by a Researcher Identity MUST approve the release
+ 1. The user represented by a researcher identity MUST approve the release
of these claims to relying parties with sufficient granularity to
allow for responsible disclosure of information best practices as well
as to meet privacy regulations that may be applicable within or between
@@ -309,210 +521,219 @@ the Broker.
3. A user's withdrawal of this agreement does not need to apply to
previously generated access tokens.
-6. By signing an access token, an Broker asserts that the GA4GH Claims that
- token makes available at the /userinfo endpoint -- not including any
- Visas -- were legitimately derived from their [Claim
- Sources](#term-claim-source), and the content is presented and/or
- transformed without misrepresenting the original intent.
-
- When a Broker acts as a Visa Issuer and signs Visas, then those signatures
- adhere to the same assertion criteria as outlined in the [Conformance
+7. When a Broker acts as a Visa Issuer then it MUST adhere to the [Conformance
for Visa Issuers](#conformance-for-visa-issuers) section of this
specification.
- When a Broker provides Embeded Tokens from other Visa Issuers, it is providing
+ When a Broker provides Visas from other Visa Issuers, it is providing
them "as is" (i.e. it provides no additional assurance as to the quality,
- authenticity, or trustworthiness of the claims from such tokens and any such
+ authenticity, or trustworthiness of the [Claims](#term-claim) from such tokens and any such
assurances are made by the issuer of the Visa, i.e. the Visa Issuer).
-
-#### Conformance for Visa Issuers
+{% hr3 %}
-1. A [Visa Issuer](#term-visa-issuer) MUST provide one or more of the following
- types of [Visas](#term-visa):
- 1.
- **Visa Access Token** -- The Visa Issuer is providing an OIDC provider
- service and issues OIDC-compliant access tokens in a specific format that can
- be used as a Visa.
-
- 1. The Visa payload MUST contain the "openid" scope. That
- is, it has a `scope` JWT claim that contains "openid" as a
- space-delimited substring.
-
- 2. Visa is a JWS string and follows the [Visa Access Token
- Format](#visa-access-token-format). This includes
- having GA4GH Claims as JWT claims directly in the Visa.
-
- 3. Visa Issuer MUST support [OIDC Discovery
- spec](https://openid.net/specs/openid-connect-discovery-1_0.html),
- and provide `jwks_uri` as
- [Metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata)
- that may be reachable by a Claim Clearinghouse.
-
- 4. Visa Issuer MUST support public-facing
- /userinfo endpoint. When presented with a valid Visa Access
- Token, the /userinfo endpoint MUST return a success status
- and MAY return the current values for GA4GH Claims that were
- included within the Visa Access Token, however returning
- GA4GH Claims from the /userinfo endpoint for Visa Access
- Tokens is OPTIONAL.
-
- 5. If the Visa Access Token's `exp` exceeds the `iat` by
- more than 1 hour, the Visa Issuer should expect
- Claim Clearinghouses to use [Access Token Polling](#at-polling) and
- MUST provide a means to revoke Visa Access Tokens. The
- /userinfo endpoint MUST return an HTTP status 401 as per
- [RFC6750 section 3.1](https://tools.ietf.org/html/rfc6750#section-3.1)
- when provided an Visa Access Token that has completed the
- revocation process.
-
- 6. The JWS header MUST NOT have `jku` specified.
-
- 7. Visa Issuer MUST provide protection against
- attacks as outlined in [RFC
- 6819](https://tools.ietf.org/html/rfc6819).
-
- 2.
- **Visa Document Token** -- The Visa Issuer does not need to be a
- be a OIDC provider, and MAY provide tokens of this type without any
- revocation process.
-
- 1. The JWS header contains `jku` as specified by [RFC7515 Section
- 4.1.2](https://tools.ietf.org/html/rfc7515#section-4.1.2), and
- provides the corresponding public-facing endpoint to fetch
- the public key used to sign the Visa Document Token.
-
- 2. Follows the [Visa Document Token
- Format](#visa-document-token-format).
+
+### Conformance for Visa Issuers
+
+Visa Issuers issue signed JWTs (Visas) asserting facts about researchers, which may be used by Passport Clearinghouses
+to justify granting access to data. This specification defines the format of the Visas and endpoints Visa Issuers
+should have in order for Passport Clearinghouses to validate those Visas. This document _does not_ specify how a Broker
+obtains Visas contained in a Passport or returned from the Userinfo Endpoint.
- 3. The token is not treated as an access token, but validity
+1. A [Visa Issuer](#term-visa-issuer) MUST provide one or more of the following
+ types of [Visas](#term-visa):
+
+ 1.
+
+
+
+ **Visa Document Token** -- The Visa Issuer does not need to
+ be an OIDC provider, and MAY provide tokens of this type without any
+ revocation process.
+
+ 1. The token MUST conform with JWS format [[RFC7515]](#ref-rfc7515) requirements
+ 2. The token MUST be signed by a [Visa Issuer](#term-visa-issuer).
+ 3. The JWS header MUST contain `jku` as specified by [section
+ 4.1.2](https://tools.ietf.org/html/rfc7515#section-4.1.2) of [[RFC7515]](#ref-rfc7515), and
+ MUST provide the corresponding endpoint to fetch
+ the public key used to sign the Visa Document Token.
+ 4. The token is not treated as an access token, but validity
checks outlined elsewhere in this specification still apply.
+ 5. [Visas](#term-visa) MUST be signed with a [conformant signing algorithm](#signing-algorithms).
+ 6. The `scope` [Claim](#term-claim), if included, MUST NOT contain "openid" as
+ a space-delimited substring of the `scope` JWT [Claim](#term-claim).
+ 7. Payload [Claims](#term-claim) are specified in
+ [Visa Format](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md#visa-format) in [[Passport]](#ref-passport).
+
+ 2.
+ **Visa Access Token** -- The Visa Issuer is providing an OIDC provider
+ service and issues OIDC-compliant access tokens in a specific format that can
+ be used as a Visa. Details are specified in the AAI Profile 1.0 specification.
+
+ The Visa Access Token is proposed for removal in a future
+ version of the specification. Current and future specifications emphasize use of Visas embedded in a Passport, which are not access tokens. New implementations should issue Visas
+ as Visa Document Tokens.
+
+2. By signing a Visa, a Visa Issuer asserts that
+ the [Visa Assertions](#term-visa-assertion) made available by the Visa were legitimately derived
+ from their [Visa Assertion Sources](#term-visa-assertion-source), and the content is
+ presented and/or transformed without misrepresenting the original intent.
- 4. MUST conform to [token limited-life or revocation
- requirements](#token-revocation), even if no Visa token
- revocation process is provided.
+{% hr3 %}
- 5. The `scope` JWT claim, if included, MUST NOT contain "openid" as
- a space-delimited substring.
+### Conformance for Passport Issuers
+
+Passport Issuers are used to package Visas into signed Passports. Passports are signed JWTs
+that use [this format](#passport-format) to contain Visas.
+
+1. Passport Issuers MUST be Brokers.
+
+2. Passports MUST be signed with a [conformant signing algorithm](#signing-algorithms).
-2. A Visa Issuer MAY generate the `exp` timestamp to enforce
- its policies and allow Claim Clearinghouses to understand the intent of
- how long the claim may be used before needing to return to the Visa Issuer
- to refesh the claim. As a non-normative example, if a
- GA4GH claim expires in 25 years (or even never expires explictly in the
- Claim Repository), the Visa Issuer could set the `exp` to
- 1 day into the future plus issue a refresh token in order to force the
- refresh token to be used when a downstream Claim Clearinghouse is still
- interested in using such a claim after 1 day elapses.
-
-3. By signing a Visa, a Visa Issuer asserts that
- the GA4GH claims made available by the token were legitimately derived
- from their [Claim Sources](#term-claim-source), and the content is
- presented and/or transformed without misrepresenting the original intent,
- except for accommodating for `exp` timestamps to be represented as
- indicated above.
-
-#### Conformance for Claim Clearinghouses (consuming Access Tokens to give access to data)
-
-1. Claim Clearinghouses MUST trust at least one Broker.
-
- 1. Claim Clearinghouses MAY trust more than one Broker
+3. Passports MAY be issued from a [Token Endpoint](#term-token-endpoint) using [Token Exchange](#term-token-exchange), with the following clarifications:
+
+ 1. The Token Endpoint MAY also support other OAuth2 grant types.
+
+ 2. Client authentication is REQUIRED (using [OAuth2 client authentication](https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1) in [[RFC6749]](#ref-rfc6749) is RECOMMENDED).
+
+ 3. The `requested_token_type` parameter MUST be present with the value `urn:ga4gh:params:oauth:token-type:passport`.
+
+ 4. The `subject_token` parameter value MUST be a valid [Passport-Scoped Access Token](#term-passport-scoped-access-token).
+
+ 5. The `subject_token_type` parameter value MUST be `urn:ietf:params:oauth:token-type:access_token`.
+
+ 6. The Token Endpoint MAY accept or require any other optional parameters defined in [[RFC8693]](#ref-rfc8693).
+
+
+*Passport Issuing via [Token Exchange](#term-token-exchange) (non-normative example)*
+
+{% plantuml %}
+
+hide footbox
+skinparam BoxPadding 10
+skinparam ParticipantPadding 20
+
+box "Researcher" #eee
+actor "User Agent" as user
+participant Client as client
+end box
+
+box "AAI"
+participant "Broker and Passport Issuer" as broker
+end box
+
+box "Data Access Committee (1)"
+participant "Visa Issuer (1)" as issuer1
+end box
+
+box "Data Access Committee (2)"
+participant "Visa Issuer (2)" as issuer2
+end box
+
+==OIDC==
+
+user -> client : Initiates login
+client -> user : Send redirect to Broker
+user -> broker : Follow redirects
+ref over broker
+Broker authenticates user
+(potentially with external IdP)
+end ref
+broker -> user : Send redirect to client with authorization code
+user -> client : Follow redirect with code
+
+client -> broker : Request Passport-Scoped Access Token
+broker -> client : Respond with Passport-Scoped Access Token
+
+==Token Exchange==
+
+client -> broker : Request to exchange Passport-Scoped \nAccess Token for Passport
+
+ref over broker, issuer1, issuer2
+Signed visas can be sourced from multiple visa issuers - either on demand or via batch transfer/cached
+end ref
+
+broker <-> issuer1 : Obtain Visa A
+broker <-> issuer2 : Obtain Visa B
+broker <-> issuer2 : Obtain Visa C
+client <- broker : Response with Passport containing Visas A, B, C
+
+
+{% endplantuml %}
+
+
+{% hr3 %}
+
+### Conformance for Passport Clearinghouses
+
+Passport Clearinghouses consume Passports containing Visas in order to grant access to data.
+
+1. Passport Clearinghouses MUST trust at least one Broker.
+
+ 1. Passport Clearinghouses MAY trust more than one Broker
- 2. The responsibility of risk assessment of a Broker is on the Claim Clearinghouse to trust an access token. RECOMMENDED to trust the minimum set of Brokers required to obtain the access token payload.
+ 2. The Passport Clearinghouse is responsible for assessing the risk in choosing to trust a token from a Broker.
-2. Claim Clearinghouses MUST either check the validity of the access token or treat the access
+2. Passport Clearinghouses MUST process access tokens to access a Broker's Token or UserInfo Endpoint to get access to Visas OR MUST process Passports directly.
+
+ 1. For access token flows, Passport Clearinghouses MUST either check the validity of the access token or treat the access
token as opaque.
- 1. If treating the token as a JWT a Claim Clearinghouse:
-
- 1. Even though JWTs are expected to be submitted against /userinfo, a Claim Clearinghouse SHOULD check the Token’s signature via JWKS or having stored the
- public key.
-
- 1. A metadata URL (.well-known URL) SHOULD be used here to use the
- jwks_uri parameter.
-
- 2. MUST check `iss` attribute to ensure a trusted Broker has generated
- the token.
-
- 1. If evaluating a Visa, trust MUST be established based
- on the signer of the Visa itself. In Claim
- Clearinghouses participating in open federation, the Claim
- Clearinghouse does not necessarily have to trust the Broker that
- includes Visas within another token in order to use
- the Visa (although the Claim Clearinghouse MAY require
- any other Broker involved in the propagation of the claims to
- also be trusted if the Claim Clearinghouse needs to restrict its
- trust model).
-
- 3. MUST check `exp` to ensure the token has not expired.
-
- 4. MAY additionally check `aud` to make sure Relying Party is trusted
- (client_id).
-
- 2. If treating the token as an opaque a Claim Clearinghouse MUST know in
- advance where to find a corresponding /userinfo. This may limit the
- functionality of accepting tokens from some Brokers.
-
-3. Claim Clearinghouse or downstream applications MAY use [/userinfo
- endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)
- (derived from the access_token JWT’s `iss`) to request claims and MAY make
- use of the [OIDC claims request
- parameter](https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter)
- to subset which claims are requested if supported by the Broker for the
- claims in question.
-
-4. Claim Clearinghouses service can be a Broker itself and would follow the
+
+ 2. For Passport flows, Passport Clearinghouses MUST check the validity of the Passport.
+
+3. A Passport Clearinghouse service can be a Broker itself and would follow the
[Conformance For Brokers](#conformance-for-brokers).
-5. Claim Clearinghouses MUST provide protection against attacks as outlined in
- [RFC 6819](https://tools.ietf.org/html/rfc6819).
+4. Passport Clearinghouses MUST provide protection against attacks as outlined in
+ [[RFC6819]](#ref-rfc6819).
- 1. Section 5.1.6 of RFC 6819 contains a SHOULD section that states `Ensure that client applications do not share tokens with 3rd parties.` This profile provides a mechanism for Clearinghouses to consume access tokens from multiple brokers in a manner that does not involve 3rd parties. Client applications SHOULD take care to not spread the tokens to any other services that would be considered 3rd parties.
+ 1. [Section 5.1.6](https://www.rfc-editor.org/rfc/rfc6819.html#section-5.1.6) of [[RFC6819]](#ref-rfc6819) states `Ensure that client applications do not share tokens with 3rd parties.` This profile provides a mechanism for Clearinghouses to consume access tokens from multiple brokers in a manner that does not involve 3rd parties. Client applications SHOULD take care to not spread the tokens to any other services that would be considered 3rd parties.
-6. If making use of [Visas](#term-visa):
+5. If making use of [Visas](#term-visa):
- 1. The Claim Clearinghouse MUST validate that all token checks pass (such as
- the token hasn’t expired) as described elsewhere in this specification and
+ 1. The Passport Clearinghouse MUST validate that all JWT checks pass (such as
+ the JWT hasn’t expired) as described elsewhere in this specification and
the underlying OIDC specifications.
2. If making use of [Visa Access Tokens](#term-visa-access-token):
-
+
1. Token checks MUST be performed to ensure it complies with the access
token specification.
-
+
2. In addition to other validation checks, a Visa is considered
- invalid if it is more than 1 hour old (as per the `iat` claim) AND
+ invalid if it is more than 1 hour old (as per the `iat` [Claim](#term-claim)) AND
[Access Token Polling](#at-polling) does not confirm that the token is still
valid (e.g. provide a success status code).
-
+
3. If making use of [Visa Document Tokens](#term-visa-document-token):
- 1. Fetching the public keys using the `jku` is not required if a Claim
+ 1. Fetching the public keys using the `jku` is not required if a Passport
Clearinghouse has received the keys for the given `iss` via a trusted,
out-of-band process.
- 2. If a Claim Clearinghouse is to use the `jku` URL to fetch the public
+ 2. If a Passport Clearinghouse is to use the `jku` URL to fetch the public
keys to verify the signature, then it MUST verify that the `jku` is
- trusted for the given `iss` as part of the Claim Clearinghouse's
+ trusted for the given `iss` as part of the Passport Clearinghouse's
trusted issuer configuration. This check MUST be performed before
calling the `jku` endpoint.
-7. **Access Token Polling**: Clients MAY use access tokens,
- including Visas, to occasionally check which claims are still valid
- at the associated /userinfo endpoint in order to establish whether the user
- still meets the access requirements.
-
+6. **Access Token Polling**: Clients MAY use access tokens,
+ including Visas, to occasionally check which Visas are still valid
+ at the associated Token or UserInfo Endpoint in order to establish
+ whether the user still meets the access requirements.
+
This MUST NOT be done more than once per hour (excluding any optional retries)
- per Claim Clearinghouse. Any request retries MUST include exponential backoff
+ per Passport Clearinghouse. Any request retries MUST include exponential backoff
delays based on best practices (e.g. include appropriate jitter). At a
minimum, the client MUST stop checking once any of the following occurs:
1. The system can reasonably determine that authorization related to these
- claims is not longer needed by the user. For example, all downstream cloud
+ [Claims](#term-claim) is no longer needed by the user. For example, all downstream cloud
tasks have terminated and the related systems will no longer be using the
access token nor any downstream tokens that were authorized by evaluating
- access requirements against claims in the token.
+ access requirements against [Claims](#term-claim) in the token.
2. The JWT access token has expired as per the `exp` field.
@@ -520,40 +741,60 @@ the Broker.
administrator has revoked the access token or a refresh token related to
minting the access token.
- 4. The /userinfo endpoint returns an HTTP status that is not retryable.
- For example, /userinfo returns HTTP status 400.
+ 4. The endpoint returns an HTTP status that is not retryable, e.g. HTTP status 400.
+
+ 5. If the endpoint returns an updated set of Visas (this is
+ an OPTIONAL feature of a Visa Issuer), then the Passport
+ Clearinghouse MUST use the updated Visas and ignore the original
+ GA4GH Claim values in the Visa Access Token. If the Passport
+ Clearinghouse is unable to adjust for the updated Visas, then
+ it MUST act as though the token was revoked.
- 5. If the /userinfo endpoint returns an updated set of GA4GH Claims (this is
- an OPTIONAL feature of an Visa Issuer), then the Claim
- Clearinghouse MUST use the updated GA4GH Claims and ignore the original
- GA4GH Claim values in the Visa Access Token. If the Claim
- Clearinghouse is unable to adjust for the the updated GA4GH Claims, then
- it MUST act as though the the token was revoked.
+{% hr2 %}
-### GA4GH JWT Format
+
+## GA4GH JWT Formats
+This specification builds on the JWT format defined in [[RFC7519]](#ref-rfc7519).
A well-formed JWS-Encoded JSON Web Token (JWT) consists of three concatenated
Base64url-encoded strings, separated by dots (.) The three sections are: header,
-payload and signature. These JWTs follow [RFC7515](https://tools.ietf.org/html/rfc7515) (JWS)
-and utilize a number of [standard JWT claim names](https://www.iana.org/assignments/jwt/jwt.xhtml)
-as per the registation process.
+payload and signature. These JWTs follow JWS [[RFC7515]](#ref-rfc7515)
+and utilize a number of standard JWT [Claim](#term-claim) names [[IANA-JWT]](#ref-iana-jwt)
+as per the registration process.
This profile is agnostic to the format of the id_token.
+{% hr3 %}
+
+
-#### Passport-Scoped Access Token issued by Broker
+### Passport-Scoped Access Token
+
+This is the format for the token that is issued by [Brokers](#term-broker), extending the definition of
+the [[OIDC-Core]](#ref-oidc-core) access token.
+
+**Header**
-Header - The `kid` parameter (see [RFC7515 section
-4.1.4](https://tools.ietf.org/html/rfc7515#section-4.1.4)) must be included
-and `alg` must be "RS256".
```
{
- "typ": "JWT",
- "alg": "RS256",
+ "typ": "",
+ "alg": "",
"kid": ""
}
```
+- `typ`: REQUIRED. Media type of the JWT. Value should be either
+ `JWT` as [recommended](https://datatracker.ietf.org/doc/html/rfc7519#section-5.1)
+ in [[RFC7519]](#ref-rfc7519)
+ or `at+jwt` as [required](https://datatracker.ietf.org/doc/html/rfc9068#section-2.1)
+ in [[RFC9068]](#ref-rfc9068)
+ if the token format follows [[RFC9068]](#ref-rfc9068).
+
+- `alg`: REQUIRED. See [Signing Algorithms](#signing-algorithms).
+
+- `kid`: REQUIRED. Key ID, see [section 4.1.4](https://tools.ietf.org/html/rfc7515#section-4.1.4)
+ of [[RFC7515]](#ref-rfc7515).
+
+**Payload**
-Payload:
```
{
"iss": "https:///",
@@ -566,21 +807,21 @@ Payload:
"iat": ,
"exp": ,
"jti": ,
- "scope": "openid ",
+ "scope": "openid ga4gh_passport_v1 ",
}
```
- `iss`: REQUIRED. MUST be able to be appended with
- .well-known/openid-configuration to get spec of Broker.
+ `.well-known/openid-configuration` to get spec of Broker.
- `sub`: REQUIRED. Authenticated user unique identifier.
- `idp`: OPTIONAL. SHOULD contain the IDP the user used to auth with.
- A non-normative example is "google". This does not have to be unique and
- can be used just to help inform if that is what a data owner or data holder
- needs.
+ This does not have to be unique and
+ can be used just to help inform if that is what a [Visa Issuer](#term-visa-issuer)
+ or [Data Holder](#term-data-holder) needs.
-- `aud`: OPTIONAL. If provided, it MUST contain the Oauth Client ID of the
+- `aud`: OPTIONAL. If provided, it MUST contain the OAuth Client ID of the
relying party.
- `iat`: REQUIRED. Time issued.
@@ -588,249 +829,126 @@ Payload:
- `exp`: REQUIRED. Time expired.
- `jti`: RECOMMENDED. a unique identifier for the token as per
- [RFC7519 Section 4.1.7](https://tools.ietf.org/html/rfc7519#section-4.1.7)
-
-- `scope`: REQUIRED. Includes verified scopes. MUST include "openid". Will also
- include any `` from the GA4GH Passport specification
- (e.g. "ga4gh_passport_v1" is the [scope for GA4GH
- Passports](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md#requirement-7)).
- The `scope` claim is defined by [RFC8693 section 4.2](https://datatracker.ietf.org/doc/html/rfc8693#section-4.2).
+ [section 4.1.7](https://tools.ietf.org/html/rfc7519#section-4.1.7) of [[RFC7519]](#ref-rfc7519)
-- `addtional claims`: OPTIONAL. Any other additional non-GA4GH claims are allowed. This specification does not dictate the format of other claims.
+- `scope`: REQUIRED. Includes verified scopes. MUST include `openid` and `ga4gh_passport_v1`.
+ The `scope` [Claim](#term-claim) is defined by [section 4.2](https://datatracker.ietf.org/doc/html/rfc8693#section-4.2)
+ of [[RFC8693]](#ref-rfc8693).
-#### Claims sent to Data Holder by a Broker via /userinfo
+- [GA4GH Claims](#term-ga4gh-claim) (`ga4gh_passport_v1` or `ga4gh_visa_v1`): MUST NOT be included.
-Only the GA4GH claims truly must be as prescribed here. Refer to OIDC Spec for
-more information. The /userinfo endpoint MAY use `application/json` or
-`application/jwt`. If `application/jwt` is returned, it MUST be signed as per
-[UserInfo](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse).
+- additional [Claims](#term-claim): OPTIONAL. Any other additional non-GA4GH [Claims](#term-claim) are allowed. This specification does not dictate the format of other [Claims](#term-claim).
-```
-{
- "iss": "https:///",
- "sub": "",
- "aud": [
- "",
- "" ...
- ],
-
-}
-```
+{% hr3 %}
-- `iss` and `sub`: REQUIRED.
+### Visas provided by a Broker via UserInfo Endpoint
-- `aud`: OPTIONAL.
+The [UserInfo Endpoint](#term-userinfo-endpoint) MAY use `application/json`
+or `application/jwt` response content type. It is RECOMMENDED that if desiring to return a JWT, a Token Endpoint supporting
+[Token Exchange](#term-token-exchange) exists to do that and that the UserInfo Endpoint returns an `application/json` response.
+Only the [GA4GH claims](#term-ga4gh-claim) must be as prescribed here. Refer to [[OIDC-Core]](#ref-oidc-core) for more information.
-- ``: OPTIONAL. GA4GH Claims are generally included as
- specified by the GA4GH Passport specification based on the Passport-Scoped
- Access Token's scope provided. Even when requested by the appropriate scopes,
- these GA4GH Claims may not be included in the response for various reasons, such
- as if the user does not have any GA4GH Claims. See
- [Authorization/Claims](#authorizationclaims) for an example of a GA4GH
- Claim.
+The UserInfo response MUST include a `ga4gh_passport_v1` [Claim](#term-claim) with a list of [Visas](#term-visa)
+if a [Passport-Scoped Access Token](#term-passport-scoped-access-token) was used for accessing it.
-
-#### Visa issued by Visa Issuer
+{% hr3 %}
-There are two supported formats for Visas.
+### Passport Format
-
-##### Visa Access Token Format
+Passport Issuers MUST issue a Passport conforming to the requirements in this section when a [Token Exchange](#term-token-exchange)
+with the `requested_token_type=urn:ga4gh:params:oauth:token-type:passport` is successfully performed
+(as described in the [Conformance for Passport Issuers](#conformance-for-passport-issuers) section).
-Header format:
+Passports are defined as signed JWTs. The JWT specification [[RFC7519]](#ref-rfc7519)
+states that JWTs can be either signed and encoded using JWS Compact Serialization,
+or encrypted and encoded using JWE Compact Serialization.
+Passports are signed JWTs, which implies that they must be encoded using [JWS Compact Serialization](https://www.rfc-editor.org/rfc/rfc7515#section-3.1) [[RFC7515]](#ref-rfc7515).
-```
-{
- "typ": "JWT",
- "alg": "RS256",
- "kid": ""
-}
-```
+**Header**
-where:
+This spec prescribes the following JWS headers for Passports
+in addition to the guidelines established in [[RFC7515]](#ref-rfc7515):
-1. `alg` MUST be "RS256".
+- `typ`: REQUIRED where the value must be `vnd.ga4gh.passport+jwt` for Passports.
-2. The header MUST NOT contain a `jku`.
+**Payload**
-Payload format:
+Only the [GA4GH claims](#term-ga4gh-claim) must be as prescribed here. See the
+JWT specification [[RFC7519]](#ref-rfc7519) for more details.
```
{
"iss": "https:///",
"sub": "",
+ "aud": [
+ "",
+ "" ...
+ ],
"iat": ,
"exp": ,
- "jti": ,
- "scope": "openid "
-
+ "ga4gh_passport_v1": [
+ ,
+ ,
+ ...
+ ]
}
```
-where:
-
-1. The standard JWT payload claims `iss`, `sub`, `iat`, `exp` are
- all REQUIRED.
+- `iss`: REQUIRED.
-2. `jti` is RECOMMENDED.
+- `sub`: REQUIRED. Please note that [[OIDC-Core]](#ref-oidc-core) in its section
+ [Subject Identifier Types](https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes)
+ allows the use of PPIDs (Pairwise Pseudonymous Identifiers) providing different `sub` value to each client
+ to preclude correlation of user's activities at different clients. Even if a public identifier is used (same for all clients),
+ the value of the `sub` claim of a [Passports](#term-passport) may be different from the values of `sub` claims of its [Visas](#term-visa),
+ and the values may need to be linked using [LinkedIdentities](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md#linkedidentities)
+ visas.
-3. `scope` is REQUIRED and MUST be a string containing a space-delimited set of
- scope names. "openid" MUST be included as a scope name. The `scope` claim
- name is defined by [RFC8693 section 4.2](https://datatracker.ietf.org/doc/html/rfc8693#section-4.2).
+- `aud`: OPTIONAL.
-4. The payload claims MAY contain at least one GA4GH Claim
- (``).
+- `iat`: REQUIRED.
-5. The payload claims MUST NOT include `aud`.
+- `exp`: REQUIRED.
-
-##### Visa Document Token Format
+- `jti`: RECOMMENDED.
-Conforms with JWS format requirements and is signed by a Visa Issuer.
+- `ga4gh_passport_v1`: REQUIRED. An array of GA4GH Visas. May be empty if a
+ user has no visas. See the [[Passport]](#ref-passport) specification
+ for more details on types of visas.
-1. MUST be a JWS string.
-
-2. MUST contain a `jku` in the header.
-
-3. MUST NOT contain "openid" as a space-delimited substring of the `scope`
- JWT claim, if the `scope` claim is provided.
-
-4. The following headers and JWT claims in the payload are REQUIRED
- (here shown in its decoded JSON form):
-
- ```
- {
- "typ": "JWT",
- "alg": "RS256",
- "jku": "https://",
- "kid": ""
- }.
- {
- "iss": "https:///",
- "sub": "",
- "iat": ,
- "exp": ,
- "jti": ,
-
- }.
-
- ```
-
- - `typ`: MUST be "JWT".
-
- - `alg`: MUST be "RS256".
-
- - `jti`: RECOMMENDED. A unique identifier for the token as per
- [RFC7519 Section 4.1.7](https://tools.ietf.org/html/rfc7519#section-4.1.7)
- is RECOMMENDED.
-
- - ``: OPTIONAL. One or more GA4GH Claims MAY be
- provided. See [Authorization/Claims](#authorizationclaims) for an
- example.
-
-#### Authorization/Claims
-
-User attributes and claims are being developed in the [GA4GH Passport
-specification](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md)
-by the DURI work stream.
-
-A non-normative example of a GA4GH Passport, as referred to
-in as `` within the JWT formatting sections of this
-specification, is:
+{% hr3 %}
-```
-"ga4gh_passport_v1": [
-
-]
-```
-
-See the [GA4GH Passport
-Claim Format](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md#passport-claim-format)
-for more details.
-
-Token Revocation
-----------------
-
-#### Claim Source Revokes Claim
-
-Given that claims can cause downstream access tokens to be minted by Claim
-Clearinghouses and such downstream access tokens may have little knowledge or no
-connectivity to sources of claims, it can be challenging to build robust
-revocation capabilities across highly federated and loosely coupled systems.
-During the lifetime of the downstream access token, some systems may require
-that claims are no longer inspected nor updated.
-
-In the event that a [Claim Source](#term-claim-source) revokes a claim within
-a [Claim Repository](#term-claim-repository), downstream Visa
-Issuers, Brokers, Claim Clearinghouses, and other Authorization or Resource
-Servers MUST at a minimum provide a means to limit the lifespan of any given
-access tokens generated as a result of claims. To achieve this goal, servers
-involved with access may employ one or more of the following options:
-
-1. Have each GA4GH Claim or sub-object be paired with an expiry timestamp.
- Expiry timestamps would require users to log in occasionally via
- an Broker in order to refresh claims. On a refresh, expiry timestamps can
- be extended from what the previous claim may have indicated.
-
-2. Provide GA4GH Claims in the form of [Visa Access
- Tokens](#term-visa-access-token) to allow downstream Claim
- Clearinghouses to periodically check the validity of the token via calls
- to the /userinfo endpoint as per [Access Token Polling](#at-polling).
-
-3. Provide refresh tokens at every level in the system hierarchy and use
- short-lived access tokens. This may require all contributing systems to
- support [OIDC offline
- access](https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess)
- refresh tokens to deal with execution of processes where the user is no
- longer actively involved. In the event that refresh tokens experience
- errors, the systems involved must eventually revoke the ability for
- downstream access tokens to be replaced via refresh tokens (although some
- level of delay to reach out to a user to try to resolve the issue may be
- desirable).
-
-4. Provide some other means for downstream Claim Clearinghouses or other
- systems that create downstream access tokens to be informed of a material
- change in upstream claims such that action can be taken to revoke the token,
- revoke the refresh token, or revoke the access privileges associated with
- such tokens.
-
-#### Revoking Access from Bad Actors
-
-In the event that a system or user detects that a specific user is misbehaving or
-has falsified claims despite previous assurances that access was appropriate,
-there MUST be a mechanism to withdrawal access from existing tokens and update
-claims to prevent further tokens from being minted.
-
-1. Systems MUST have a means to revoke existing refresh tokens or remove
- permissions from access tokens that are sufficiently long-lived enough to
- warrant taking action.
-
- - If an access token is long-lived, then the access token MUST be
- revocable, and once revoked the /userinfo endpoint MUST NOT return
- claims. In this event, an appropriate error status MUST be returned as per
- [section 5.3.3 of the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoError).
-
- - [Access Token Polling](#at-polling) can allow downstream systems to detect
- token revocation and remove access accordingly.
+### Signing Algorithms
-2. A process MUST exist, manual or automated, to eventually remove or invalidate
- related claims from the [Claim Repository](#term-claim-repository).
+JWTs MUST be issued with signatures using the `ES256` or `RS256` algorithm.
-#### Limited Damage of Leaked Tokens
+{% hr2 %}
-In order to limit damage of leaked tokens, systems MUST provide all of the
-following:
+## Security Considerations
-1. Be able to leverage mechanisms in place for revoking claims and tokens
- for other purposes to also limit exposure of leaked tokens.
+The confidentiality and integrity of tokens must be secured, taking
+[JSON Web Token Best Current Practices](https://www.rfc-editor.org/rfc/rfc8725.html#name-best-practices) in [[RFC8725]](#ref-rfc8725)
+into consideration. Of special concern are:
+* Revoking access tokens and Visa Assertions
+* Limiting damage of leaked tokens
-2. Follow best practices for the safekeeping of refresh tokens or longer lived
- tokens (should longer lived tokens be needed).
+{% hr2 %}
-3. Limit the life of refresh tokens or long lived keys before an auth challenge
- occurs or otherwise the refresh token simply fails to generate more access
- tokens.
+## Specification Revision History
-4. Any signed tokens that may be stored by participating services SHOULD be
- encrypted at rest and follow best practices to limit the ability of
- administrators from decrypting this content.
+| Version | Date | Editor | Notes |
+|---------------|---------|-----------------------------------------------------------------------|----------------------------------------------------------------------------------|
+| 1.2.0 | 2023-01 | Andrew Patterson, Martin Kuba, Kurt Rodarmer, Tom Conner, Max Barkley | Introduce token exchange and Passport format, incorporate Visas, update diagrams |
+| 1.1.0 | 2021-07 | Craig Voisin | *abandoned* version now reserved, new concepts moved to v1.2 |
+| 1.0.4 | 2021-07 | Craig Voisin | Improve existing terminology and define Passport and Visa JWTs |
+| 1.0.3 | 2021-06 | Craig Voisin | Links for "scope" claim |
+| 1.0.2 | 2020-02 | David Bernick | Clarify risk scenarios |
+| 1.0.1 | 2019-10 | David Bernick | Clarify that non-GA4GH claims are allowed in tokens |
+| 1.0.0 | 2019-10 | Approved by GA4GH Steering Committee | |
+| 0.9.9 | 2019-10 | David Bernick, Craig Voisin, Mikael Linden | Approved standard |
+| 0.9.5 | 2019-09 | Craig Voisin | Update claim flow diagram and definitions |
+| 0.9.4 | 2019-08 | Craig Voisin | Embedded tokens for signed RI Claim Objects |
+| 0.9.3 | 2019-08 | Craig Voisin | Support for RI's embedded tokens |
+| 0.9.2 | 2019-07 | David Bernick | Made changes based on feedback from review |
+| 0.9.1 | 2019-06 | Craig Voisin | Added terminology links |
+| 0.9.0 | 2017- | Mikael Linden, Craig Voisin, David Bernick | Initial working version |
diff --git a/AAI/CHANGES_1.2.md b/AAI/CHANGES_1.2.md
new file mode 100644
index 0000000..e42f590
--- /dev/null
+++ b/AAI/CHANGES_1.2.md
@@ -0,0 +1,102 @@
+---
+layout: page
+title: Changes Between Versions 1.0 and 1.2
+permalink: changes-1_2
+---
+
+This document lists changes between
+ * GA4GH AAI OIDC Profile [1.0.0](https://github.com/ga4gh/data-security/blob/AAIv1.0/AAI/AAIConnectProfile.md) and [1.2](https://ga4gh.github.io/data-security/aai-openid-connect-profile)
+ * GA4GH Passport [1.0.0](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/v1.0.0/researcher_ids/ga4gh_passport_v1.md) and 1.2
+
+### Table of Contents
+{:.no_toc}
+
+* toc
+{:toc}
+
+## Terminology changes
+
+* Removed double definitions of same concepts like “Claim Source” in AAI and “Passport Visa Assertion Source” in Passport.
+* Made distinction between claim as an abstract assertion and a JWT/OIDC claim as a pair of a string key and a JSON value.
+* Renamed “Data Owner” to “Data Controller” to be compatible with European GDPR
+
+### Changed terms
+
+* **Claim Management System** removed, the term was not used
+* claim → **Visa Assertion**
+* **Claim Repository** → **Visa Assertion Repository**
+* **Claim Source** → **Visa Assertion Source**
+* **Claim Clearinghouse** → **Passport Clearinghouse**
+* **Embedded Token** → **Visa**
+* **Embedded Token Issuer** → **Visa Issuer**
+* **Embedded Access Token** → **Visa Access Token**
+* **Embedded Document Token** → **Visa Document Token**
+* **Flow of Claims** → **Flow of Assertions**
+* **Passport Bearer Token** → **Passport-Scoped Access Token**
+* **Data Owner** → **Data Controller**
+
+### New terms
+
+* **Passport** - A signed and verifiable JWT container for holding Visas.
+* **Passport Issuer** - a service that creates and signs Passports.
+* **Token Endpoint** – as defined by OIDC
+* **UserInfo Endpoint** - as defined by OIDC
+
+## Introduced Token Exchange mechanism
+
+The standardized mechanism for exchanging access tokens for other tokens defined in [RFC 8693 OAuth 2.0 Token Exchange](https://www.rfc-editor.org/info/rfc8693)
+was added and used for releasing Passports.
+
+## Redefined Passport as a JWT containing Visas
+
+In version 1.0, Passport was defined as ”*GA4GH-compatible access token along with the Passport Claim that is returned from Passport Broker service endpoints using such an access token*“,
+thus as a tuple of an access token and a list of Visas that can be obtained from UserInfo endpoint using the access token.
+
+In version 1.2, Passport is defined as “*a signed and verifiable JWT container for holding Visas*“, thus as a token that can be passed among systems.
+
+For backward compatibility with version 1.0, list of Visas is still provided as a claim value from UserInfo endpoint.
+
+## Defined Passport Issuer
+
+A **Passport Issuer** is a service that creates and signs Passports.
+A **Broker** is an OIDC Provider service that collects Visas from Visa Issuers and provides them to Passport Clearinghouses.
+
+
+Broker may optionally become a Passport Issuer by supporting Token Exchange for issuance of Passports.
+
+Brokers conforming to version 1.0 are still compatible with version 1.2, because Token Exchange support is optional.
+
+## Added more signing algorithms
+
+The version 1.0 allowed only **RS256** algorithm for JWT signing.
+It is RSA-based algorithm using keys of size 2048 bits or larger and SHA-256 hash function.
+
+The AAI specification version 1.2 allows also the **ES256** algorithm which is
+ECDSA-based using P-256 elliptic curve and SHA-256 hash function.
+
+Elliptic Curve Cryptography allows much shorter keys and signatures than RSA.
+A short Elliptic Curve key of around 256 bits provides the same security as a 3072 bit RSA key.
+
+For a detailed discussion of signing algorithms, see the article
+[JWTs: Which Signing Algorithm Should I Use?](https://www.scottbrady91.com/jose/jwts-which-signing-algorithm-should-i-use)
+
+## Media types for JWTs
+
+In version 1.0, all the mentioned JWTs (access tokens, visas) used in their `typ` (media type) header parameter
+the generic value `JWT` that marks a generic JWT.
+
+In version 1.2, the `typ` header parameter is used to distinguish the various types of JWTs:
+
+- access tokens conforming to [RFC9038](https://datatracker.ietf.org/doc/html/rfc9068#section-2.1)
+ use the value `at+jwt`
+- Passports use the value `vnd.ga4gh.passport+jwt`
+- Visas are recommended to use the value `vnd.ga4gh.visa+jwt` but allowed to use `JWT`
+ for backward compatibility with version 1.0
+
+## Proposed Deprecations
+
+### Visa Access Tokens (also referred to as Embedded Access Tokens)
+
+It is proposed that the 1.x versions of this specification will be the last to support
+Visa Access Tokens. New implementations should issue Visas
+as Visa Document Tokens.
diff --git a/AAI/FAQ.md b/AAI/FAQ.md
index db16dad..c5e0c6f 100644
--- a/AAI/FAQ.md
+++ b/AAI/FAQ.md
@@ -1,26 +1,526 @@
---
layout: page
+title: AAI FAQ
permalink: aai-faq
---
-Frequently Asked Questions and Implementation Examples
-----------------
-## Can the output of `/userinfo` be used as a JWT for Authentication?
+A collection of questions (and hopefully useful answers).
-The spec says that `/userinfo` may be formatted as a JWT. A Clearinghouse that sends an access token to a `/userinfo` endpoint might get either JSON or a formatted and signed JWT from a broker. The JWT can be used downstream as an authentication mechanism if downstream services like Clearinghouses support it and know what to do with it.
+{% hr2 %}
+## Background
-It is probable that a special token endpoint will exist in a future version of this profile that should prevent the `/userinfo` endpoint from being overloaded.
+### Why Brokers?
-## Can a JWT alone be used for authentication even if the spec mostly talks about OIDC Flow?
+We have found that there are widely used Identity Providers (IdP).
+These authentication mechanisms provide no authorization
+information (custom claims or scopes) but are ubiquitous for authentication at the institution level.
+The use of a Broker and Clearinghouse
+enables attaching information to the usual OIDC flow so that IdPs
+can be used with customized claims and scopes.
-Yes. This specification allows for groups to organize themselves in many ways.
+Here is a diagram of a single broker. This is one possible way to use this spec.
-A trusted group of Brokers and Claims Clearinghouses are permitted to format `/userinfo` output as a JWT and use that as a means of how their services communicate. They can also take `/userinfo` JSON output and format it through some other means into a JWT. Proper due-dilligence and handling of tokens must be followed.
+@startuml
+skinparam componentStyle rectangle
+left to right direction
-This specification does not prohibit services from using JWTs as authentication outside of an OIDC flow.
+component "Visa Issuer 1\nservice" as Issuer1
+component "Visa Issuer 2\nservice" as Issuer2
+component "Visa Issuer N\nservice" as IssuerN
-An example: Two different stacks of software all have a similar user-base and often use the same shared data resource -- a biobank, for instance. The User authenticates with Biobank Broker on Software stack S1 and gets `/userinfo` output as a JWT. The JWT includes GA4GH Passport Visas for a Dataset that the Broker holds permissions for. S1 might not hold the data, S2 might hold the data. The User may be allowed to bring that JWT to Software Stack S2 and get data authorized by the claim in the JWT and held by S2, provided that S2 can trust S1 as a valid and trustworthy client.
+component "Broker\nservice" as Broker #FAFAD2
+component "Passport Clearinghouse\nservice" as ClearingHouse #9E7BB5
- This enables two or more software stacks to work together more fluidly than having the same user authenticate twice across two stacks to access the same data. There is an assumption that these two software stacks have agreements and risk assessment in place in order to make this a secure method of authentication and that the User is aware that they are exchanging information with another stack without explicit OIDC-style consent.
+Issuer1 --> Broker : Provide Visas
+Issuer2 --> Broker : Provide Visas
+IssuerN --> Broker : Provide Visas
+Broker --> ClearingHouse : Provide Passport and Visas
- ![JWT-Only Flow between trusted stacks](GA4GH_JWT-only_flow.png)
\ No newline at end of file
+@enduml
+
+In this diagram, the Broker relies on a separate service for fetching visas, which
+stores assertions from multiple sources. The visa assertions are obtained by the
+Clearinghouse after a successful login, and used to determine a researcher's
+access in the Clearinghouse system.
+
+The Broker, Clearinghouse, and Visa Issuer may be separate services (as shown
+in this diagram), but in other configurations they may be run as parts of a single
+service, or as separate services run by single organization. Data holders and data
+controllers should explore their options to decide what best fits their needs.
+
+## Flows
+
+The following sequence diagrams are included to help explain the intended flows
+documented in the accompanying specification.
+
+### What is the complete end to end flow using token exchange?
+
+(last updated June 2022)
+
+**This flow is the preferred flow for v1.2+ of the specification.**
+
+The exchange flow does not ever distribute the initial *Passport-Scoped Access Token* beyond
+the client application. A token exchange operation is executed by the client, in
+exchange for a *Passport* JWT that may be used downstream to access resources. In this example flow, the
+*Passport* is included as authorization in the POST to a DRS server. The token
+exchange has also specified known resources that will limit the audience
+of the *Passport*.
+
+{% plantuml %}
+
+hide footbox
+skinparam BoxPadding 10
+skinparam ParticipantPadding 20
+
+box "Researcher" #eee
+actor "User Agent" as user
+participant Client as client
+end box
+
+box "AAI"
+participant Broker as broker
+collections "IdP" as idps
+end box
+
+box "Data Controller"
+collections "Visa Issuer(s)" as issuers
+end box
+
+box "Data Holder"
+participant "Clearing House" as clearing
+participant "Data" as data
+end box
+
+==OIDC==
+
+ref over user, client, broker, idps
+OIDC flow results in the client holding a *Passport-Scoped Access Token*.
+end ref
+
+==Exchange==
+
+client -> broker : Token exchange
+note right
+(note: for clarity these form values have not actually been URL encoded)
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=urn:ietf:params:oauth:grant-type:token-exchange
+&requested_token_type=urn:ga4gh:params:oauth:token-type:passport
+&subject_token_type=urn:ietf:params:oauth:token-type:access_token
+&subject_token=
+&resource=https://drs.example.com/dataset1
+&resource=https://drs.example.com/dataset2
+end note
+
+group#DeepSkyBlue #LightSkyBlue Informative Only (not defined in the specification)
+broker -> issuers : Fetch signed visa(s) for user
+broker <- issuers : Return signed visa(s) for user
+note right
+[
+ "",
+ ""
+]
+end note
+end
+
+client <- broker : Token exchange return
+note right
+{
+ "access_token": "",
+ "issued_token_type": "urn:ga4gh:params:oauth:token-type:passport",
+ "token_type": "Bearer"
+}
+
+▼ Passport content as example (decoded from the base64 of the JWT Passport) ▼
+
+{
+ "typ": "vnd.ga4gh.passport+jwt",
+ "alg": "",
+ "kid": ""
+} .
+{
+ "iss": "https://",
+ "sub": "",
+ "aud": [
+ "https://drs.example.com"
+ ],
+ "iat": ,
+ "exp": ,
+ "jti": "",
+ "ga4gh_passport_v1": [
+ "",
+ "",
+ ...
+ ]
+} .
+end note
+
+==Use==
+
+client -> clearing : Client requests data
+note right
+POST /ga4gh/drs/v1/objects/dataset1/access/s3 HTTP/1.1
+Host: drs.example.com
+Content-Type: application/json
+
+{
+ "passports": [
+ ""
+ ]
+}
+end note
+
+note over clearing, data #FFCCCB
+Decision is made to release data using information contained in the
+passport token - and this decision is coordinated with the data system to
+facilitate that actual data release.
+end note
+
+client <- clearing : Client is given data
+
+{% endplantuml %}
+
+
+
+### What is the complete end to end flow using `/userinfo`?
+
+(last updated June 2022)
+
+**This flow is the flow for v1.0 implementations of the specification.**
+
+The flow as used by Elixir uses the initial *Passport-Scoped Access Token* as
+a token handed to downstream resource servers. These servers can use this token, in conjunction
+with a callback to the broker's *Userinfo Endpoint*, to obtain the *Passport* content in
+JSON format.
+
+{% plantuml %}
+
+hide footbox
+skinparam BoxPadding 10
+skinparam ParticipantPadding 20
+
+box "Researcher" #eee
+actor "User Agent" as user
+participant Client as client
+end box
+
+box "AAI"
+participant Broker as broker
+collections "IdP" as idps
+end box
+
+box "Data Controller"
+collections "Visa Issuer(s)" as issuers
+end box
+
+box "Data Holder"
+participant "Clearing House" as clearing
+participant "Data" as data
+end box
+
+==OIDC==
+
+ref over user, client, broker, idps
+OIDC flow results in the client holding a *Passport-Scoped Access Token*.
+end ref
+
+==Use==
+
+client -> clearing : Client requests data
+note right
+{
+ Authorization: Bearer
+}
+end note
+
+clearing -> broker : Clearing house asks for list of signed visa(s)
+note right
+{
+ Authorization: Bearer
+}
+end note
+
+group#DeepSkyBlue #LightSkyBlue Informative Only (not defined in the specification)
+broker -> issuers : Fetch signed visa(s) for user
+broker <- issuers : Return signed visa(s) for user
+note right
+[
+ "",
+ ""
+]
+end note
+end
+
+clearing <- broker : UserInfo endpoint returns list of signed visa(s)
+note right
+{
+ "iss": "https:///",
+ "sub": "",
+ "ga4gh_passport_v1": [
+ "",
+ "",
+ ...
+ ]
+}
+end note
+
+
+note over clearing, data #FFCCCB
+Decision is made to release data using information contained in the
+passport - and this decision is coordinated with the data system to
+facilitate that actual data release.
+end note
+
+client <- clearing : Client is given data
+
+
+{% endplantuml %}
+
+
+{% hr2 %}
+
+## Trust
+
+### What's with all the signed passports and visas etc? Why so complex?
+
+(last updated July 2022)
+
+The practical operation of a loosely coupled
+federated ecosystem like GA4GH Passports requires establishing trust
+relationships between the participating entities (see
+[OpenID Connect Federation](https://openid.net/specs/openid-connect-federation-1_0.html)
+for an interesting discussion of the properties of multilateral federations).
+
+Any entity that is asked to make a decision about sharing data needs to have *a priori*
+made the decision "which other entities do I trust?". In genomics, a single decision
+to allow data sharing might involve simultaneous trusting of
+multiple entities - human genomics is complex!
+
+When presented with a
+Passport and Visas from entities that they trust - they can rely on the information (claims) provided
+to make data sharing decisions. If presented with information from entities that are
+untrusted - the content of the message is irrelevant as there is no basis on which to believe
+the content.
+
+So we can see that trust is a crucial element of a working federation. How do we establish
+these trust relationships?
+
+GA4GH Passports and Visas leverage the mechanisms
+present in [JWT](https://datatracker.ietf.org/doc/html/rfc7519) as used
+by the [OIDC standards](https://openid.net/specs/openid-connect-core-1_0.html)
+to cryptographically "sign" tokens containing claims. Signed tokens can be
+"verified" using public/private keys.
+
+
+### Why are the Visa claims formatted as JWTs inside the Passport?
+
+(last updated August 2022)
+
+If visas were not signed separately from a Passport, then Clearinghouses would require a high degree of confidence that
+the signing Passport Issuer or Broker was accurately representing the contents of Visas from the original Visa Issuer;
+there would be no mechanisms to prevent a malicious or defective Passport Issuer from misrepresenting Visa contents.
+By signing Visas separately from Passports, we prevent intermediate parties from tampering with Visa contents,
+allowing Clearinghouses to safely rely on Visa contents based on their trust relationship with the Visa Issuer.
+
+### What are the ways that key management is done in practice?
+
+(last updated July 2022)
+
+There are a variety of approaches that can be used for key
+management for Passports and Visas. We will first detail those that can be used for Passports
+and then discuss some extra wrinkles for Visas.
+
+For this discussion we assume there is a concrete JWT from issuer `https://issuer.example.org`
+(possibly a Broker *or* a Visa Issuer).
+
+My clearinghouse service 'trusts' the above issuer to help make data
+access decisions - and that trust is stated probably through some sort of explicit
+configuration. For our example, let's imagine it has a hypothetical YAML configuration file
+
+```yaml
+trusted_brokers:
+ - https://issuer.example.org
+ - https://login.broker.com
+
+trusted_visa_issuers:
+ - https://dac.gov.world
+```
+
+The service now wants to verify a Passport or Visa
+JWT purporting to be from that issuer.
+
+---
+
+#### Use `jku` in the header of the JWT
+
+The JKU is the URL of a JSON file containing the issuers' public keys.
+
+```json
+{
+ "iss": "https://issuer.example.org",
+ "jku": "https://issuer.example.org/public-keys.json",
+ "kid": "key-october-1"
+}
+```
+
+For our concrete example we say that it is a JSON file residing
+at `https://issuer.example.org/public-keys.json` (see
+[RFC 7517 "JSON Web Key"](https://datatracker.ietf.org/doc/html/rfc7517)).
+
+**IMPORTANTLY**, for the secure use of this key management technique - the JKU
+**MUST** also be allow-listed as part of the configuration of **OUR** service.
+For example:
+
+```yaml
+trusted_brokers:
+ - issuer: https://issuer.example.org
+ jku: https://issuer.example.org/public-keys.json
+
+ - issuer: https://login.broker.com
+ jku: https://keys.broker.com/set
+```
+
+It is **NEVER** valid to even attempt to access a JKU from a JWT header - unless the URL
+is already known to belong to the given issuer. See
+["JWT Forgery via unvalidated jku parameter"](https://www.invicti.com/web-vulnerability-scanner/vulnerabilities/jwt-forgery-via-unvalidated-jku-parameter/).
+
+To verify a JWT, the content of the JKU file is loaded and the `kid` is
+looked up in key set. The signature is validated using the public key found.
+
+Although this configuration requires explicit registration of JKUs, the content
+of the key sets can allow the best practice of key rotation.
+
+The content of the JKU file is designed to be cached aggressively, but as long as
+the file is fetched every few days/weeks, the set of keys
+can evolve/rotate.
+
+---
+
+#### Use the `kid` in the header of the JWT along with OIDC Discovery
+
+The [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html)
+protocol allows the use of the JWT issuer URL - in conjunction with a fetch
+of a `/.well-known/openid-configuration` - to look up the location of the public key set file. See
+[OpenID Provider Metadata specification](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata)
+and the `jwks_uri` entry.
+
+As with JKU - it is important that OIDC discovery is limited only to JWT issuer URLs that are
+in some way allow-listed. It is **NEVER** valid to perform discovery on an arbitrary issuer
+encountered in a JWT. Luckily, the concept of allow-listing issuers is already in some way
+inherent to the way trust relationships are established, and hence this allow list should
+already be present in the system.
+
+Also as with JKU, the content of the discovery protocol and key sets can be cached
+aggressively. This means that the double step of the discovery protocol is not
+required on every JWT verification.
+
+
+---
+
+#### Exchange public keys beforehand with each trusted entity
+
+This is an approach used by the [NIH](https://www.nih.gov) - and is appropriate if the number
+of trusted entities is small - such that the public keys of each trusted entity can be exchanged
+out of band (and their rotation/updating can also be managed out of band).
+
+Configuration may be
+
+```yaml
+trusted_brokers:
+ - issuer: https://issuer.example.org
+ keys:
+ key-october-1: "ABCDTRTFDSFSDFSF...."
+
+ - issuer: https://login.broker.com
+ keys:
+ kid123456: "ABCDTRTFDSFSDFSF...."
+```
+
+For any `kid`
+encountered in a JWT, the corresponding public key is already available for signature validation.
+
+An even safer version of this approach is to perform
+the key verification across every public key you hold before even decoding the JWT JSON
+and then confirm the `kid`. This avoids ever even needing to JSON decode
+data from untrusted entities.
+
+---
+
+#### Requirement for JKU in Visas
+
+When it comes to Visas, there is an extra wrinkle - unlike Brokers, Visa Issuers do not
+need to have been part of an OIDC flow. It is possible that the visa issuer URI is not
+even a locatable reference
+(e.g. `urn:example.com:dac-world-visa-issuer`).
+
+Therefore the OIDC Discovery technique is not appropriate and hence the requirements
+of the AAI standard regarding the presence of JKUs.
+
+{% hr2 %}
+
+## Client Software
+
+### Use of GA4GH passport/visas in Single Page Apps (SPAs)
+
+It is currently recommended that single page apps (SPA) such as a React/VueJS websites
+are NOT used for scenarios where the single page app code is *solely* responsible for the handling of
+genomic passports and tokens.
+
+A SPA contains all the source of the application in public - and hence cannot
+possess a 'client secret' in an OIDC flow (the 'client secret' is used to prove the identity of the
+client software and is an important risk mitigation that prevents unconstrained
+use of an accidentally leaked/stolen token).
+
+Techniques such as PKCE can be used to allow a SPA to participate in an OIDC flow - and this is not
+forbidden by the specification - but there
+are still unresolved questions about how SPAs can prove client identity in things like the token
+exchange that retrieves passports or other tokens.
+
+Therefore if writing SPA websites for genomic data handling, it is recommended to use
+a backend set of services to execute OIDC flows and token exchanges (even if the rest of the SPA
+can operate purely on the front end). These
+backend service can hold secrets and hence can prove client identity - and the backend
+service can then securely participate in token exchange and retain tokens/passports.
+
+There is an emerging standard DPoP that may remove some of these limitations -
+([OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop-09))
+- and it will be considered for future versions of the AAI specification.
+
+{% hr2 %}
+
+{% comment %}
+## Legacy
+
+### Can a JWT alone be used for authentication even if the spec mostly talks about OIDC Flow?
+
+(last updated 2020 - Removed from the 1.2 version of the FAQ. If not missed - then can be deleted entirely in 2.0)
+
+Yes. This specification allows for groups to organize themselves in many ways.
+
+A trusted group of Brokers and Passport Clearinghouses are permitted to
+format `/userinfo` output as a JWT and use that as a means of how their
+services communicate. They can also take `/userinfo` JSON output and
+format it through some other means into a JWT. Proper due-diligence and
+handling of tokens must be followed.
+
+This specification does not prohibit services from using JWTs as authentication
+outside of an OIDC flow.
+
+An example: Two different stacks of software all have a similar user-base and
+often use the same shared data resource -- a biobank, for instance. The User
+authenticates with Biobank Broker on Software stack S1 and gets `/userinfo` output
+as a JWT. The JWT includes GA4GH Passport Visas for a Dataset that the Broker holds
+permissions for. S1 might not hold the data, S2 might hold the data. The User may
+be allowed to bring that JWT to Software Stack S2 and get data authorized by the
+claim in the JWT and held by S2, provided that S2 can trust S1 as a valid and
+trustworthy client.
+
+This enables two or more software stacks to work together more fluidly than having
+the same user authenticate twice across two stacks to access the same data. There
+is an assumption that these two software stacks have agreements and risk assessment
+in place in order to make this a secure method of authentication and that the User
+is aware that they are exchanging information with another stack without
+explicit OIDC-style consent.
+
+![JWT-Only Flow between trusted stacks](./AAI/GA4GH_JWT-only_flow.png)
+{% endcomment %}
diff --git a/AAI/MAINTAINER.md b/AAI/MAINTAINER.md
index 355ca3c..492ffb4 100644
--- a/AAI/MAINTAINER.md
+++ b/AAI/MAINTAINER.md
@@ -1,15 +1,20 @@
## Specification maintainers
-The current maintainers are listed below.
+The current maintainers for this repository are listed below.
### AAI
-* David Bernick (@davidbernick)
-* Craig Voisin (@https://www.linkedin.com/in/craigvoisin/?originalSubdomain=ca)
+* David Bernick - Broad Institute (@davidbernick)
+* Martin Kuba - ELIXIR Czech Republic
+* Craig Voisin - Google (https://www.linkedin.com/in/craigvoisin/)
## Updating the specifications
+As GA4GH standards, these specifications and guidance are subject to community review and discussion. If you would like to contribute or have any questions, please reach out to the Data Security Work Stream via https://www.ga4gh.org/contactus/
+
+## Changes to the repository
+
Minor editorial fixes where there is no likelihood of controversy may be done directly on the **master** branch.
Larger changes should be proposed as pull requests so that they can be discussed and refined.
-This way when the main repository is forked again, the new fork is created with a minimum of extraneous volatile branches.)
+This way when the main repository is forked again, the new fork is created with a minimum of extraneous volatile branches.
diff --git a/AAI/README.md b/AAI/README.md
index 9d50425..3881caa 100644
--- a/AAI/README.md
+++ b/AAI/README.md
@@ -1,162 +1,81 @@
----
-layout: page
-permalink: aai-introduction
----
+# Authentication and Authorization Infrastructure
-# Introduction to the GA4GH Authentication and Authorization Infrastructure (AAI)
-
-## Quick Links
-
-- Specification: [GA4GH Authentication and Authorization Infrastructure (AAI) OpenID Connect Profile]({% link AAI/AAIConnectProfile.md %})
-- Other specifications that use the AAI profile: [GA4GH Passport](https://bit.ly/ga4gh-passport-v1)
-
-### Table of Contents
-
-- [**Introduction**](#introduction)
-- [**Background**](#background)\
- - [Examples of broker technologies](#examples-of-broker-technologies)\
- - [Why Brokers?](#why-brokers)\
- - [Embedded Tokens example and explanation](#embedded-tokens)\
- - [Services parties are responsible for providing](#services-parties-are-responsible-for-providing)
-- [**Future topics to explore**](#future-topics-to-explore)
-- [**FAQ**](FAQ.md)
+## [Link to Specification](https://ga4gh.github.io/data-security/)
## Introduction
-The [GA4GH AAI profile
-specification]({% link AAI/AAIConnectProfile.md %})
-leverages OpenID Connect (OIDC) Servers for use in authenticating the identity of
-researchers desiring to access clinical and genomic resources from [data
-holders]({% link AAI/AAIConnectProfile.md %}#term-data-holder)
-adhering to GA4GH standards, and to enable data holders to obtain security-related
-attributes of those researchers. This is intended to be endorsed as a GA4GH standard,
-implemented by GA4GH Driver Projects, and shared broadly.
-
-To help assure the authenticity of identities used to access data from GA4GH
-Driver Projects, and other projects that adopt GA4GH standards, the Data Use and
-Researcher Identity (DURI) Work Stream has developed a standard around [claims](https://github.com/ga4gh-duri/ga4gh-duri.github.io/tree/master/researcher_ids). This standard assumes that some GA4GH Claims provided
-by Brokers described in this document will conform to the DURI researcher-identity
-policy and standard. This standard does NOT assume that DURI's GA4GH Claims will be
-the only ones used.
-
-This AAI standard aims at developing an approach that enables data holders’ and data owners
-systems to have systems that recognize and accept identities from multiple Brokers -- allowing for
-a federated approach. An organization can still use this specification and not
-support multiple Brokers, though they may find in that case that it’s just using
-a prescriptive version of OIDC.
-
-## Background
-
-#### Examples of broker technologies
-
-Examples of suites that provide both functionalities in a single package are :
-[Auth0.com](https://auth0.com/), [Keycloak](https://www.keycloak.org) (open
-source), [Hydra](https://github.com/ory/hydra) (open source), OpenAM,
-[Okta](https://www.okta.com/), Globus Auth, [Gen3
-Fence](https://github.com/uc-cdis/fence),
-[ELIXIR](https://elixir-europe.org/services/compute/aai), NIH/VDS, [AWS
-Cognito](https://aws.amazon.com/cognito/).
-
-#### Why Brokers?
-
-We have found that there are widely used Identity Providers (IdP) such as Google
-Authentication. These authentication mechanisms provide no authorization
-information (custom claims or scopes) but are so pervasive at the institution
-level that they cannot be ignored. The use of a "brokers" and "clearinghouses"
-enables "inserting" information into the usual OIDC flow so that Google
-identities can be used but claims and scopes can be customized.
-
-We have also found that some brokers, such as ELIXIR for example, provide some useful "extra" claims on top of an IdP like Google, but an institution receiving ELIXIR claims might want to add even more claims. Brokers then had to have a mechanism for trusting claims from other Brokers while providing provenance and proof of where they came from. This lead to the Embedded Token structure.
+The Authentication and Authorizations Infrastructure (AAI) specification
+leverages OpenID Connect (OIDC) to authenticate researchers
+desiring to access clinical and genomic resources from data
+holders adhering to GA4GH standards. Beyond standard OIDC authentication, AAI enables
+data holders to obtain security-related attributes and authorizations of those
+researchers. In parallel, the Data Use and Researcher Identity (DURI) Work Stream has developed a standard
+representation for researcher authorizations and attributes known as Researcher-ID.
+At its core, the AAI specification defines cryptographically secure tokens for exchanging
+these researcher attributes called Visas and how various
+participants can interact to authenticate researchers, and obtain and validate Visas.
-Here is a diagram:
-
-of a full-broker. This is one possible way to use this spec.
+This specification also provides for federated multilateral authorization infrastructure for greater
+interoperability between biomedical institutions sharing restricted datasets.
-![flow diagram]({% link AAI/flow.png %})
+### What is OpenID Connect?
-In this diagram, the Data Owner Claim Clearinghouse, the Data Holder Claim
-Clearinghouse and the Broker are all different entities. However, some cases, the Broker and Data Owner might be the same entity and
-even be operated with the same OIDC Provider Software.
+OpenID Connect is a simple identity layer, on top of the OAuth 2.0 protocol, that supports identity verification and the ability to
+obtain basic profile information about end users. The AAI specification extends this to define tokens,
+endpoints, and flows that enable an OIDC provider (called a Broker) to
+provide Passports and Visas to downstream consumers called Passport Clearinghouses. Passports can then be used for
+authorization purposes by downstream systems.
-Examples of implementations that provide both Identity Brokering and Data Owner
-Claim Clearinghouse services are:
-[ELIXIR](https://docs.google.com/document/d/1hD0lsxotLvPaML_CSydVX6rJ-zogAH2nRVl4ax4gW1o/edit#heading=h.eilp6df62hbd),
-[Auth0](http://auth0.com), [Keycloak](http://keycloak.org), [Globus
-auth](https://www.globus.org/tags/globus-auth), [Okta](https://www.okta.com/),
-[Hydra](https://github.com/ory/hydra), [AWS
-Cognito](https://aws.amazon.com/cognito/). These can be Brokers and/or
-Claim Clearinghouses. They’re not usually only used for Claim consumption (akin
-to a OAuth2 Resource Server in many ways). NGINX and Apache both offer reverse
-proxies for "Claim Consumption Only" functionality --
- (with
-) and
- respectively.
+## Passports specification
+The AAI and Passports specifications rely on each other for full functionality and will likely be merged in a future version. The Passports specification from the Data Use and Researcher Identities Work Stream can be found [here](https://ga4gh-duri.github.io/researcher_ids/ga4gh_passport_v1.html).
-Data holders and data owners should explore their options to decide what best
-fits their needs.
+## Version history
-#### Embedded Tokens example and explanation
+[Changelog](https://ga4gh.github.io/data-security/changes-1_2) for v1.2
-![embedded claims flow diagram]({% link AAI/embedded_Claims_flow.png %})
+Full version history available [here](https://ga4gh.github.io/data-security/aai-openid-connect-profile#specification-revision-history)
-Consider two parties: Google and ELIXIR.
-In this example, Google Passport Clearinghouse makes access decisions based on ELIXIR Assertion Repository information via a chain of brokers that have passed along the Passport Visas in standard GA4GH Passport format where the Passports are signed by different Brokers but the Passport Visas retain the signature from the Passport Visa Issuer.
+## Contributors
-The way this chain of brokers and trust is maintained is through "embedded tokens". There are two types of embedded tokens: Embedded Access Tokens and Embedded Document Tokens.
+GA4GH is an open community and contribution is not limited to those named below.
+Names listed alphabetically by surname. Repository maintainers listed [here](./MAINTAINER.md).
-Embedded Access Tokens are claims in a Broker's token that can then be sent to OTHER brokers' `/userinfo` endpoints for further user claims. In GA4GH Passports, embedded access tokens will usually carry full claims so as not to interrogate /userinfo each time.
+### Core Developers for v1.2
-Embedded Document Tokens cannot be revoked and no `/userinfo` endpoint is provided for them, however they stilll offer a signature that can be used to verify their provenance and always contain the necessary claims in them already.
+- Max Barkley - DNAstack
+- Tom Conner - Broad Institute
+- Martin Kuba - ELIXIR Czech Republic
+- Andrew Patterson - The University of Melbourne Centre for Cancer Research
+- Kurt Rodarmer - National Center for Biotechnology Information - NIH
-#### Services parties are responsible for providing
+### Reviewers for v1.2
-**Data Holders:**
+- Francis Jeanson - Peter Munk Cardiac Centre and Ted Rogers Centre for Heart Research
+- David Glazer - Verily Life Sciences
+- Timothy Slade - RTI International
+- Dylan Spalding - ELIXIR Finland
-Data holders are expected to protect their resources within a Claim
-Clearinghouse Server. These Servers should be able to get claims from one or
-more Brokers, with researcher authentication provided by one or more Identity
-Providers. *Note: Most Claim Clearinghouses can provide access to resources
-based on information in Claims -- if not the Claim Clearinghouses themselves
-then in some downstream application that protects data.*
+### Technical Programme Manager
-**Data Owners:**
+- Fabio Liberante - Global Alliance for Genomics and Health
-Data owners are not required to implement or operate an Identity Provider
-(though they may choose to do so) or an Broker.
-
-Data Owners may choose to operate a Claim Clearinghouse server configured
-to consume access_tokens from an upstream Broker and then hand out JWT
-claims to relying parties and other Claim Clearinghouses.
+## Work Stream Leadership
-Some data owners will own the whole "chain" providing all of the different kinds
-of brokers and will also operate Claim Clearinghouses. For instance, NIH is a
-data owner and might provide Cloud Buckets and operate an IDP and Broker to
-utilize ERACommons and other identity resources.
+### Data Security
-A Data Owner should be able to, based on an Identity from an Identity Provider,
-express some sort of [permissions](#ga4gh-jwt-format) via the Claim Clearinghouse
-GA4GH claims. It is the responsibility of the Data Owner to provide these
-permissions to their Claim Clearinghouse to be expressed claims within a standard
-/userinfo process for downstream use.
+- David Bernick - Broad Institute
+- Lucila Ohno-Machado - Yale University School of Medicine
+- Previously - Jean-Pierre Hubaux - Swiss Federal Institute of Technology Lausanne
-It is possible that the IdPs might have special claims. The Claim Clearinghouse
-being operated by the Data Owner should be "looking" for those claims and
-incorporating them, if desired, into the claims that it eventually sends to the
-user.
+### Data Use and Researcher Identities
-A data owner is expected to maintain the [operational
-security](https://github.com/ga4gh/data-security) of their Claim Clearinghouse
-server and hold it to the GA4GH spec for [operational
-security](https://github.com/ga4gh/data-security). It is also acceptable to
-align the security to a known and accepted framework such as NIST-800-53,
-ISO-27001/ISO-27002.
+- Jaime Guidry-Auvil - National Cancer Institute - NIH
+- Tommi Nyrönen - ELIXIR Finland
-## Future topics to explore
- - OIDC federation
+## Demonstration Implementation
-Register the Claim - According to RFC 7519 (JSON Web Token) section 4.2
- claim names should be
-registered by IANA in its "JSON Web Token Claims" registry at
- . Register GA4GH.
+[Life Science RI](https://lifescience-ri.eu/) have implemented this v1.2 specification from the finalised draft for use across the Life Science RI platforms.
+Information on creating an account is available [here](https://lifescience-ri.eu/ls-login/users/how-to-get-and-use-life-science-id.html).
+With an account, the test service [here](https://echo.aai.elixir-czech.org/) will return a technical view of the various tokens created and shared in an example flow using Passport/AAI 1.2.
\ No newline at end of file
diff --git a/README.md b/README.md
index 4f10135..dc8a819 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,19 @@
-# data-security
+# GA4GH Data Security Work Stream
This is the repository for the source of any specifications/documentation
-of the GA4GH Data Security working group.
+of the Data Security Work Stream of the Global Alliance for Genomics and Health ([GA4GH](https://www.ga4gh.org/)).
-The source is written in Markdown and processed via Jekyll.
+## Resources
-To produce a local copy, you can
+- [Data Security and Infrastructure Policy](DSIP/DSIP_v4.0.md)
+- [Authentication and Authorization Infrastructure](AAI/README.md)
+
+
+## Rendering documentation
+
+The source is written in Markdown and processed via Jekyll. Diagrams make use of PlantUML.
+
+To produce a local copy, clone the repository and run
```shell
make
@@ -18,3 +26,20 @@ The local copy can then be browsed at
```
http://localhost:4000/local/
```
+
+### Use of Jekyll
+
+The following Liquid tags are used to separate
+
+Second level headers - {% hr2 %}
+
+Third level headers - {% hr3 %}
+
+Fourth level headers - {% hr4 %}
+
+Note that level 5 and 6 headers render smaller than paragraph text and are not
+distinctive - and therefore should be avoided.
+
+Use **text** for a 5th level header if required.
+
+The actual HTML for these dividers can be found in `_plugins/jekyll-hrs.rb`.
diff --git a/_config.yml b/_config.yml
index 712cfdb..87b24df 100644
--- a/_config.yml
+++ b/_config.yml
@@ -16,8 +16,9 @@ kramdown:
# Limit the header pages to those we want top at top level, this also controls ordering
header_pages:
- - AAI/README.md
- AAI/AAIConnectProfile.md
+ - AAI/FAQ.md
+ - AAI/CHANGES_1.2.md
# Due to the way we publish to github pages - it is useful that Jekyll keeps any .git in the destination around
keep_files: [.git]
diff --git a/_plugins/jekyll-alerts.rb b/_plugins/jekyll-alerts.rb
new file mode 100644
index 0000000..3f2edb4
--- /dev/null
+++ b/_plugins/jekyll-alerts.rb
@@ -0,0 +1,21 @@
+module Jekyll
+ class AlertDeprecationBlock < Liquid::Block
+
+ def render(context)
+ text = super
+ "#{text}
"
+ end
+ end
+
+ class AlertWarningBlock < Liquid::Block
+
+ def render(context)
+ text = super
+ "#{text}
"
+ end
+ end
+
+end
+
+Liquid::Template.register_tag('alert_deprecation', Jekyll::AlertDeprecationBlock)
+Liquid::Template.register_tag('alert_warning', Jekyll::AlertWarningBlock)
diff --git a/_plugins/jekyll-hrs.rb b/_plugins/jekyll-hrs.rb
new file mode 100644
index 0000000..7883117
--- /dev/null
+++ b/_plugins/jekyll-hrs.rb
@@ -0,0 +1,27 @@
+module Jekyll
+ class HR2Tag < Liquid::Tag
+
+ def render(context)
+ '
'
+ end
+ end
+
+ class HR3Tag < Liquid::Tag
+
+ def render(context)
+ '
'
+ end
+ end
+
+ class HR4Tag < Liquid::Tag
+
+ def render(context)
+ '—
'
+ end
+ end
+
+end
+
+Liquid::Template.register_tag('hr2', Jekyll::HR2Tag)
+Liquid::Template.register_tag('hr3', Jekyll::HR3Tag)
+Liquid::Template.register_tag('hr4', Jekyll::HR4Tag)
diff --git a/_sass/minima.scss b/_sass/minima.scss
index e69399d..4727b97 100644
--- a/_sass/minima.scss
+++ b/_sass/minima.scss
@@ -21,7 +21,7 @@ $grey-color-dark: darken($grey-color, 25%) !default;
$table-text-align: left !default;
// Width of the content area
-// Patto - changed from minima default
+// changed from minima default (GA4GH)
$content-width: 1200px !default;
$on-palm: 600px !default;
@@ -51,11 +51,28 @@ $on-laptop: 800px !default;
"minima/syntax-highlighting"
;
-// Patto - added custom CSS for callouts
+// due to estensive nested lists we set styling (GA4GH added)
+
+ol ol { list-style-type: lower-alpha; }
+ol ol ol { list-style-type: lower-roman; }
+ol ol ol ol { list-style-type: circle; }
+ol ol ol ol ol { list-style-type: disc; }
+
+// a fix for Kramdowns markup/css that doesn't leave enough space at the end of single item lists (GA4GH added)
+
+li:only-child {
+ margin-bottom: 1em;
+}
+
+// custom CSS for callouts (GA4GH added)
+
$border-radius: 5px;
$callouts: (
- rationale: (#008, rgba(#aaa, .2), 'RATIONALE'),
+ // rationale example callout
+ rationale: (#008, rgba(#aaa, .2), 'RATIONALE'),
+ // deprecation warning callout
+ deprecation: (#FFA500, rgba(#ddd, .2), 'DEPRECATION WARNING'),
);
@each $class, $props in $callouts {
diff --git a/check-links.py b/check-links.py
new file mode 100644
index 0000000..502aea8
--- /dev/null
+++ b/check-links.py
@@ -0,0 +1,92 @@
+from bs4 import BeautifulSoup
+import os
+from pprint import pprint
+import re
+
+anchors = set()
+local_hrefs = set()
+external_hrefs = set()
+
+for root, dirs, files in os.walk('build'):
+ for relpath in files:
+ if 'htm' in relpath:
+ with open(os.path.join(root, relpath)) as fh:
+ content = fh.read()
+
+ if relpath == 'index.html':
+ base = ''
+
+ base = relpath.replace('.html','')
+
+ soup = BeautifulSoup(content, 'html.parser')
+ for link in soup.find_all('a'):
+ href = link.get('href')
+ name = link.get('name')
+ if href is None:
+ anchors.add(f"{base}#{name}")
+ #print("No href: "+str(link))
+ else:
+ if href in ['/local/',
+ '/local/aai-openid-connect-profile',
+ '/local/aai-faq',
+ '/local/changes-1_2']:
+ pass
+ elif href.startswith('#'):
+ local_hrefs.add(f"{base}{href}")
+ else:
+ external_hrefs.add(href)
+
+ for heading in ['h1','h2','h3', 'strong']:
+ for link in soup.find_all(heading):
+ id = link.get('id')
+ if id is not None:
+ anchors.add(f"{base}#{id}")
+ #print("No href: "+str(link))
+
+
+
+line_links_from_duri_passport = """
+[GA4GH AAI OIDC Profile](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#terminology)
+* **[Passport](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-passport)**
+* **[Passport-Scoped Access Token](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-passport-scoped-access-token)**
+* **[Passport Clearinghouse](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-passport-clearinghouse)**
+* **[Visa Assertion](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-visa-assertion)**
+* **[Visa Assertion Source](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-visa-assertion-source)**
+* **[Visa Issuer](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-visa-issuer)**
+* **[Visa](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-visa)**
+* **[JWT](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-jwt)**
+* **[GA4GH Claim](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-ga4gh-claim)**
+* **[Broker](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-broker)**
+Please see the [Flow of Assertions](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#flow-of-assertions)
+ [GA4GH AAI Specification Visa formats](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#visa-issued-by-visa-issuer)
+ [GA4GH AAI Specification](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md)
+[Conformance for Visa Issuers](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#conformance-for-visa-issuers)
+ for [Visa Document Token Format](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#visa-document-token-format)
+- For [Visa Access Token Format](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#visa-access-token-format)
+- REQUIRED.The section [Signing Algorithms](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#signing-algorithms)
+if the Visa is encoded as a [Visa Access Token](https://github.com/ga4gh/data-security/blob/master/AAI/AAIConnectProfile.md#term-visa-access-token-format).
+"""
+
+print ("\n\nChecking anchors to which DURI passport links\n")
+for line_from_duri in line_links_from_duri_passport.split('\n'):
+ #print(line_from_duri)
+ m = re.search(r'AAIConnectProfile.md#([^)]*)', line_from_duri)
+ if m:
+ target = f"aai-openid-connect-profile#{m.group(1)}"
+ if target in anchors:
+ print (f"valid {target}")
+ else:
+ print (f"INVALID ------ {target}")
+
+#pprint(anchors)
+
+print ("\n\nChecking links within AAI\n")
+for local_href in local_hrefs:
+ if local_href in anchors:
+ print(f"valid {local_href}")
+ else:
+ print(f"INVALID ---- {local_href}")
+
+print ("\n\nListing links from AAI to external hrefs\n")
+pprint(external_hrefs)
+
diff --git a/index.md b/index.md
index b6fe2d3..3b5fbe2 100644
--- a/index.md
+++ b/index.md
@@ -2,6 +2,8 @@
layout: home
---
-* [Intro]({% link AAI/README.md %})
-* [Specification]({% link AAI/AAIConnectProfile.md %})
+## Authentication and Authorization Infrastructure (AAI)
+
+* [OIDC Profile]({% link AAI/AAIConnectProfile.md %})
* [FAQ]({% link AAI/FAQ.md %})
+* [Changes between 1.0 and 1.2]({% link AAI/CHANGES_1.2.md %})
diff --git a/jekyll-builder-local/Dockerfile b/jekyll-builder-local/Dockerfile
index 371af93..98f5aba 100644
--- a/jekyll-builder-local/Dockerfile
+++ b/jekyll-builder-local/Dockerfile
@@ -1,4 +1,4 @@
-FROM jekyll/builder:4
+FROM jekyll/builder:4.2.0
ENV PLANTUML_VERSION=1.2021.10
ENV LANG en_US.UTF-8