diff --git a/.github/workflows/publish-drafts.yml b/.github/workflows/publish-drafts.yml index 000b490..b22c582 100644 --- a/.github/workflows/publish-drafts.yml +++ b/.github/workflows/publish-drafts.yml @@ -3,19 +3,19 @@ name: Publish Drafts on: # Triggers the workflow on push or pull request events but only for the draft+branches we are on push: - branches: [ 1.2-draft*, add-github* ] + branches: [ "*draft*" ] pull_request: - branches: [ 1.2-draft*, add-github* ] + branches: [ "*draft*" ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: jobs: - cummulative-publish: + cumulative-publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions/cache@v2 with: @@ -35,6 +35,7 @@ jobs: with: cmd: yq eval -i '.baseurl = strenv(PUBLISH_BASEURL)' '_config.yml' + # NOTE: this build step is duplicated between publish-drafts and publish-main - please keep in sync - name: Build Jekyll Site uses: helaili/jekyll-action@master env: diff --git a/.github/workflows/publish-main.yml b/.github/workflows/publish-main.yml new file mode 100644 index 0000000..7804868 --- /dev/null +++ b/.github/workflows/publish-main.yml @@ -0,0 +1,51 @@ +name: Publish Main + +on: + # Triggers the workflow on push to the main branch + push: + branches: [ main, master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + replace-publish: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Set Jekyll baseurl to Publish Folder + uses: mikefarah/yq@master + env: + PUBLISH_BASEURL: data-security + with: + cmd: yq eval -i '.baseurl = strenv(PUBLISH_BASEURL)' '_config.yml' + + # NOTE: this build step is duplicated between publish-drafts and publish-main - please keep in sync + - name: Build Jekyll Site + uses: helaili/jekyll-action@master + env: + PLANTUML_VERSION: "1.2021.10" + with: + # this is dodgy.. the jekyll action wants to build things outside our workspace so setting it to + # this brings it back into the workspace where files will be kept for the deploy + target_path: ../workspace/build + build_only: true + token: ${{ secrets.GITHUB_TOKEN }} + pre_build_commands: apk add --no-cache graphviz wget ca-certificates ttf-dejavu fontconfig openjdk11 && wget http://downloads.sourceforge.net/project/plantuml/$PLANTUML_VERSION/plantuml.$PLANTUML_VERSION.jar -O /usr/bin/plantuml.jar && echo '#!/bin/sh' > /usr/bin/plantuml && echo 'java -jar /usr/bin/plantuml.jar $*' >> /usr/bin/plantuml && chmod a+rx /usr/bin/plantuml + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + # note that because this a publish of the main branch - it completely replaces the content of the gh-pages + # (see publish-drafts for how drafts are published in a cumulative mode) + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: build diff --git a/.gitignore b/.gitignore index bfa4aa1..d421519 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ _site vendor build .idea +.vscode diff --git a/AAI/AAIConnectProfile.md b/AAI/AAIConnectProfile.md index ca86625..5ed56b4 100644 --- a/AAI/AAIConnectProfile.md +++ b/AAI/AAIConnectProfile.md @@ -1,298 +1,510 @@ --- layout: page +title: AAI OIDC Profile permalink: aai-openid-connect-profile --- -| Version | Date | Editor | Notes | -|---------|---------|--------------------------------------------|-------------------------| -| 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 | - ### Abstract +{:.no_toc} + +This specification defines a profile for using the OpenID Connect protocol +[[OIDC-Core]](#ref-oidc-core) to provide federated multilateral authorization infrastructure for greater +interoperability between biomedical institutions sharing restricted datasets. (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.) In particular, this specification defines tokens, +endpoints, and flows that enable an OIDC provider (called a [Broker](#term-broker)) to +provide [Passports](#term-passport) and [Visas](#term-visa) to downstream consumers called +[Passport Clearinghouses](#term-passport-clearinghouse). [Passports](#term-passport) can then be used for +authorization purposes by downstream systems. + +### Table of Contents +{:.no_toc} -This specification profiles the OpenID Connect protocol to provide a federated -(multilateral) authentication and authorisation infrastructure for greater -interoperability between Genomics institutions in a manner specifically -applicable to (but not limited to) the sharing of restricted datasets. +* toc +{:toc} -In particular, this specification introduces a JSON Web Token -([JWT](#relevant-specifications)) syntax for an access token to -enable an OIDC provider (called a [Broker](#term-broker)) to allow a downstream -access token consumer (called a [Claim Clearinghouse](#term-claim-clearinghouse)) -to locate the Broker’s /userinfo endpoint as a means to fetch [GA4GH -Claims](#term-ga4gh-claim). This specification is suggested to be used together -with others that specify the syntax and semantics of the GA4GH Claims exchanged. +{% hr2 %} -### Table of Contents +## Introduction + +This specification +leverages OpenID Connect (OIDC) to authenticate researchers +desiring to access clinical and genomic resources from [data +holders]({% link AAI/AAIConnectProfile.md %}#term-data-holder) +adhering to GA4GH standards. Beyond standard OIDC authentication, AAI enables +data holders to obtain security-related attributes and authorizations of those +researchers. The Data Use and Researcher Identity (DURI) Work Stream has developed a standard +representation for researcher authorizations and attributes [[Researcher-ID]](#ref-researcher-ids). + +### Technical Summary + +At its core, the AAI specification defines cryptographically secure tokens for exchanging +researcher attributes called [Visas](#term-visa), and how various +participants can interact to authenticate researchers, and obtain and validate [Visas](#term-visa). + +The main components identified in the specification are: +* [Visa Issuers](#term-visa-issuer), that cryptographically sign researcher attributes in the + form of [Visas](#term-visa). +* [Brokers](#term-broker), that authenticate researchers and provide [Visas](#term-visa). +* [Clients](#term-client), that perform actions that may require data access on behalf of researchers, + relying on tokens issued by [Brokers](#term-broker) and [Visa Issuers](#term-visa-issuer). +* [Passport Clearinghouses](#term-passport-clearinghouse), that accept tokens containing or + otherwise availing researcher visas for the purposes of enforcing access control. + +### Visa Tokens + +[Visas](#term-visa) are used +for securely transmitting authorizations or attributes of a researcher. +[Visas](#term-visa) are tokens [[JWT](#term-jwt)] signed by [Visa Issuers](#term-visa-issuer) and +validated by [Passport Clearinghouses](#term-passport-clearinghouse). + +### Separation of Data Holders and Data Access Committees + +It is a fairly common situation that, for a single dataset, the Data Access Committee (DAC) (the authority managing +who has access to a dataset) is not the same party as the +[Data Holder](#term-data-holder) (the organization +that hosts the data, while respecting the DAC's access policies). + +For these situations, AAI is a standard mechanism for data holders to obtain +and validate existing authorizations from DACs, by specifying the interactions +between [Visa Issuers](#term-visa-issuer), [Brokers](#term-broker), and +[Passport Clearinghouses](#term-passport-clearinghouse). + +The AAI standard enables [Data Holders](#term-data-holder) and [Visa Issuers](#term-visa-issuer) to recognize +and accept identities from multiple [Brokers](#term-broker) --- allowing for a more federated +approach. An organization can still use this specification with a single +[Broker](#term-broker) and [Visa Issuer](#term-visa-issuer), +though they may find in that case that there are few benefits beyond standard OIDC. -- [Abstract](#abstract) -- [Requirements Notation and Conventions](#requirements-notation-and-conventions) -- [Terminology](#terminology) -- [Relevant Specifications](#relevant-specifications) -- [Flow of Claims](#flow-of-claims) -- [**Profile Requirements**](#profile-requirements)\ - - [Client/Application Conformance](#clientapplication-conformance)\ - - [Conformance for Brokers](#conformance-for-brokers)\ - - [Conformance for Visa Issuers](#conformance-for-visa-issuers)\ - - [Conformance for Claim Clearinghouses (consuming Access Tokens to give access to data)](#conformance-for-claim-clearinghouses-consuming-access-tokens-to-give-access-to-data) -- [**GA4GH JWT Format**](#ga4gh-jwt-format)\ - - [Passport-Scoped Access_Token issued by broker](#passport-scoped-access-token-issued-by-broker)\ - - [Claims sent to Data Holder by a Broker via /userinfo](#claims-sent-to-data-holder-by-a-broker-via-userinfo)\ - - [Visa issued by Visa Issuer](#visa-issued-by-visa-issuer)\ - - [Visa Access Token Format](#visa-access-token-format)\ - - [Visa Document Token Format](#visa-document-token-format)\ - - [Authorization/Claims](#authorizationclaims) -- [**Token Revocation**](#token-revocation)\ - - [Claim Source Revokes Claim](#claim-source-revokes-claim)\ - - [Revoking Access from Bad Actors](#revoking-access-from-bad-actors)\ - - [Limited Damage of Leaked Tokens](#limited-damage-of-leaked-tokens) -- [**Appendix**](#Appendix) - -### Requirements Notation and Conventions - -This specification inherits terminology from the [OpenID -Connect](http://openid.net/specs/openid-connect-core-1_0.html) and the [OAuth -2.0 Framework (RFC 6749)](https://tools.ietf.org/html/rfc6749) specifications. +{% hr2 %} + +## Notation and Conventions + +Terms defined in [Terminology](#terminology) appear as capitalized +links, e.g. [Passport](#term-passport). + +References to [Relevant Specifications](#relevant-specifications) appear +as bracket-enclosed links, e.g. [[OIDC-Core]](#ref-oidc-core). The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this specification are to -be interpreted as described in [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). +be interpreted as described in [[RFC2119]](#ref-rfc2119). -### Terminology +{% hr2 %} - **GA4GH Claim** -- A JWT claim as defined by a GA4GH -documented technical standard that is making use of this AAI specification. Typically -this is the `ga4gh_passport_v1` or `ga4gh_visa_v1` claim for GA4GH Passports v1.x. -Note that GA4GH is not the organization making the claim nor taking responsibility -for the claim as this is a reference to a GA4GH documented standard only. - - **Claim Management System** -- a service -that allows [Claim Source](#term-claim-source) users to manage claims and update one -or more [Claim Repositories](#term-claim-repository). For instance, a data owner -of a controlled access dataset would typically interact with a Claim Management -System to add or remove claims from a [Claim Repository](#term-claim-repository). - - **Claim Repository** -- a service that -manages the durable storage and retrieval of claims (such as a database), -along with any metadata and/or audit logs related to claim creation, -modification, and deletion. - - **Claim Source** -- the source organization of -a claim assertion which at a minimum includes the organization associated with -asserting the claim, although can optionally identify a sub-organization or a -specific assignment within the organization that made the claim. - -- This is NOT necessarily the organization that stores the claim, nor the - [Broker](#term-broker)’s organization that signs the token; it is the - organization that has the authority to assert the claim on behalf of the - user and is responsible for making and maintaining the assertion. +## Terminology - **Identity Provider (IdP)** -- a -service that provides to users an identity, authenticates it; and provides -claims to a Broker using standard protocols, such as OpenID Connect, SAML or -other federation protocols. Example: eduGAIN, Google Identity, Facebook, NIH -ERACommons. IdPs MAY be claims sources. +This specification inherits terminology from the OpenID +Connect [[OIDC-Core]](#ref-oidc-core) +and OAuth 2.0 Authorization Framework [[RFC6749]](#ref-rfc6749) specifications. **Broker** -- An OIDC Provider service that -authenticates a user (potentially by an Identity Provider), collects their -claims from internal and/or upstream claim sources and issues conformant JWT -claims to be consumed by [Claim Clearinghouses](#term-claim-clearinghouse). -Brokers may also be Claim Clearinghouses of other upstream Brokers (i.e. -create a chain of Brokers like in the -[Flow of Claims diagram](#flow-of-claims)). - - **Claim Clearinghouse** -- A consumer -of [GA4GH Claims](#term-ga4gh-claim) (i.e. an OIDC Relying Party or a service -downstream), that were provided by a [Broker](#term-broker), to make an -authorization decision at least in part based on inspecting GA4GH claims and +authenticates a user (potentially by relying on an [Identity Provider](#term-identity-provider)), +collects user's [Visas](#term-visa) from internal and/or external [Visa Issuers](#term-visa-issuer), +and provides them to [Passport Clearinghouses](#term-passport-clearinghouse). + +**Claim**{: #term-claim} -- as [defined](https://datatracker.ietf.org/doc/html/rfc7519#section-2) +by the JWT specification [[RFC7519]](#ref-rfc7519) -- A piece of information asserted about a subject, +represented as a name/value pair consisting of +a claim name (a string) and a claim value (any JSON value). + +**Client**{: #term-client} -- as discussed in the OAuth 2.0 Authorization Framework [[RFC6749]](#ref-rfc6749) specification + + **Data Holder** -- An organization that +holds a specific set of data (or its copy) and respects +and enforces the Data Access Committee's (DAC's) decisions on who can access it. + + +**GA4GH Claim** -- A [Claim](#term-claim) as defined by a GA4GH +documented technical standard that is making use of this AAI specification. Typically +this is the `ga4gh_passport_v1` or `ga4gh_visa_v1` [Claim](#term-claim) for [Passports v1.x](#term-passport). +A GA4GH Claim is asserted by the entity that signed the token in which it is contained (not by GA4GH). + + **Identity Provider (IdP)** -- A +service that provides to users an identity, authenticates it, and provides +assertions to a Broker using standard protocols, such as OpenID Connect, SAML or +other federation protocols. Examples: eduGAIN, Facebook, NIH +eRA Commons. IdPs MAY be [Visa Assertion Sources](#term-visa-assertion-source). + +**JWT**{: #term-jwt} -- JSON Web Token as defined in [[RFC7519]](#ref-rfc7519). +A JWT contains a set of [Claims](#term-claim). + + **Passport Clearinghouse** -- +A service that consumes [Visas](#term-visa) and uses them to make an +authorization decision based on inspecting them and allows access to a specific set of underlying resources in the target environment or platform. This abstraction allows for a variety of models for -how systems consume these claims in order to provide access to resources. +how systems consume these [Visas](#term-visa) in order to provide access to resources. Access can be granted by either issuing new access tokens for downstream -services (i.e. the Claim Clearinghouse may act like an authorization server) -or by providing access to the underlying resources directly (i.e. the Claim -Clearinghouse may act like a resource server). Some Claim Clearinghouses may -issue access tokens that may contain a new set of GA4GH Claims and/or a -subset of GA4GH claims for downstream consumption. +services (i.e. the Passport Clearinghouse may act like an authorization server) +or by providing access to the underlying resources directly (i.e. the Passport +Clearinghouse may act like a resource server). Some Passport Clearinghouses may +issue [Passports](#term-passport) that contain a new set or subset of Visas for downstream consumption. - **Data Holder** -- An organization that -protects a specific set of data. They hold data (or its copy) and respects -and enforces the data owner's decisions on who can access it. A data owner -can also be a data holder. Data holders run an -[Claim Clearinghouse Server](#term-claim-clearinghouse) at a minimum. - - **Data Owner** -- An organization that manages -data and, in that role, has capacity to decide who can access it. For -instance, a Data Access Committee (DAC). - - **Passport-Scoped Access -Token** -- A JWT bearer token, returned as an OAuth2 access token as -described herein, encoded via JWS Compact Serialization per -[RFC7515](https://datatracker.ietf.org/doc/html/rfc7515), containing -`ga4gh_passport_v1` as a space-separated entry within the `scope` claim but -does not contain [GA4GH Claims](#term-ga4gh-claim). - - -**Visa Issuer** (aka "Embedded Token Issuer") -- a service that signs -[Visas](#term-visa). - - -**Visa** (aka "Embedded Token") -- A [GA4GH Claim](#term-ga4gh-claim) -value or entry within a list or object of a GA4GH Claim that contains a JWT -encoded via JWS Compact Serialization per -[RFC7515](https://datatracker.ietf.org/doc/html/rfc7515). -It MUST be signed by a [Visa Issuer](#term-visa-issuer). A Visa MAY be passed -through various [Brokers](#term-broker) as needed while retaining the token -signature of the original Visa Issuer. - -### Relevant Specifications - -[OIDC Spec](http://openid.net/specs/openid-connect-core-1_0.html) - -Authorization Code Flow and Implicit Flow will generate id_tokens and -access_tokens from the Broker. - -[JWT](https://tools.ietf.org/html/rfc7519) - Specific implementations MAY extend -this structure with their own service-specific JWT claim names as top-level -members of this JSON object. Recommended "extensions" are in the -[Permissions](#authorizationclaims) section. The JWT specified here follows JWS -headers specification from [RFC7515](https://tools.ietf.org/html/rfc7515). - -[JWS](https://tools.ietf.org/html/rfc7515) - JSON Web Signature (JWS) is the -specific JWT to use for this spec. - -[Transport Layer Security (TLS, RFC 5246](https://tools.ietf.org/html/rfc5246)). -Information passed among clients, Applications, Brokers, and Claim -Clearinghouses MUST be protected using TLS. - -[OIDC Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) - -[OAuth 2.0 Threat Model and Security Considerations (RFC 6819)](https://tools.ietf.org/html/rfc6819). - -[GA4GH Passport](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md) - -### Flow of Claims - -![FlowOfClaims]({% link AAI/claim_flow_of_data_basic.svg %}) - -The above diagram shows how claims flow from a [Claim -Source](#term-claim-source) to a [Claim -Clearinghouse](#term-claim-clearinghouse) that uses them. This does not -label all of the Relying Party relationships along this chain, where -each recipient in the chain is typically -- but not always -- the -relying party of the auth flow that fetches the claims from upstream. - -Implementations may introduce clients, additional services, and protocols -- -not detailed in the above diagram -- to provide the mechanisms to move the data -between the Claim Respository and the [Broker](#term-broker). -These mechanisms are unspecified by the scope of this specification except that + **Passport-Scoped Access Token** -- +An OIDC access token with [scope](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) +including the identifier `ga4gh_passport_v1`. + +The access token MUST be a JWS-encoded JWT token containing `openid` and `ga4gh_passport_v1` +entries in the value of its `scope` [Claim](#term-claim). +It is RECOMMENDED that Passport-Scoped Access Tokens follow the JWT Profile for OAuth 2.0 Access Tokens specification [[RFC9068]](#ref-rfc9068). + + **Passport** -- A signed and verifiable JWT that contains [Visas](#term-visa). + + **Passport Issuer** -- +A service that creates and signs [Passports](#term-passport). + + **Token Endpoint** -- a [Broker](#term-broker)'s implementation of the [[OIDC-Core]](#ref-oidc-core) [Token Endpoint](https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint). + + **Token Exchange** -- +The protocol defined in [[RFC 8693]](#ref-rfc8693) as an extension of OAuth 2.0 +for exchanging access tokens for other tokens. A token exchange is performed by calling the [Token Endpoint](#term-token-endpoint). + + **UserInfo Endpoint** -- a [Broker](#term-broker)'s implementation of the [[OIDC-Core]](#ref-oidc-core) [UserInfo Endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo). + + +**Visa** -- A +Visa encodes a [Visa Assertion](#term-visa-assertion) in compact and digitally signed +format that can be passed as a URL-safe string value. + +A Visa MUST be signed by a [Visa Issuer](#term-visa-issuer). A Visa MAY be passed +through various [Brokers](#term-broker) as needed while retaining the +signature of the original [Visa Issuer](#term-visa-issuer). + + +**Visa Assertion** -- a piece of information about a user that is asserted by a [Visa Assertion Source](#term-visa-assertion-source). It is then encoded by a [Visa Issuer](#term-visa-issuer) into a [Visa](#term-visa). + + **Visa Assertion Source** -- the source organization of +a [Visa Assertion](#term-visa-assertion), which SHOULD include the organization associated with making the assertion, although it MAY optionally identify a sub-organization or a +specific assignment within the organization that made the assertion. + +- This is NOT necessarily the organization that signs the Visa; it is the + organization that has the authority to make the assertion on behalf of the + user and is responsible for making and maintaining the assertion. + + +**Visa Issuer** -- A service that signs [Visas](#term-visa). This service: +* may be a [Broker](#term-broker) itself +* may be used by a [Broker](#term-broker) as part of collecting [Visas](#term-visa). + +{% hr2 %} + +## Relevant Specifications + + +[[IANA-JWT]](https://www.iana.org/assignments/jwt/jwt.xhtml) -- Standard JWT [Claim](#term-claim) name assignments, +Internet Assigned Numbers Authority + + +[[OIDC-Core]](http://openid.net/specs/openid-connect-core-1_0.html) -- OpenID Connect Core 1.0 (OIDC) -- + [Authorization Code Flow](http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1) + will generate id_tokens and access_tokens from the [Broker](#term-broker). + + +[[OIDC-Client]](https://openid.net/specs/openid-connect-basic-1_0.html) -- OpenID Connect Basic Client Implementer's Guide 1.0 + + +[[OIDC-Discovery]](https://openid.net/specs/openid-connect-discovery-1_0.html) -- OpenID Connect Discovery 1.0 + + +[[Passport]](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md) -- GA4GH Passport Specification, Data Use and Researcher Identity (DURI) Work Stream -- Defines Passport and Visa formats. + + +[[Researcher-ID]](https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids) -- GA4GH Passport Specification, Data Use and Researcher Identity (DURI) Work Stream -- Defines researcher identities for GA4GH [Passports](#term-passport) and [Visas](#term-visa). + + +[[RFC2119]](https://www.ietf.org/rfc/rfc2119.txt) - Key words for use in RFCs to Indicate Requirement Levels + + +[[RFC5246]](https://tools.ietf.org/html/rfc5246) - Transport Layer Security (TLS). + Information passed among clients, applications, resource servers, + [Brokers](#term-broker), and [Passport Clearinghouses](#term-passport-clearinghouse) + MUST be protected using TLS. + + +[[RFC6749]](https://tools.ietf.org/html/rfc6749) -- The OAuth 2.0 Authorization Framework + + +[[RFC6819]](https://www.rfc-editor.org/info/rfc6819) - + Lodderstedt, T, McGloin, M., and P. Hunt, + "OAuth 2.0 Threat Model and Security Considerations", + RFC 6819, January 2013. + + +[[RFC7515]](https://tools.ietf.org/html/rfc7515) -- JSON Web Signature (JWS) is the + specific JWT to use for this spec. + + +[[RFC7519]](https://tools.ietf.org/html/rfc7519) -- JSON Web Token (JWT) -- Specific implementations MAY extend + this structure with their own service-specific JWT [Claim](#term-claim) names as top-level + members of this JSON object. The JWTs specified here follow the JWS + specification [[RFC7515]](#ref-rfc7515). + + +[[RFC7636]](https://datatracker.ietf.org/doc/html/rfc7636) -- Proof Key for Code Exchange by OAuth Public Clients (PKCE) + + +[[RFC7662]](https://www.rfc-editor.org/rfc/rfc7662) -- J. Richer, Ed., "OAuth 2.0 Token Introspection", October 2015 + + +[[RFC8693]](https://www.rfc-editor.org/info/rfc8693) - Jones, M., Nadalin, A., Campbell, B., Ed., Bradley, J., + and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693, + DOI 10.17487/RFC8693, January 2020. + + +[[RFC8725]](https://www.rfc-editor.org/info/rfc8725) - Sheffer, Y., Hardt, D., and M. Jones, "JSON Web Token Best + Current Practices", BCP 225, RFC 8725, + DOI 10.17487/RFC8725, February 2020. + + +[[RFC9068]](https://datatracker.ietf.org/doc/html/rfc9068) -- JWT Profile for OAuth 2.0 Access Tokens + + +{% hr2 %} + +## Overview of Interactions + +### Full Login and Token Exchange Interaction in AAI/Passport 1.2 + +In the full token exchange flow recommended in this document, the client does not ever distribute the initial +*Passport-Scoped Access Token* to other services. 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 Clearinghouse that holds data. + +{% 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" +participant "Visa Issuer" as issuer +end box + +box "Data Holder" +participant "Passport Clearinghouse" as clearing +end box + +==OIDC== + +user -> client : Initiates login +client -> user : Send redirect to Broker +user -> broker : Follow redirects +ref over user, client, 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 with code and client credentials +broker -> client : Respond with Passport-Scoped Access Token + +==Exchange== + +client -> broker : Request to exchange Passport-Scoped Access Token for Passport +broker <-> issuer : Exchange of visas, if needed (protocol unspecified) +client <- broker : Response with Passport + +==Use== + +user -> client : User initiates action requiring data +client -> clearing : Client requests data with Passport +clearing -> issuer : Request public keys +issuer -> clearing : Respond with public keys +client <- clearing : Clearinghouse responds with data + +{% endplantuml %} + +Notable differences between this diagram and interaction specified in AAI/Passport v1.0: +* The Passport Clearinghouse is no longer required to be a Client of the Broker +* The Passport-Scoped Access Token is only ever shared between the Client and the Broker +* An additional Token Exchange request is used to exchange the Passport-Scoped Access Token for a Passport Token, + which can be sent to a Passport Clearinghouse. The Passport Token carries only the authorization in a user's + Visas, whereas the Passport-Scoped Access Token contains authorizations above and beyond the Visas. + +### Flow of Assertions + +@startuml +package "Flow of assertions" { + +skinparam componentStyle rectangle +left to right direction + +component "Broker" as bro +component "Passport\nClearinghouse" as ch +component "Visa Assertion Source" as vas +component "Visa Issuer" as vi + +vas --> vi +vi --> bro +bro --> ch + +} +@enduml + +The above diagram shows how [Visa Assertions](#term-visa-assertion) flow from a [Visa Assertion Source](#term-visa-assertion-source) +to a [Passport Clearinghouse](#term-passport-clearinghouse) that uses them. + +Implementations may introduce clients, services, and protocols +to provide the mechanisms to move the data between the +[Visa Assertion Sources](#term-visa-assertion-source) and the [Broker](#term-broker). These mechanisms are unspecified by the scope of this specification except that they MUST adhere to security and privacy best practices, such as those outlined in this specification, in their handling of protocols, claims, tokens and -related data. The flow between these components (represented by black arrows) -MAY not be direct or conversely services shown as being separate MAY be +related data. The flow between these components +MAY be indirect or conversely services shown as being separate MAY be combined into one service. For example, some implementations MAY deploy one service that handles the responsibilities of both the Visa Issuer and the Broker. -### Profile Requirements +Here are two non-normative examples illustrating two *of many possible mechanisms*: + +@startuml +skinparam componentStyle rectangle +left to right direction + +package "Non-normative Example 1: Separate Issuer and Broker" { +component "Visa Assertion Source (1)\norganization" as VisaSource1 +component "Visa Assertion Source (2)\norganization" as VisaSource2 + +component "Visa Issuer (1)\nservice" as VisaIssuer1 +component "Visa Issuer (2)\nservice" as VisaIssuer2 -#### Client/Application Conformance +component "Broker\nservice" as Broker +component "Client\napplication" as Client +component "Passport\nClearinghouse\nservice" as ClearingHouse +} + +VisaSource1 --> VisaIssuer1 +VisaSource2 --> VisaIssuer2 + + +VisaIssuer1 --> Broker +VisaIssuer2 --> Broker +Broker --> Client +Client --> ClearingHouse -1. Confidential clients (keep the client secret secure - typically - server-side web-applications) MUST implement OIDC Authorization Code - Flow (with Confidential Client) - +@enduml -2. Public Clients (typically javascript browser clients) - SHOULD implement OIDC Implicit Flow - () - 1. MUST use "id_token token" response_type for authentication. +@startuml +skinparam componentStyle rectangle +left to right direction - 2. Public Clients like mobile apps that use Authorization Code Grant SHOULD implement some additional protection such as PKCE () . +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