Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Nextstrain CLI's new means of authentication with IdPs #757

Merged
merged 3 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion aws/cognito/clients.tf
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,15 @@ resource "aws_cognito_user_pool_client" "nextstrain-cli" {

name = "nextstrain-cli"

# Allow Secure Remote Password (SRP) auth, plus refresh token auth (required).
# Allow client to use OAuth (with the authorization code grant type only)
# against the user pool, plus Secure Remote Password (SRP) auth and refresh
# token auth (required).
allowed_oauth_flows_user_pool_client = true
allowed_oauth_flows = ["code"]
allowed_oauth_scopes = ["email", "openid", "phone", "profile"]

supported_identity_providers = ["COGNITO"]

explicit_auth_flows = [
"ALLOW_USER_SRP_AUTH",
"ALLOW_REFRESH_TOKEN_AUTH",
Expand All @@ -96,6 +104,39 @@ resource "aws_cognito_user_pool_client" "nextstrain-cli" {
refresh_token = "days"
}

# Allowed redirection destinations to complete authentication.
#
# We'd prefer to use 127.0.0.1 instead of localhost to avoid name resolution
# issues on end user systems, issues which are known to occur. The "OAuth
# 2.0 for native apps" best current practice (RFC 8252) suggests as much¹, but
# alas, Cognito's https-requirement exception for localhost is not applied to
# 127.0.0.1.
#
# Similarly, we'd prefer to register without an explicit port and rely on the
# same RFC's stipulation of relaxed port matching for localhost², but alack,
# Cognito doesn't follow that either and requires strict port matching.
#
# Since the CLI may not always be able to listen on a specific port given
# other services that might be running, and there's also value in random
# choice making interception harder, register a slew of ports for use and let
# Nextstrain CLI draw from the list.
# -trs, 19 Nov 2023
#
# ¹ <https://datatracker.ietf.org/doc/html/rfc8252#section-8.3>
# ² <https://datatracker.ietf.org/doc/html/rfc8252#section-7.3>
callback_urls = formatlist("http://localhost:%d/", random_integer.nextstrain_cli_callback_port[*].result)

read_attributes = local.user_attributes
write_attributes = setsubtract(local.user_attributes, ["email_verified", "phone_number_verified"])
}

resource "random_integer" "nextstrain_cli_callback_port" {
# AWS Cognito supports 100 callback URLs per client
# <https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html#resource-quotas>
count = 99

# IANA-defined port range for dynamic use.
# <https://datatracker.ietf.org/doc/html/rfc6335#section-6>
min = 49152
max = 65535
}
4 changes: 4 additions & 0 deletions aws/cognito/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ output "OAUTH2_CLI_CLIENT_ID" {
value = aws_cognito_user_pool_client.nextstrain-cli.id
}

output "OAUTH2_CLI_CLIENT_REDIRECT_URIS" {
value = aws_cognito_user_pool_client.nextstrain-cli.callback_urls
}

output "OAUTH2_LOGOUT_URL" {
value = format("https://%s/logout", coalesce(
one(aws_cognito_user_pool_domain.custom[*].domain),
Expand Down
10 changes: 10 additions & 0 deletions aws/iam/policy/NextstrainDotOrgServerInstance-testing.tftpl.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@
"Resource": [
"arn:aws:cognito-idp:us-east-1:827581582529:userpool/${COGNITO_USER_POOL_ID}"
]
},
{
"Sid": "GetResourcesIndex",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::nextstrain-inventories/resources.json.gz"
]
}
]
}
10 changes: 10 additions & 0 deletions aws/iam/policy/NextstrainDotOrgServerInstance.tftpl.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@
"Resource": [
"arn:aws:cognito-idp:us-east-1:827581582529:userpool/${COGNITO_USER_POOL_ID}"
]
},
{
"Sid": "GetResourcesIndex",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::nextstrain-inventories/resources.json.gz"
]
}
]
}
56 changes: 44 additions & 12 deletions docs/production.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ file are::
OAUTH2_CLIENT_ID
OAUTH2_CLIENT_SECRET
OAUTH2_CLI_CLIENT_ID
OAUTH2_CLI_CLIENT_REDIRECT_URIS
OIDC_USERNAME_CLAIM
OIDC_GROUPS_CLAIM

Expand All @@ -255,6 +256,9 @@ Clients
Two OAuth 2.0 clients (sometimes called "applications") must be registered with
the IdP.

App server client
~~~~~~~~~~~~~~~~~

A `confidential, web application client <oauth2-clients_>`__ is required for
use by the app server to implement browser-based sessions. Its id and secret
are configured by `OAUTH2_CLIENT_ID` and `OAUTH2_CLIENT_SECRET`. The app
Expand All @@ -270,24 +274,52 @@ server does not strictly require a secret. The client registration must allow:

- a logout redirection URL of `https://<host>`

Token lifetimes for this client should be configured with consideration that
the id token lifetime affects how often background renewal requests are
necessary and the refresh token lifetime limits the maximum duration of web
sessions.
.. _oauth2-clients: https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
.. _PKCE: https://datatracker.ietf.org/doc/html/rfc7636

CLI client
~~~~~~~~~~

A `public, native application client <oauth2-clients_>`__ is required for use
by the :doc:`Nextstrain CLI <cli:index>` and is permitted by the app server to
make `Bearer`-authenticated requests. Its id is configured by
`OAUTH2_CLI_CLIENT_ID`.
`OAUTH2_CLI_CLIENT_ID`. The client registration must allow:

.. note::
Currently Nextstrain CLI is tightly bound to AWS Cognito and requires
its Secure Remote Password authentication flow implemented outside of
the standard OAuth 2.0 flows. We anticipate changing this in the
future.
- the authorization code flow, ideally with PKCE_ support

.. _oauth2-clients: https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
.. _PKCE: https://datatracker.ietf.org/doc/html/rfc7636
- issuance of refresh tokens, either by default or by requesting the
`offline_access` scope

- at least one authentication redirection (sometimes "callback") URL of
`http://127.0.0.1:<port>/` or `http://localhost:<port>/`

The CLI auto-discovers its OpenID client configuration (and the IdP
configuration) from the app server. The app server must be configured to know
the CLI client's redirect URIs with `OAUTH2_CLI_CLIENT_REDIRECT_URIS` so the
URLs can be included in the discovery response.

If the IdP allows for `http://` redirect URIs for loopback IPs (e.g.
`127.0.0.1`), then the loopback IP should be preferred over using `localhost`,
as per best current practice described in `RFC 8252 § 8.3`_.

If the IdP allows relaxed port matching for loopback IP/localhost redirect
URIs, as per best current practice described in `RFC 8252 § 7.3`_, then only a
single redirect URI needs to be registered with the IdP. Otherwise, multiple
redirect URIs with varying ports should be registered to allow the CLI
alternatives to choose from in case it can't bind a given port on a user's
computer.

.. _RFC 8252 § 7.3: https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
.. _RFC 8252 § 8.3: https://datatracker.ietf.org/doc/html/rfc8252#section-8.3


Token lifetimes
~~~~~~~~~~~~~~~

Token lifetimes for the clients should be configured with consideration that
the id token lifetime affects how often background renewal requests are
necessary and the refresh token lifetime limits the maximum duration of web or
CLI sessions.


Authorization role groups
Expand Down
4 changes: 4 additions & 0 deletions env/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ output "OAUTH2_CLI_CLIENT_ID" {
value = module.cognito.OAUTH2_CLI_CLIENT_ID
}

output "OAUTH2_CLI_CLIENT_REDIRECT_URIS" {
value = module.cognito.OAUTH2_CLI_CLIENT_REDIRECT_URIS
}

output "OAUTH2_LOGOUT_URL" {
value = module.cognito.OAUTH2_LOGOUT_URL
}
Expand Down
19 changes: 19 additions & 0 deletions env/production/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 101 additions & 0 deletions env/production/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,107 @@
"OIDC_IDP_URL": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_Cg5rcTged",
"OAUTH2_CLIENT_ID": "rki99ml8g2jb9sm1qcq9oi5n",
"OAUTH2_CLI_CLIENT_ID": "2vmc93kj4fiul8uv40uqge93m5",
"OAUTH2_CLI_CLIENT_REDIRECT_URIS": [
"http://localhost:49154/",
"http://localhost:49208/",
"http://localhost:49233/",
"http://localhost:49278/",
"http://localhost:49852/",
"http://localhost:50049/",
"http://localhost:50146/",
"http://localhost:50208/",
"http://localhost:50290/",
"http://localhost:50552/",
"http://localhost:50555/",
"http://localhost:50560/",
"http://localhost:50978/",
"http://localhost:51122/",
"http://localhost:51182/",
"http://localhost:51357/",
"http://localhost:51494/",
"http://localhost:51716/",
"http://localhost:51838/",
"http://localhost:51841/",
"http://localhost:51861/",
"http://localhost:51924/",
"http://localhost:52109/",
"http://localhost:52176/",
"http://localhost:52191/",
"http://localhost:52258/",
"http://localhost:52560/",
"http://localhost:52629/",
"http://localhost:53113/",
"http://localhost:53369/",
"http://localhost:53995/",
"http://localhost:54137/",
"http://localhost:54211/",
"http://localhost:54378/",
"http://localhost:54568/",
"http://localhost:54971/",
"http://localhost:55027/",
"http://localhost:55341/",
"http://localhost:55396/",
"http://localhost:55535/",
"http://localhost:55536/",
"http://localhost:55555/",
"http://localhost:55610/",
"http://localhost:55825/",
"http://localhost:56014/",
"http://localhost:56361/",
"http://localhost:56691/",
"http://localhost:56846/",
"http://localhost:56978/",
"http://localhost:57264/",
"http://localhost:57282/",
"http://localhost:57578/",
"http://localhost:57856/",
"http://localhost:57875/",
"http://localhost:58039/",
"http://localhost:58199/",
"http://localhost:58638/",
"http://localhost:59095/",
"http://localhost:59462/",
"http://localhost:59507/",
"http://localhost:59628/",
"http://localhost:59804/",
"http://localhost:59906/",
"http://localhost:59942/",
"http://localhost:60139/",
"http://localhost:60257/",
"http://localhost:60377/",
"http://localhost:60564/",
"http://localhost:60579/",
"http://localhost:60705/",
"http://localhost:60775/",
"http://localhost:61015/",
"http://localhost:61309/",
"http://localhost:61376/",
"http://localhost:61384/",
"http://localhost:61399/",
"http://localhost:61588/",
"http://localhost:61915/",
"http://localhost:62350/",
"http://localhost:62478/",
"http://localhost:62752/",
"http://localhost:62947/",
"http://localhost:63087/",
"http://localhost:63124/",
"http://localhost:63230/",
"http://localhost:63257/",
"http://localhost:63514/",
"http://localhost:63519/",
"http://localhost:63638/",
"http://localhost:63692/",
"http://localhost:63838/",
"http://localhost:64029/",
"http://localhost:64098/",
"http://localhost:64294/",
"http://localhost:64873/",
"http://localhost:65081/",
"http://localhost:65266/",
"http://localhost:65271/",
"http://localhost:65311/"
],
"OAUTH2_LOGOUT_URL": "https://login.nextstrain.org/logout",
"COGNITO_USER_POOL_ID": "us-east-1_Cg5rcTged",
"OIDC_USERNAME_CLAIM": "cognito:username",
Expand Down
19 changes: 19 additions & 0 deletions env/testing/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading