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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions docs/knowledge/devops-tools/aws/cognito.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,41 @@ so the next app's redirect skips the login form — that is
- **`name` and `picture` come in the ID token**, from the user's attributes; `picture`
is only a URL, so the image must be hosted elsewhere.
- **Self-signup can be off** for a private pool; users are created by an admin.
- **No Dynamic Client Registration.** Cognito cannot register clients on the fly, so it
cannot be the authorization server for a "paste a link" remote
[MCP connector](../../web-development/mcp-authorization.md) without a shim or
pre-registered client.
- **Pools created with a retain removal policy** are not deleted when the stack is;
delete them by hand once nothing uses them.
- **Global sign-out** revokes the user's refresh tokens; access tokens already issued
stay valid until they expire.

## Dynamic Client Registration for MCP

Cognito can now let applications register their own app clients at runtime (RFC 7591),
which is what a remote [MCP connector](../../web-development/mcp-authorization.md)
needs to onboard from just a URL. It is off by default (console: user pool →
Applications → **MCP auth**).

- **Requirements:** the Essentials or Plus feature plan, and **managed login** on every
domain of the pool. For MCP, a **resource server** whose identifier is the MCP
server's URL, with custom scopes; clients send the `resource` parameter and the access
token's `aud` is then that URL.
- **Two modes:** *open* registration (no token) and *authenticated* registration (an
initial access token from a client holding the system scope `aws.cognito/dcr/register`).
Claude's connector cannot present an initial token, so it needs open registration.
- **Discovery:** the OIDC document (`/.well-known/openid-configuration`) lists
`registration_endpoint` (`/oauth2/register`). The RFC 8414 path
`/.well-known/oauth-authorization-server` still answers 400 on the issuer, so a client
that does not fall back to OIDC discovery needs a small shim on the MCP server.
- **Cost of open registration:** anyone can create clients (they share the app-client
quota, 10,000 with DCR on); registered clients get every identity provider of the
pool and the default auth flows; there is **no consent screen**, so a user with a live
session can be signed in to a hostile client without a prompt; there is no
per-connection grant, so revoking means deleting the client (list them with
`ListUserPoolClients` and `ClientType=DCR`). AWS suggests a WAF rate limit on
`/oauth2/register`, which is an extra paid component.

In a shared SSO pool this puts anonymous registration next to every other app, so a
dedicated pool (federating the SSO pool) or a self-run authorization server are the
alternatives when that is too open.

## When to Use Which

- Need "is this user logged in, and who are they" for your own API? →
Expand Down Expand Up @@ -109,5 +135,5 @@ for the specific AWS resources the client needs to touch directly.
direct client-side uploads.
- [Single Sign-On with OIDC](../../web-development/single-sign-on-oidc.md) — several
apps as clients of one pool.
- [MCP Authorization](../../web-development/mcp-authorization.md) — why a provider
without Dynamic Client Registration complicates remote MCP connectors.
- [MCP Authorization](../../web-development/mcp-authorization.md) — remote MCP
connectors: delegating to Cognito's DCR versus running your own authorization server.
44 changes: 32 additions & 12 deletions docs/knowledge/web-development/mcp-authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,35 @@ The MCP server only validates tokens issued by a provider such as
[Cognito](../devops-tools/aws/cognito.md), and points `authorization_servers` at it.

- **Pros:** no token issuance code to maintain; one place for users and MFA.
- **Cons:** the provider must support what the client expects. Cognito, notably, has
**no Dynamic Client Registration**, so a connector can only work if someone
pre-registers a client and gives the assistant that client id by hand (and a shim in
front of the provider usually has to paper over the missing discovery documents).
Tokens are also issued for the whole pool, so the server must check the client and
audience to know a token was meant for it.
- **Cons:** the provider must support what the client expects, and you inherit its
defaults. Tokens are issued for the whole pool, so the server must check issuer,
audience and scope to know a token was meant for it.

Whether a provider can onboard "paste a link" connectors depends on **Dynamic Client
Registration**. Cognito used to have none (a connector then needed a hand-registered
client id, plus a shim route on the MCP server to paper over missing discovery
documents). It now has an opt-in DCR for MCP (managed login, a resource server per MCP
server whose identifier is the MCP URL, open or authenticated registration; see
[Cognito](../devops-tools/aws/cognito.md#dynamic-client-registration-for-mcp)). That
removes the token code, but not the trade-offs below.

**Delegating with open registration is a weaker posture:**

- **No consent screen of your own.** A registered client chooses its own redirect
URIs, and a user who already has an SSO session can be signed in to it without a
prompt. A phishing link plus a client the attacker registered can then mint a
token. A self-run server can instead allow only the assistant vendor's callbacks
and ask "approve this app?" every time.
- **Open registration is anonymous and shared.** Anyone can create clients in the
pool (counted against its quota) unless you front it with a rate limit, and in a
shared SSO pool the clutter and the allowed scopes sit next to every other app.
- **Revocation is client deletion**, not a per-connection grant you can list.

!!! tip "Rule of thumb"
"Paste a link and it works, for several different assistant accounts" means the
server must speak DCR, which in practice means it runs its own small authorization
server. Delegating to a provider is simpler when the clients are known in advance.
"Paste a link and it works, for several different assistant accounts" needs DCR.
A provider's DCR is the lowest-code way; a small self-run authorization server is
the one that gives you consent, a redirect allow-list and per-connection
revocation. Delegating is simplest when the clients are known in advance.

## Design Decisions That Matter

Expand Down Expand Up @@ -194,8 +212,10 @@ grant row, all pointing at the approving user's id. That gives:
bearer token.
- The MCP server is a resource server; whether it also acts as the authorization
server decides whether "just a link" onboarding is possible.
- No DCR (as in Cognito) means manual client registration; running a small
authorization server with DCR removes it.
- "Just a link" onboarding needs DCR: either the provider's (Cognito now offers one,
with open registration, no consent screen and client-deletion revocation) or a
small authorization server of your own (consent, redirect allow-list, per-grant
revocation).
- Bind every grant to the approving user's id, hash all secrets, rotate refresh
tokens and revoke the grant on reuse, restrict DCR, and give users a revoke page.
- Validate `client_id` and `redirect_uri` before ever redirecting.
Expand All @@ -209,4 +229,4 @@ grant row, all pointing at the approving user's id. That gives:
- [FastMCP: Building and Deploying an MCP Server](../machine-learning/fastmcp-knowledge-base-server.md)
— the server side: tools, transports, deployment.
- [AWS Cognito](../devops-tools/aws/cognito.md) — the identity provider used in the
delegated variant, and its missing DCR.
delegated variant, and its opt-in DCR for MCP.
Loading