Browser-Based Apps and Cross-Device Flows on Amazon Cognito - RFC 10017 and RFC 10027 Mapped to App Client Settings
First Published:
Last Updated:
Developers working with Amazon Cognito user pools to create sign-in experiences for Single Page Applications (SPAs) and mobile apps may be asked to demonstrate how their applications align with these new BCPs. However, many of the
MUST requirements in RFC 10017 are written as requirements that the authorization server enforces, while RFC 10027 addresses most of its requirements to implementers and gives the authorization server MAY-level options. What the Cognito app client offers are settings that make those features available. Simply having a configuration option available is not the same as a requirement being enforced. Furthermore, for some requirements no setting is found in the documentation, and some requirements are directed at the application itself, rather than Cognito.This article maps the requirements of RFC 10017 and RFC 10027, presenting each requirement that it maps with its section number and requirement word, and correlates them to the names of settings within Amazon Cognito's app client. The setting names are presented as they appear in the API, AWS CloudFormation, and console. The mapping is categorized into four types: settings that correspond to specific requirements, features that are available but not made mandatory by a setting, settings that are not found, and requirements that are the responsibility of the application. The information presented was verified as of November 4, 2026.
This article is not a step-by-step guide for configuring Cognito, nor is it an introduction to OAuth. It does not provide a comprehensive assessment of whether Cognito is compliant with the RFCs, nor does it discuss pricing.
Related articles on this site:
- Amazon Cognito Federation Complete Implementation Guide - Google, Apple, Microsoft, OIDC, and SAML
- NIST IR 8587 Mapped to AWS Controls - Signing Keys, Audience, Token Lifetimes, Revocation, and What the Settings Leave Open
- OAuth 2.0 and OIDC Flow Visualizer and PKCE Generator - Authorization Code, Client Credentials, and S256 Challenge Builder
- AWS History and Timeline regarding Amazon Cognito - Overview, Functions, Features, Summary of Updates, and Introduction
- JWT and JOSE Standards History and Timeline - JWS, JWE, JWK, JWA, JWT, and How the Algorithm Registry Has Changed
- HTTP Security Headers Complete Reference - CSP, HSTS, COOP, COEP, Permissions Policy
- Passkeys and WebAuthn in Practice - Discoverable Credentials, Synced Versus Device-Bound Keys, and Why Account Recovery Decides the Design
- Where AI Agent Authorization Standards Stand - RFCs, IETF Working Group Documents, Individual Drafts, and Specifications from Other Bodies
Table of Contents
- 1. Scope and Assumptions
- 2. Understanding the Tables
- 3. Three Architectures in RFC 10017 and the Cognito App Client
- 4. RFC 10017 Requirements and App Client Settings
- 5. Refresh Tokens
- 6. Storing Tokens in the Browser
- 7. RFC 10027 and Cognito
- 8. Where the Sources Differ and Where No Statement Is Found
- 9. What the Demo Showed
- 10. Frequently Asked Questions About RFC 10017, RFC 10027, and Cognito
- 11. Summary
- 12. References
1. Scope and Assumptions
This chapter defines the intended audience, the scope of this article, the relevant source materials, and any potentially ambiguous terminology.1.1 Intended Audience
This article is intended for individuals who are using Cognito's user pools to handle sign-in for SPA (Single Page Application) and mobile apps, and who need to explain whether their applications follow the new BCPs. It also targets those responsible for reviewing app client settings. Specifically, this article is written for readers who believe the following:- Cognito supports Proof Key for Code Exchange (PKCE), ensuring compliance with RFC 10017.
- Implicit grant has been deprecated in OAuth 2.1.
- If refresh token rotation is enabled, sender constraints are not required.
- Cognito also supports device flow.
Each of these holds only under conditions, or has no supporting statement in the documentation. Chapters 4 through 8 will outline the extent to which these points can be supported by the existing documentation.
1.2 Scope: What This Article Covers, and What It Does Not
This article will address the following topics:- Requirements outlined in RFC 10017 and RFC 10027, including section numbers, requirement words, and to whom each requirement is addressed.
- App client settings and default values within Cognito user pools, specifically the names used in the API, CloudFormation, and console.
- Whether a particular setting exists, and whether that setting makes a requirement mandatory.
- Refresh token rotation and revocation.
- Options for storing tokens within a browser, and the storage options provided by AWS Amplify.
- The fact that a relatively small number of requirements from RFC 10027 can be directly mapped to Cognito settings.
- Items for which documentation was not found.
This article does not cover the following:
- Pricing, including the pricing of feature plans. It only lists feature plan names and which plans a feature is available in.
- Configuration steps and code for Cognito. This is already covered in the existing Amazon Cognito Federation Complete Implementation Guide.
- The history and timeline of OAuth and OpenID Connect.
- Comparisons and evaluations of other identity providers.
- Federation with external identity providers, and Cognito identity pools.
- Attack methodologies. This article will not include details on how to steal tokens using cross-site scripting (XSS) or provide code to demonstrate cross-site request forgery (CSRF). It will only cover the requirements for defense.
- Three parts of RFC 10017 that this article does not map: §6.3.3.2 (the authorization server
SHOULD NOTprocess authorization requests automatically without user consent or interaction, except when it can assure the identity of the client application), §6.3.3.3 (the initiator and receiver origins of apostMessagemessageMUSTbe verified), and §9.1 (the authorization serverSHOULD NOTinclude any ID token claims that the client does not use). - TLS key exchange and time validation. These topics are covered in two other articles in this series: When Does a Connection to an AWS Endpoint Actually Use ML-KEM? and Trusting the Clock When Certificates Expire Fast.
1.3 Date of Review and Materials Reviewed
This article was written after reviewing the following materials on November 4, 2026. Abbreviations enclosed in parentheses will be used throughout the text.- IETF RFC 10017, OAuth 2.0 for Browser-Based Applications (RFC 10017). Best Current Practice, BCP 212, August 2026.
- IETF RFC 10027, Best Current Practice for Security of Cross-Device Flows (RFC 10027). Best Current Practice, BCP 247, August 2026.
- The RFC Editor errata search. As of November 4, 2026, both documents had zero errata.
- In the Amazon Cognito Developer Guide, the following pages: Application-specific settings with app clients, The redirect and authorization endpoint, The token endpoint, OAuth 2.0 grants, Using PKCE in authorization code grants, Refresh tokens, Ending user sessions with token revocation, Managing user pool token expiration and caching, User pool feature plans, User pool managed login, Authentication flows.
- In the Amazon Cognito User Pools API Reference, the pages for: CreateUserPoolClient, UpdateUserPoolClient, RefreshTokenRotationType, GetTokensFromRefreshToken, RevokeToken (API Reference).
- The reference for
AWS::Cognito::UserPoolClientin AWS CloudFormation (CloudFormation Reference). - The "Tokens and credentials" page in AWS Amplify Gen 2 Documentation (Amplify Tokens page).
- Announcements from AWS What's New and articles from the AWS Security Blog. Dates are the publication dates of the announcements, and the text names the announcement in the same sentence.
RFC 10017 draws upon the requirements outlined in RFC 9700 (BCP 240, Best Current Practice for OAuth 2.0 Security), while PKCE is defined in RFC 7636, Demonstrating Proof of Possession (DPoP) as an example of sender constraints is specified in RFC 9449, and the device authorization grant is defined in RFC 8628. This article does not rewrite the content of these RFCs; it covers only what the text of RFC 10017 and RFC 10027 cites from them. According to the datatracker page, the original drafts of these two RFCs are draft-ietf-oauth-browser-based-apps and draft-ietf-oauth-cross-device-security.
1.4 Terminology and Distinctions of Terms with Similar Spellings
This article uses the following terms with the following meanings:- Authorization Server: A server that issues tokens in OAuth. In this article, this refers to the authorization endpoint and token endpoint of a Cognito user pool.
- Public Client and Confidential Client: These terms refer to the distinction outlined in RFC 6749 §2.1. A public client is a client that cannot securely store its credentials, with browser-based applications being a typical example.
- Backend for Frontend (BFF): A server-side component that handles all OAuth processing for a browser-based application and also relays requests to the resource server (RFC 10017 §6.1).
- Token-Mediating Backend: A server-side component that handles OAuth processing, obtains tokens, and then passes only the access token to the browser-based application (RFC 10017 §6.2).
- Sender-Constrained Token: A token that is restricted to be used only by clients that possess a specific key. RFC 10017 §9.2 provides DPoP as an example of a method that can be used in a browser environment.
The following three sets of terms have similar spellings or meanings, but represent distinct concepts. This article keeps them apart.
- RFC 6749 defines a "public client," and Cognito has "app clients without a client secret." The app client page describes a Cognito public client as one that runs on a browser or mobile device and does not possess a client secret. This article will use "app client without a client secret" when referring to Cognito's terminology and "public client" when referencing the terminology used in RFC specifications.
- The Resource Owner Password Credentials (ROPC) grant in RFC 10017 §7.3 and Cognito's
ALLOW_USER_PASSWORD_AUTH. ROPC is an OAuth grant type that sends the user's password to the token endpoint.ALLOW_USER_PASSWORD_AUTHis an authentication flow used with Cognito'sInitiateAuthAPI. The token endpoint page lists the supportedgrant_typevalues asauthorization_code,refresh_token, andclient_credentials, but does not includepassword. No AWS statement that callsALLOW_USER_PASSWORD_AUTHROPC was found (see Section 4.6).
- The three paths for token refresh. These include the
refresh_tokengrant on the token endpoint, theREFRESH_TOKEN_AUTHauthentication flow withinInitiateAuth, and theGetTokensFromRefreshTokenAPI. The available paths differ when refresh token rotation is enabled (see Chapter 5).
2. Understanding the Tables
This chapter defines the columns of the tables in this article, the terms for the categories, and the terms for the state of the sources.2.1 Columns
The summary table in Chapter 3 uses the following seven columns, which are common to the three articles in this series.- Requirement or Guarantee: The relevant requirement from the RFC.
- Source and Strength: The section of the originating RFC and the requirement word.
- AWS Setting or Endpoint: The name of the Cognito setting or endpoint.
- Default: The value when no setting is specified.
- What It Does Not Cover: The aspects not addressed by this setting.
- How You Can Tell: Where to verify the setting.
- Where It Is Written: The page within Cognito where this is documented.
The mapping tables in Chapters 4 and 7 use the following seven columns.
- RFC and Section: The RFC number and section.
- Requirement Word: The BCP 14 requirement word, written in capitals as in the RFC.
- Addressed To: To whom the requirement is addressed. One of Authorization server, Client, BFF, Token-mediating backend, Browser-based application, or Implementers.
- Requirement: A summary of the requirement. The RFC text itself is quoted in code blocks before and after the table.
- Cognito Setting: The name of the Cognito setting. When the API and CloudFormation names are the same, only one is given.
- Category: One of the four categories listed in Section 2.2.
- Source State: The state of the material as described in Section 2.3. When the documentation has a statement, the cell is not left blank and reads Stated.
2.2 Four Categories
The categories are defined using the following four terms. Table cells use the same English spelling.- Setting exists: An app client setting that directly corresponds to the requirement exists.
- Available, no setting to require it: The functionality is available, but there is no setting within Cognito's documentation that mandates its use.
- No setting found: No setting was found that corresponds to the requirement.
- Application side: Meeting the requirement is the responsibility of the Backend for Frontend (BFF), browser code, or the implementer's choices, and is not determined by Cognito's settings or behavior. Even when using Cognito components, if the implementer chooses which components to use, this category applies.

2.3 Terms for the State of the Sources
The state of the sources is described using the following terms. These terms are also used in the English spellings in the table cells. This article takes the seven terms listed in the first article of this series, leaves out "Not recorded (stated)," and adds "Stated" to indicate that the document contains relevant text.- Stated: The document contains text that addresses the matter in question.
- Stated as not supported: The document explicitly states that the feature is not supported, is not yet supported, or that there are no plans to support it.
- Documentation does not list: The list, table, or enumeration includes values, but the specific item is not listed. This does not indicate that the feature is unavailable or unsupported.
- No statement found: Despite searching using different terms and document categories, no relevant text could be found in the documents referenced in Section 1.3. This does not indicate that the feature is unavailable or will not occur.
- Sources disagree: Both statements are shown side by side with their sources. This article does not designate either source as incorrect.
- Inference: This is an inference made within this article, and is not a statement found in any document. The same sentence says so.
- Observation: This refers to findings from testing conducted in Chapter 9. It is not a commitment in the documentation. Observations do not override statements in the documentation.
In this article, no instances were found where Cognito documentation explicitly states that a feature is not supported ("Stated as not supported"). The "No setting found" category specifically indicates that a setting could not be found in the app client. In the "Source State" column, settings are described with either "Documentation does not list" or "No statement found". However, if Cognito meets a requirement through a fixed behavior, the column reads "Stated," because a relevant statement exists (as described in Section 4.7).
2.4 Requirement Words and to Whom a Requirement Is Addressed
RFC 10017, §2, and RFC 10027, §1.4, specify that the BCP 14 key words are read as requirement words only when they are written in all capitals. This article will reproduce requirement words using the original uppercase formatting from the RFCs. Words written in lowercase, such asmay or should, will not be treated as requirement words.Occasionally, a single section may contain requirements directed at different recipients. For example, RFC 10017 §6.3.2.1 requires that browser-based applications implement PKCE, while simultaneously requiring authorization servers to enforce PKCE in the same sentence. This article will separate requirements directed at different recipients onto separate lines.
3. Three Architectures in RFC 10017 and the Cognito App Client
Section 6 of RFC 10017 lists three architectures for browser-based applications using OAuth, in decreasing order of security. The first sentence of Section 6 states:There are three main architectural patterns available when building browser-based applications that rely on OAuth for accessing protected resources:
The patterns in this section are presented in decreasing order of security.

3.1 BFF and Token-Mediating Backend — Confidential Client and Authorization Code Grant
BFFs and token-mediating backends share similar requirements. Section 6.1.3.1 states the following:Therefore, the BFF MUST act as a confidential client by establishing credentials with the authorization server. Furthermore, the BFF MUST use the OAuth 2.0 Authorization Code grant as described in Section 2.1.1 of [RFC9700] to initiate a request for an access token.
Section 6.2.3.1 addresses the same two
MUST requirements to the token-mediating backend. The key difference between the two architectures lies in whether the access token is delivered to the browser. A BFF does not expose the token to the browser but instead forwards requests to the resource server. A token-mediating backend, on the other hand, passes the access token to the browser application, allowing the application to directly call the resource server.From Cognito's perspective, the confidential client corresponds to an app client that possesses a client secret. The app client page describes a confidential client as follows:
A confidential client has server-side resources that can be trusted with a client secret for unauthenticated API operations.
The API and CloudFormation
GenerateSecret setting determines whether a client secret is created. In the console, the selection of the "Application type" determines the default setting for whether a client secret is created. The app client page indicates that the "Traditional web application" and "Machine-to-machine application" types create a client secret. Authorization code grant is enabled by including code in the AllowedOAuthFlows setting. The API reference says that AllowedOAuthFlowsUserPoolClient must be true before AllowedOAuthFlows, CallbackURLs, and AllowedOAuthScopes can be configured.3.2 Browser-Only Clients — Public Clients and PKCE
In the architecture described in §6.3, the browser application itself functions as the OAuth client. RFC 10017 §6.3.3.1 states that because the source code of a browser application is accessible to the user's browser, it is not suitable for holding secrets, and therefore browser applications are typically deployed as public clients. §6.3.2 usesMUST to require browser-based applications that are public clients and use the authorization code grant to follow the additional requirements in §6.3.2.On the Cognito side, this corresponds to an app client without a client secret. The app client page describes it as follows:
A public client runs in a browser or on a mobile device. Because it does not have trusted server-side resources, it does not have a client secret.
The same page also provides the following recommendations for applications that are public clients:
As a best security practice in public-client apps, activate only the authorization-code grant OAuth flow, and implement Proof Key for Code Exchange (PKCE) to restrict token exchange.
It is important to note that these are recommendations. A setting that makes these recommendations mandatory is not listed in the app client configuration options, as seen in Section 4.1.
3.3 Things That Cannot Be Changed After Creation
The app client page states that once created, you cannot change whether or not it includes a client secret.You can't change whether an app client has a client secret after you create the app client.
The same page explains that you cannot add or remove a client secret using
UpdateUserPoolClient. Instead, you must create a new app client to make any changes. The CloudFormation reference also gives Replacement as the Update requires value of GenerateSecret. When changing the architecture from a BFF to a browser-only client, or vice versa, you will need to recreate the app client.The same page also contains the following statement:
You can use a confidential client, and a client secret, with a public app. Use an Amazon CloudFront proxy to add a SECRET_HASH in transit.
This statement refers to a configuration where a CloudFront proxy is placed in front of the browser application, and the proxy adds the secret. RFC 10017 §6.3.3.1 uses
MUST to require authorization servers that require a shared secret to be statically included in the SPA client to treat that client as a public client. As an inference of this article (Inference), a configuration where the proxy adds the secret is distinct from a configuration where the secret is included directly in the browser's code, and the statement in §6.3.3.1 does not directly apply to this configuration. However, no AWS documentation was found that specifies which configuration within RFC 10017 this setup corresponds to (No statement found).3.4 Summary Table
The following table outlines the core requirements of RFC 10017 and the corresponding Cognito settings for each of the three architectures. Detailed requirements are given in the table in Chapter 4 and in the text of Chapter 5.| Requirement or Guarantee | Source and Strength | AWS Setting or Endpoint | Default | What It Does Not Cover | How You Can Tell | Where It Is Written |
|---|---|---|---|---|---|---|
| The BFF uses authorization code grant as a confidential client. | RFC 10017 §6.1.3.1, MUST for the BFF. | GenerateSecret set to true, AllowedOAuthFlows includes code. | Determined by the Application type in the console. The API reference says a secret is generated when the value is true; no statement of the default was found (No statement found). | The BFF's cookies, CSRF protection, and restrictions on outbound requests. | Presence of ClientSecret in the DescribeUserPoolClient output and the AllowedOAuthFlows setting. | App client page, API reference. |
| A token-mediating backend uses authorization code grant as a confidential client. | RFC 10017 §6.2.3.1, MUST for the token-mediating backend. | GenerateSecret set to true, AllowedOAuthFlows includes code. | Same as above. | Secure storage of the access token passed to the browser. | Same as above. | Same as above. |
| Browser-only clients implement PKCE. | RFC 10017 §6.3.2.1, MUST for the browser-based application. | Include code_challenge and code_challenge_method (as request parameters, not settings) in the authorization request. | The authorization endpoint page lists these two parameters as optional. | Configuration to enforce PKCE. | Contents of the authorization request and token request. | Authorization endpoint page, PKCE page. |
| The authorization server enforces PKCE. | RFC 10017 §6.3.2.1, MUST for the Authorization server. | No setting to enforce PKCE is in the list of app client settings (Documentation does not list). | None. | Whether the token endpoint rejects an exchange when PKCE was not started. The token endpoint page says code_verifier is required only when PKCE was started (Chapter 9). | Chapter 9 demonstration. | API reference, CloudFormation reference. |
| Do not use implicit grant. | RFC 10017 §7.2, MUST NOT for both the Authorization server and Client. | Exclude implicit from the AllowedOAuthFlows setting. | Only the specified values are permitted. | Disabling implicit grant across the entire authorization server. | AllowedOAuthFlows in the DescribeUserPoolClient output. | API reference, authorization endpoint page. |
| Either rotate refresh tokens or apply sender constraints. | RFC 10017 §6.3.2.3, MUST for the Authorization server (when issuing refresh tokens). | RefreshTokenRotation. | No statement of the default was found (No statement found). | Sender-constrained refresh tokens. | RefreshTokenRotation in the DescribeUserPoolClient output. | Refresh token page, API reference. |
| Where to store tokens in the browser. | RFC 10017 §8, includes MUST NOT and NOT RECOMMENDED. | Not a Cognito setting. Amplify provides storage options. | Amplify uses localStorage. | No storage method can completely protect against malicious code. | Application code. | Amplify Tokens page, caching page. |
4. RFC 10017 Requirements and App Client Settings
This chapter maps the requirements of RFC 10017, other than those on refresh tokens and token storage, to Cognito settings. Refresh tokens are covered in Chapter 5, and token storage in Chapter 6.4.1 PKCE
RFC 10017 §6.3.2.1 states:Browser-based applications that are public clients MUST implement the PKCE [RFC7636] extension when obtaining an access token, and authorization servers MUST support and enforce PKCE for such clients.
This single sentence addresses two audiences. The first part requires browser-based applications to implement PKCE, and the second part requires authorization servers to support and enforce PKCE. The flow of PKCE, and the process of creating a
code_challenge from a code_verifier, can be verified on this site's OAuth 2.0 and OIDC Flow Visualizer and PKCE Generator.In Cognito's documentation, PKCE is described as a parameter for both authorization requests and token requests. The authorization endpoint page lists
code_challenge_method and code_challenge as follows:code_challenge_method Optional. The hashing protocol that you used to generate the challenge. The PKCE RFC defines two methods, S256 and plain; however, Amazon Cognito authentication server supports only S256.
code_challenge Optional. The proof of key code exchange (PKCE) challenge that you generated from the code_verifier.
The same page specifies that
code_challenge is only required when a code_challenge_method is specified. The token endpoint page describes code_verifier as follows:code_verifier Optional. Required only if you provided code_challenge_method and code_challenge parameters in your initial authorization request.
The PKCE page states that Cognito validates the verifier for requests that initiate PKCE.
Amazon Cognito only returns ID, access, and refresh tokens if it determines that the code verifier results in the same code challenge that it received in the authorization request.
These statements support the following two points:
- When a request initiates PKCE, Cognito validates the verifier before returning a token. RFC 9700 §2.1.1 calls this duty enforcing the correct usage of
code_verifierwhen a client sends a validcode_challenge. - The parameters of each request determine whether PKCE is started. The token endpoint page states that
code_verifieris only required when PKCE parameters are sent in the authorization request.
The list of app client settings has no setting that makes PKCE required for a client. As an inference of this article (Inference),
support and enforce PKCE for such clients in §6.3.2.1 includes requiring PKCE from public clients, which is broader than the duty in RFC 9700 §2.1.1. As of November 4, 2026, the API reference listed 24 parameters for CreateUserPoolClient, 23 for UpdateUserPoolClient, and 23 properties for AWS::Cognito::UserPoolClient in CloudFormation. None of these lists include any items that mention PKCE, code_challenge, or code_verifier in their names or descriptions (Documentation does not list). No statement about an item that makes PKCE mandatory was found on the console procedure pages either (No statement found).This article does not conclude that Cognito will not enforce PKCE. What the documentation indicates is that there is no setting listed that mandates PKCE, and that
code_verifier is described as required only for requests that started PKCE. The behavior when an authorization code obtained without starting PKCE is exchanged without a verifier is tested in Chapter 9.The first half of §6.3.2.1, the requirement that browser-based applications implement PKCE, is an application-side requirement. The recommendation on the app client page (Section 3.2) is also addressed to this side.
4.2 CSRF Protection
RFC 10017 §6.3.2.2 usesMUST to require browser-based applications to prevent CSRF attacks against their redirect URI, and lists three methods.Browser-based applications MUST prevent CSRF attacks against their redirect URI. This can be accomplished by any of the below:
These three methods are: configuring the authorization server to require PKCE for the client, using and verifying a unique value for the OAuth
state parameter, and using and verifying the OpenID Connect nonce parameter if the application also uses OpenID Connect. As Section 4.1 shows, Cognito's configuration for the first method is not listed. The authorization endpoint page lists the state and nonce parameters, describing state as follows:state Optional, recommended. When your app adds a state parameter to a request, Amazon Cognito returns its value to your app when the /oauth2/authorize endpoint redirects your user. Add this value to your requests to guard against CSRF attacks.
As an inference of this article (Inference), for browser-based applications using Cognito, the means of meeting this requirement will involve the application generating and verifying either the
state or nonce parameter. Both options require processing on the application's side.4.3 The Implicit Grant and Access Tokens in the Authorization Response
RFC 10017 §7.2 states the following:To effectively prevent the use of this flow, the authorization server MUST NOT issue access tokens in the authorization response and MUST issue access tokens only from the token endpoint. Browser-based clients MUST use the Authorization Code grant type and MUST NOT use the Implicit grant type to obtain access tokens.
The preceding statement is intended for the authorization server, while the subsequent statement is directed towards the browser client. This article puts them in separate rows.
In Cognito, the
AllowedOAuthFlows setting of each app client determines the allowed grant types. The API reference lists three possible values.Valid Values: code | implicit | client_credentials
This list is a closed enumeration and, as of November 4, 2026, includes
implicit. The authorization endpoint page states the following regarding implicit grants:An implicit grant is less secure because it exposes tokens and potential identifying information to users. You can deactivate support for implicit grants in the configuration of your app client.
The grants page positions implicit grants as follows:
The implicit grant is a legacy authorization grant. Unlike with the authorization code grant, users can intercept and inspect your tokens. To prevent token delivery through implicit grant, configure your app client to support authorization code grant only.
Therefore, the preceding statement in §7.2 – the requirement that the authorization server not issue an access token in the authorization response – is addressed by excluding
implicit from the AllowedOAuthFlows setting for each app client (Setting exists). However, this setting is specific to each app client; there is no documentation stating that it is possible to disable implicit grants across an entire user pool (No statement found). If another app client in the same user pool permits implicit, that client will receive a token in the authorization response.The subsequent statement in §7.2 – the requirement that the browser client not use implicit – is an application-side requirement.
The rationale for not using implicit is based on RFC 9700 and RFC 10017 §7.2. As of November 4, 2026, according to the datatracker, OAuth 2.1 is an Active Internet-Draft (draft-ietf-oauth-v2-1-17), last updated on October 30, 2026. Cognito’s documentation positions implicit as a
legacy option, but no statement about a planned end was found (No statement found).4.4 Shared Secret
RFC 10017 §6.3.3.1 places the following two requirements on the authorization server:authorization servers MUST NOT require client authentication of browser-based applications using a shared secret, as this serves no value beyond client identification, which is already provided by the client_id parameter.
Authorization servers that still require a statically included shared secret for SPA clients MUST treat the client as a public client and not accept the secret as proof of the client's identity.
In Cognito, the
GenerateSecret setting determines whether an app client must provide a client secret. If an app client is created without a client secret, Cognito does not require that client to provide one (Setting exists). As described in Section 3.3, this choice cannot be changed after the client is created.There is no corresponding setting for the second item (No setting found). The second item assumes a configuration where the secret is included in the code running in a browser. From Cognito's perspective, an app client that possesses a client secret is considered a confidential client, and Cognito will verify that secret. Cognito cannot determine which app clients have secrets distributed in the browser code. As an inference of this article (Inference), meeting this requirement relies on the application's choice to avoid including the secret in the browser code.
4.5 Registration and Matching of Redirect URIs
RFC 10017 §6.3.3.2.1 places aMUST on the client and a MUST on the authorization server.Clients MUST register one or more redirect URIs with the authorization server and use only exact registered redirect URIs in the authorization request.
Authorization servers MUST require an exact match of a registered redirect URI as described in Section 4.1.1 of [RFC9700].
In Cognito, redirect URIs are registered in the app client's
CallbackURLs. The API reference description for CallbackURLs includes the following statement.Amazon Cognito doesn't accept authorization requests with redirect_uri values that aren't in the list of CallbackURLs that you provide in this parameter.
That same description specifies that redirect URIs must be absolute URIs, without fragments, and requires HTTPS, with the exception of
http://localhost, http://127.0.0.1, and http://[::1].While
CallbackURLs represent a configured setting that meets registration requirements (Setting exists), no statement in the Cognito documentation says that the matching is an exact match (No statement found). A search of the developer guide, API reference, SDK type descriptions, and the AWS re:Post knowledge center for exact match and wildcard found only the statement that values not in the CallbackURLs list are not accepted. This article does not state, either, that the matching is not an exact match.4.6 ROPC Grant
The text in RFC 10017 §7.3 states:The Resource Owner Password Credentials Grant MUST NOT be used, as described in Section 2.4 of [RFC9700].
The same section uses
MUST to require browser-based applications using OAuth or OpenID Connect to use a redirect-based flow.As stated in Section 1.4, the
grant_type values listed on the Cognito token endpoint page do not include password (Documentation does not list). Cognito's ALLOW_USER_PASSWORD_AUTH is an authentication flow used with the InitiateAuth API, but it is not a grant type for OAuth token endpoints. No statement was found in AWS documentation that treats this authentication flow as the ROPC grant of the RFC (No statement found).This article does not map Section 7.3 to Cognito's configuration. Section 7.3 is addressed to applications and requires them to use a redirect-based flow (Application side). Whether a browser-based application sending a password through Cognito's API constitutes a flow that aligns with Section 7.3's redirect-based flow is outside the scope of this article.
4.7 CORS
RFC 10017 §6.3.3.4 requires both the authorization server and the resource server to send the necessary CORS headers.The authorization server and the resource server MUST send necessary CORS headers (defined in [Fetch]) to enable the application to make the necessary cross-origin requests.
The same section states that it does not define the concrete CORS policy, and that the policy can be a wildcard origin.
This specification does not include guidelines for deciding the concrete CORS policy implementation, which can consist of a wildcard origin or a more restrictive configuration.
The token endpoint page states:
The token endpoint returns an Access-Control-Allow-Origin: * response header. You can call the token endpoint cross-origin from a browser-based application.
That page also indicates that this endpoint does not support custom CORS origin policies. The managed login page lists three endpoints—the token endpoint, the revocation endpoint, and the userInfo endpoint—as returning
Access-Control-Allow-Origin: *.The token endpoint page and the managed login page say that custom CORS origin policies are not supported, so no user setting is listed for this requirement. In the observation in Chapter 9, the token endpoint returned the same value as the request's
Origin, rather than * (see Section 9.6). This article records the source state of this row as "Stated" and does not use the "Setting exists" category. The CORS configuration for the resource server is a requirement on the user's side (Application side).4.8 Requirements for BFF and Token-Mediating Backend
RFC 10017, sections §6.1.3 and §6.2, impose many requirements on the BFF and the token-mediating backend. Examples include:- §6.1.3.2: The BFF's cookies
MUSThave the Secure and HttpOnly attributes,SHOULDhave theSameSite=Strictattribute, andSHOULDstart the cookie name with a prefix indicating that it was set via HTTP (for example,__Host-Http-). - §6.1.3.3: The BFF
MUSTimplement CSRF protection. - §6.1.3.6: The BFF
MUSTperform outbound control to verify the destination host before relaying requests. - §6.2.2.3: The token-mediating backend
SHOULD NOTreturn an access token to the browser if its scope is broader than the scope requested by the browser; instead, itSHOULDobtain a token with a narrower scope using a refresh token.
These requirements are addressed to the BFF or the token-mediating backend, not to Cognito settings (Application side). The general meaning of cookie attributes is covered in this site's HTTP Security Headers Complete Reference.
Regarding the scope reduction described in §6.2.2.3, RFC 10017 states that whether to support this functionality is at the authorization server's discretion. No statement was found in the description of
refresh_token on the Cognito token endpoint page regarding scope reduction in refresh requests (No statement found).4.9 The Mapping Table
The following table lists the requirements discussed in Chapter 4, one by one.| RFC and Section | Requirement Word | Addressed To | Requirement | Cognito Setting | Category | Source State |
|---|---|---|---|---|---|---|
| RFC 10017 §6.1.3.1 | MUST | BFF | Use authorization code grant as a confidential client. | GenerateSecret, code in AllowedOAuthFlows | Setting exists | Stated |
| RFC 10017 §6.2.3.1 | MUST | Token-mediating backend | Use authorization code grant as a confidential client. | GenerateSecret, code in AllowedOAuthFlows | Setting exists | Stated |
| RFC 10017 §6.3.2.1 | MUST | Browser-based application | Implement PKCE. | None (relies on request parameters code_challenge and code_challenge_method) | Application side | Stated |
| RFC 10017 §6.3.2.1 | MUST | Authorization server | Support and enforce PKCE. | Support is handled through request parameters. There is no setting to enforce it. | Available, no setting to require it | Documentation does not list |
| RFC 10017 §6.3.2.2 | MUST | Browser-based application | Prevent CSRF attacks on the redirect URI. | None. The application uses state or nonce. | Application side | Stated |
| RFC 10017 §7.2 | MUST NOT, MUST | Authorization server | Do not issue access tokens in the authorization response. | Remove implicit from AllowedOAuthFlows (per app client). | Setting exists | Stated |
| RFC 10017 §7.2 | MUST, MUST NOT | Client | Use authorization code grant and do not use implicit grant. | None | Application side | Stated |
| RFC 10017 §6.3.3.1 | MUST NOT | Authorization server | Do not require browser-based applications to authenticate using a shared secret. | Set GenerateSecret to false (cannot be changed after creation). | Setting exists | Stated |
| RFC 10017 §6.3.3.1 | MUST | Authorization server | Do not accept a secret distributed to an SPA as proof of identity. | None | No setting found | No statement found |
| RFC 10017 §6.3.3.2.1 | MUST | Client | Register redirect URIs and only use those registered URIs. | CallbackURLs | Setting exists | Stated |
| RFC 10017 §6.3.3.2.1 | MUST | Authorization server | Require an exact match between the registered redirect URI and the URI used. | CallbackURLs (no explicit wording for exact match) | No setting found | No statement found |
| RFC 10017 §7.3 | MUST NOT | Browser-based application | Do not use ROPC grant. | Not mapped. password is not among the grant_type values. | Application side | Documentation does not list |
| RFC 10017 §6.3.3.4 | MUST | Authorization server | Send the necessary CORS headers. | None (the token endpoint page says Cognito returns * and does not support custom CORS origin policies). | No setting found | Stated |
| RFC 10017 §6.1.3.2, §6.1.3.3, §6.1.3.6 | MUST, SHOULD, SHOULD NOT | BFF | Cookie attributes, CSRF protection, and outbound request controls. | None | Application side | Stated |
| RFC 10017 §6.2.2.3 | SHOULD NOT, SHOULD | Token-mediating backend | Do not return overly broad tokens; instead, request narrower scopes. | None (no description found regarding narrowing scopes during token refresh). | Application side | No statement found |
The §6.3.3.4 row is categorized as "No setting found," but the documentation can be read as showing that Cognito meets the requirement through its fixed behavior. The designation was assigned because there are no user-configurable settings involved.
5. Refresh Tokens
This chapter addresses the requirements for refresh tokens as outlined in RFC 10017 §6.3.2.3, and maps them to Cognito's rotation, validity period, and revocation.5.1 The Precondition and to Whom the Requirements Are Addressed
Section 6.3.2.3 states that the authorization server can choose whether or not to issue a refresh token to the browser application.Authorization servers may choose whether or not to issue refresh tokens to browser-based applications.
The word "may" in this sentence is in lowercase and does not express a requirement. The subsequent sentence requires (
MUST) that if a refresh token is issued, applications and authorization servers adhere to the recommendations for refresh tokens outlined in RFC 9700.Applications and authorization servers conforming to this BCP MUST also follow the recommendations in [RFC9700] for refresh tokens if refresh tokens are issued to browser-based applications.
Following this, the text lists three items directed towards the authorization server.
MUST either rotate refresh tokens on each use OR use sender-constrained refresh tokens as described in Section 4.14.2 of [RFC9700]
MUST either set a maximum lifetime on refresh tokens OR expire if the refresh token has not been used within some amount of time
MUST NOT, upon issuing a rotated refresh token, extend the lifetime of the new refresh token beyond the lifetime of the initial refresh token if the refresh token has a preestablished expiration time
All three items are addressed to the authorization server and apply when refresh tokens are issued. The first and second items are written with
OR, so each of them is met by meeting either of its two sides.5.2 Rotation
In Cognito, rotation is enabled through theRefreshTokenRotation setting on the app client. The API reference describes RefreshTokenRotationType as follows:The configuration of your app client for refresh token rotation. When enabled, your app client issues new ID, access, and refresh tokens when users renew their sessions with refresh tokens. When disabled, token refresh issues only ID and access tokens.
RefreshTokenRotationType consists of a Feature that can be either ENABLED or DISABLED, and a RetryGracePeriodSeconds value. The refresh token page states that a grace period of up to 60 seconds can be configured for the original refresh token. The same documentation further states that when rotation is enabled or disabled, the behavior is as follows:When this setting is enabled, each successful request in all forms of token refresh returns a new ID, access, and refresh token. When this setting is disabled, token-refresh requests return new access and ID tokens only and the original refresh token remains valid.
This setting corresponds to the
rotate side of the first requirement in §6.3.2.3 (Setting exists).Regarding the default value, the refresh token page indicates that rotation can be configured optionally and recommends enabling it as a security best practice.
You can optionally configure refresh token rotation in your app client.
As a security best practice, enable refresh token rotation on your app clients.
The API reference lists
RefreshTokenRotation as Required: No. However, no statement of the value used when it is not specified was found in the API reference, the CloudFormation reference, or the refresh token page (No statement found). This article does not state that the default is either disabled or enabled. To verify, examine the RefreshTokenRotation field in the response from DescribeUserPoolClient.Rotation was announced in the What's New announcement of April 22, 2025. The body of that announcement states that it is available for Essentials and Plus plans. The table on the feature plans page does not list rotation (Documentation does not list). There is no mention of whether it is available for Lite plans (No statement found). This article shows the two sources side by side and does not call the difference a disagreement.
5.3 Rotation Does Not Extend the Lifetime
The third requirement outlined in Section 6.3.2.3 stipulates (MUST NOT) that the lifetime of a newly issued refresh token is not extended beyond the lifetime of the original refresh token. A note on the refresh token page states:Rotation reissues a refresh token within the same fixed validity window. It doesn't extend the window.
This page also clarifies that a new refresh token is only valid for the remaining duration of the original
RefreshTokenValidity. This statement points in the same direction as the MUST NOT in §6.3.2.3.The second requirement in Section 6.3.2.3, concerning the maximum expiration period (lifetime) or expiration due to inactivity, corresponds, on the maximum-lifetime side, to the settings
RefreshTokenValidity and TokenValidityUnits (Setting exists). The API reference indicates that if RefreshTokenValidity is not specified, the default value is 30 days. No setting for expiration due to inactivity was found (No statement found). Since the second requirement is expressed as an OR condition, the formal condition is met if only the maximum value (lifetime) is configured.5.4 Sender-Constrained Tokens
The other side of theOR in the first requirement of §6.3.2.3 is sender-constrained refresh tokens. The beginning of RFC 10017, Section 6.3.2.3, states that refresh tokens for browser clients are typically bearer tokens unless DPoP is explicitly used.The placement of DPoP (RFC 9449) is addressed in this site's JWT and JOSE Standards History and Timeline. No statement about DPoP, sender-constrained tokens, or tokens bound through mutual TLS was found in the Cognito documentation (No statement found). The search terms and resources used are detailed in Section 8.3. The list of app client settings has no such items either (Documentation does not list).
This article does not state that rotation can replace sender-constrained tokens. RFC 10017 simply requires that either one of the two options be met, without stating that they provide the same effect. Furthermore, RFC 10017, Section 9.2, notes that sender-constrained tokens do not address the security limitations inherent in browser-only clients.
5.5 Linking to the User's Session
Section 6.3.2.3 also usesSHOULD to ask the authorization server to link the lifetime of the refresh token to the user's authenticated session.Authorization servers SHOULD link the lifetime of the refresh token to the user's authenticated session with the authorization server.
A review of Cognito's documentation did not reveal any statement indicating that the lifetime of the refresh token is linked to a managed login session (No statement found). Instead, the refresh token page describes facts that point the other way: that managed login sessions are stored in the browser's cookies and are valid for one hour, and that the response from
GetTokensFromRefreshToken does not update that session's cookie.To invalidate refresh tokens when a user signs out, the revocation APIs are available:
GlobalSignOut and RevokeToken (see Section 5.7). However, these are APIs that the application must call directly and are not automatically linked to a session. This article categorizes this as "No setting found."The final sentence in Section 6.3.2.3 states that the authorization server
MAY set different policies for refresh token issuance, lifetime, and expiration for browser applications than for other public clients. In Cognito, the validity period and rotation of refresh tokens are configured on a per-app client basis. Therefore, by creating a separate app client specifically for browser applications, it is possible to implement different policies.5.6 Three Refresh Paths
There are three paths for using refresh tokens with Cognito, and the available options differ depending on whether rotation is enabled.The first is the
refresh_token grant for the token endpoint. The refresh token page states the following:The token endpoint in user pools with a domain has a refresh_token grant type that issues new ID, access, and optionally (with refresh token rotation) refresh tokens from a valid refresh token.
The second is the
REFRESH_TOKEN_AUTH authentication flow within InitiateAuth and AdminInitiateAuth. The refresh token page states that this path is not available in app clients with rotation enabled.REFRESH_TOKEN_AUTH isn't available in app clients with refresh token rotation enabled.
The third is the
GetTokensFromRefreshToken API. The API reference for RefreshTokenRotationType states that rotation is to be completed with this API.Refresh token rotation must be completed with GetTokensFromRefreshToken.
This statement is in the API reference; the refresh token page does not contain the same statement. The refresh token page states that app clients with rotation enabled use the
GetTokensFromRefreshToken API, while app clients without rotation use the REFRESH_TOKEN_AUTH flow. The token endpoint path, as mentioned above, remains available even with rotation enabled.| Path | Rotation Disabled | Rotation Enabled | Source |
|---|---|---|---|
Token endpoint refresh_token grant | New ID and access token | New ID, access, and refresh token | Refresh token page, token endpoint page |
InitiateAuth REFRESH_TOKEN_AUTH | New ID and access token | Not available | Refresh token page |
GetTokensFromRefreshToken | New ID and access token | New ID, access, and refresh token | API reference, refresh token page |
The previously published NIST IR 8587 Mapped to AWS Controls, §6.4, also addresses
GetTokensFromRefreshToken and rotation. That article presents the information from a NIST perspective, while this article presents it from the perspective of RFC 10017, covering the same configuration.5.7 Token Revocation and JWT Validation
Cognito provides two mechanisms for token revocation: theRevokeToken API and the /oauth2/revoke endpoint. These are available when the app client's EnableTokenRevocation setting is enabled. The API reference states that if this setting is not specified, newly created app clients will have revocation enabled by default.If you don't include this parameter, token revocation is automatically activated for the new user pool client.
The revocation page notes the following regarding revoked tokens:
Revoked tokens can't be used with any Amazon Cognito API calls that require a token. However, revoked tokens will still be valid if they are verified using any JWT library that verifies the signature and expiration of the token.
If the resource server only validates the JWT signature and expiration date using Cognito's public key, revoked access tokens will remain valid until their expiration date. As an inference of this article (Inference), to carry the effect of revocation to the resource server, either the access token's validity period must be shortened, or the resource server must be designed to validate tokens against the Cognito API. According to the API reference for
RevokeToken, revocation applies to access tokens generated from the specified refresh token, as well as any access tokens generated concurrently with it.The existing Amazon Cognito Federation Complete Implementation Guide, Chapter 12, discusses how to use revocation. This article only states that revocation provides a mechanism that corresponds to the
SHOULD (Section 5.5) in RFC 10017 §6.3.2.3 and the MAY (Chapter 7) in RFC 10027 §6.1.6.6. Storing Tokens in the Browser
This chapter outlines five methods for token storage as described in RFC 10017 §8, explores the storage options available within Amplify, and references relevant passages from the Cognito developer guide. Token storage is not a setting configured in the Cognito app client itself. Instead, it is a choice made by the browser-based application.6.1 RFC 10017 §8: Five Methods
§8 discusses where tokens should be stored when a browser application directly handles them, outlining five methods. These are: Cookies (§8.1), Service Workers (§8.2), Web Workers (§8.3), memory (§8.4), and persistent storage (§8.5). Requirement words appear in two places.§8.1 describes how tokens can be stored in Cookies using JavaScript's Cookie API, and subsequently read and attached to API requests.
Because of these unintentional side effects of using cookies for JavaScript-based storage, this practice is NOT RECOMMENDED.
This section also clarifies that this method differs from using a Backend for Frontend (BFF) that sends JavaScript-invisible Cookies to the backend.
§8.2 discusses storing tokens within a Service Worker, isolating them from the main application.
When aiming to isolate tokens from the application's execution context, the Service Worker MUST NOT store tokens in any persistent storage API that is shared with the main window.
§8.5 lists
localStorage, sessionStorage, and IndexedDB, concluding with the following statement.Note that the main difference between these patterns is the exposure of the data, but none of these options can fully mitigate token exfiltration when the attacker can execute malicious code in the application's execution environment.
The beginning of §8 notes that even with completely isolated storage, an attacker whose malicious code runs can still obtain new tokens from the provider.
6.2 Amplify Storage Options
The Amplify Tokens page describes the following storage options:The default option is localStorage. Additionally, you can import the sessionStorage, sharedInMemoryStorage or CookieStorage options as well.
The same page notes that
localStorage persists across browser sessions and tabs, while sessionStorage is cleared when a tab is closed. CookieStorage saves the token in the browser's cookies. No description of sharedInMemoryStorage beyond its name was found (No statement found).6.3 The Sentence in the Cognito Developer Guide
The caching page of the Cognito developer guide contains the following sentence:A client-side app must store tokens in a memory cache. A server-side app can add an encrypted cache mechanism to store tokens.
This text appears within a paragraph discussing token validity periods and caching strategies to reduce the number of requests to Cognito. This article does not read this sentence as a general rule about where tokens are stored. Amplify's default
localStorage and this text address different topics. This article shows both and does not call this a disagreement.6.4 Storage Table
| RFC 10017 Method | Requirement Word | Amplify Option | Category | Notes |
|---|---|---|---|---|
| §8.1 Storing tokens in cookies with JavaScript | NOT RECOMMENDED | CookieStorage | Application side | The Amplify Tokens page does not state whether the CookieStorage cookies are HttpOnly (No statement found). As an inference of this article (Inference), cookies written by a browser library fall under §8.1, storing tokens in cookies with JavaScript. |
| §8.2 Service Worker | MUST NOT (Do not store in persistent storage shared with the main window) | None | Application side | No Service Worker option was found on the Amplify Tokens page (No statement found). |
| §8.3 Web Worker | None | None | Application side | §8.3 provides an example of a configuration that places refresh tokens in the Web Worker's memory. |
| §8.4 Memory | None | sharedInMemoryStorage (No description found) | Application side | The memory cache sentence on the caching page is in a paragraph about caching. |
| §8.5 Persistent Storage | None (states that none of them fully mitigates token exfiltration) | localStorage (default), sessionStorage | Application side | sessionStorage is tied to a tab and has a limited scope for sharing. |
Every row is in the Application side category. The Cognito app client does not have a setting to determine where tokens are stored. What Cognito can do is shorten the token's validity period, and utilize token rotation and revocation (Chapter 5). Modifying Amplify's defaults and which paths Amplify uses for token refresh are outside the scope of this article.
7. RFC 10027 and Cognito
This chapter outlines the alignment between the requirements of RFC 10027 and the configuration of Cognito. In short, only a few requirements could be confirmed in the Cognito documentation to map to a setting.7.1 What RFC 10027 Addresses
RFC 10027 deals with flows that span two devices. It refers to the device initiating the flow as the "Consumption Device" and the device granting authorization as the "Authorization Device." An example provided at the beginning of §1 describes a user scanning a QR code displayed on a television screen with a smartphone, thereby granting access to a video service through the television's application.§5 lists several protocols that are susceptible to attacks on cross-device flows, including OAuth 2.0 Device Authorization Grant (RFC 8628), OpenID Foundation's Client-Initiated Backchannel Authentication (CIBA), OpenID for Verifiable Credentials, and Self-Issued OpenID Provider v2.
7.2 Requirements for Implementers
RFC 10027 §2 addresses its first requirement to implementers.Implementers MUST perform a risk assessment before implementing cross-device flows, weighing the risks from CDCP and CDSP attacks against benefits for users.
CDCP and CDSP are abbreviations for Cross-Device Consent Phishing and Cross-Device Session Phishing, respectively, as defined in RFC 10027. §2 continues by stating that implementers
SHOULD avoid cross-device flows if risks cannot be sufficiently mitigated, SHOULD adhere to the protocol selection outlined in §6.2, MUST choose mitigation measures as described in §6.1, and SHOULD consider incorporating proximity as a mitigation measure where possible. All of these requirements are addressed to implementers, not to Cognito settings (Application side).§5 uses
SHOULD NOT for using cross-device protocols in same-device scenarios.Cross-device protocols SHOULD NOT be used for same-device scenarios.
The same section states that when the Consumption Device and Authorization Device are on the same device, the OpenID Connect Core and OAuth 2.0 authorization code grant flow is more appropriate. Within Cognito's app clients, allowing the authorization code grant flow is configured through the
AllowedOAuthFlows setting, specifically the code option. As an inference of this article (Inference), for same-device scenarios, this section's requirements can be met by the application selecting the authorization code grant flow, and no additional configuration is required within Cognito.7.3 Protocol Selection and Cognito
Section 6.2 compares the characteristics and appropriate uses of three protocols: device authorization grant, CIBA, and FIDO2/WebAuthn. The summary in Section 6.2.4 begins with the following sentence:The FIDO CDA flow provides the best protection against attacks on the unauthenticated channel for cross-device flows.
FIDO Cross-Device Authentication (CDA) uses hybrid transports from FIDO's Client to Authenticator Protocol (CTAP) 2.2 to indicate proximity via Bluetooth Low Energy (BLE). Section 6.2.3.5 states the following regarding the use of FIDO2/WebAuthn:
FIDO2/WebAuthn SHOULD be used for cross-device authentication scenarios whenever the devices are capable of doing so and a suitable FIDO credential is not available on the Consumption Device.
This combination of FIDO2/WebAuthn and authorization code flow with PKCE enables cross-device authorization flows, without the risks posed by the device authorization grant [RFC8628].
Between those two sentences, Section 6.2.3.5 uses
MAY to say that FIDO2/WebAuthn can be used as an authentication method with the authorization code grant and PKCE.On the Cognito side, the components involved in this combination are as follows:
- Authorization code grant is permitted by specifying
codewithinAllowedOAuthFlows(Setting exists). - PKCE can be used through request parameters, as described in Section 4.1. The list of settings has no setting that makes it mandatory (Available, no setting to require it).
- The table on the feature plans page lists
Passkey sign-in with hardware or software FIDO2 authenticatorsin the Essentials and Plus row. The authentication flow page states that passkeys are available with all feature plans except Lite, and are only supported with choice-based authentication flows.
Regarding FIDO CDA's hybrid transports, RFC 10027 §6.2.3.1 states that they are implemented by the client and authenticator platforms. The Cognito authentication flow page also states that the WebAuthn and CTAP2 standards, which form the basis for passkeys, are implemented by browsers and platforms. However, no statement in the Cognito documentation says whether its passkey sign-in supports using an authenticator on another device through hybrid transports (No statement found). This article does not state that Cognito's passkeys support FIDO CDA, nor does it explicitly state that they do not. Passkeys themselves are discussed on this site's Passkeys and WebAuthn in Practice.
7.4 The Device Authorization Grant and CIBA
Section 6.2.1.5 states that the device authorization grant is to be used only when other cross-device protocols are not viable. Section 6.2.4 usesRECOMMENDED for using the device authorization grant only when additional mitigations are deployed, and uses SHOULD for considering additional mitigations, such as proximity, when CIBA is used.The
AllowedOAuthFlows value for Cognito app clients, as described in Section 4.3, consists of three options: code, implicit, and client_credentials. The grant_type value for the device authorization grant, as defined in RFC 8628, is urn:ietf:params:oauth:grant-type:device_code, and this is not listed in the enumeration (Documentation does not list). It is also not listed among the grant_type values mentioned on the token endpoint page. No mention of CIBA was found in Cognito's documentation (No statement found).This article does not state that Cognito does not support device flows. The documentation only indicates that the specified values are not listed in two enumerations, and that no information regarding CIBA could be found.
Within AWS documentation, one resource that connects device authorization grants and Cognito is the AWS Security Blog post from November 2, 2021, titled "Implement OAuth 2.0 device grant flow by using Amazon Cognito and AWS Lambda." The post describes a configuration where AWS Lambda is used to create a custom endpoint for the device flow, and is then integrated with Cognito. This configuration is an application built by the user, rather than a setting within Cognito's user pool. Whether to build the RFC 10027 mitigations into this custom endpoint is also a requirement on the side that builds it (Application side).
Another AWS feature offers an example of cross-device sign-in. The AWS Sign-In user guide describes using
aws login --remote in the AWS CLI as a cross-device authentication method for devices without a browser. This functionality is not a feature of Cognito. How AWS sign-in separates same-device and cross-device authentication in IAM is covered in The AWS Credential Provider Chain Across SDKs and the CLI on this site.7.5 Mitigations and Cognito Settings
RFC 10027 §6.1 lists 17 mitigation strategies for cross-device flows, and usesRECOMMENDED for applying one or more of them. Many of these mitigation strategies are particularly relevant to authorization servers that issue QR codes or user codes. Given that no settings for device authorization grants can be found in Cognito's documentation, the mitigation strategies related to codes (such as short-lived codes, one-time use codes, unique codes, and rate limiting) have no corresponding setting found in Cognito's documentation (No setting found).Some mitigations point in the same direction as app client settings that are not limited to cross-device flows. The following table outlines these. However, none of these settings are specific to cross-device flows; they apply to all flows in the app client.
| RFC and Section | Requirement Word | Addressed To | Requirement | Cognito Setting | Category | Source State |
|---|---|---|---|---|---|---|
| RFC 10027 §2 | MUST, SHOULD | Implementers | Risk assessment, protocol selection, mitigation strategy selection | None | Application side | Stated |
| RFC 10027 §5 | SHOULD NOT | Implementers | Do not use cross-device protocols in scenarios involving the same device. | AllowedOAuthFlows (specifically, code – selected by the application) | Application side | Stated |
| RFC 10027 §6.1.6 | MAY | Authorization server | Invalidate tokens issued in response to codes used in an attack. | RevokeToken, EnableTokenRevocation | Setting exists | Stated |
| RFC 10027 §6.1.9 | MAY | Authorization server | Limit the scope of tokens issued for cross-device flows. | AllowedOAuthScopes (per app client, not per flow) | Setting exists | Stated |
| RFC 10027 §6.1.10 | None | Authorization server | Shorten the lifetimes of access tokens and refresh tokens. | AccessTokenValidity, RefreshTokenValidity, TokenValidityUnits | Setting exists | Stated |
| RFC 10027 §6.1.12 | None | Authorization server | Sender-constrained tokens | None | No setting found | No statement found |
| RFC 10027 §6.1.2 - §6.1.4, §6.1.11 | Includes MAY | Authorization server | Short-lived, single-use, unique codes; rate limiting | None (no device authorization grant settings found) | No setting found | Documentation does not list |
| RFC 10027 §6.2.3.5 | SHOULD, MAY | Implementers | Integration with FIDO2/WebAuthn, and combinations of authorization code grant and PKCE. | Components: AllowedOAuthFlows (specifically, code), PKCE parameters, passkeys (Essentials and Plus) | Application side | No statement found |
| RFC 10027 §6.2.4 | RECOMMENDED, SHOULD | Implementers | Use the device authorization grant only with additional mitigations; consider proximity mitigations for CIBA. | device_code is not in the enumeration. No description found for CIBA. | Application side | Documentation does not list |
Section 6.1.6 describes making the invalidation available through a token introspection endpoint (RFC 7662). However, a corresponding description of the introspection endpoint as defined in RFC 7662 is not found in the Cognito documentation (No statement found). The
RevokeToken API reference describes revoking a specified refresh token and the access tokens generated by, and at the same time as, that refresh token. No statement was found about selecting tokens by the user code or QR code that produced them (No statement found). As stated in Section 5.7, a revoked token will still pass validation if only the JWT signature and expiration date are checked. The table entries indicate the presence of a revocation setting, but do not necessarily confirm that all requirements outlined in Section 6.1.6 are met.Sections 6.2.3.5 and 6.2.4 describe choices that the implementer must make regarding which protocols and components to use, so their rows are in the Application side category. The categories of each component are given in Sections 7.3 and 7.4. The source state of the §6.2.3.5 row refers to the fact that a description of the relationship between passkeys and FIDO CDA could not be found.
8. Where the Sources Differ and Where No Statement Is Found
This chapter collects statements that are worded differently by source, and statements that could not be found despite searching.8.1 Differences in Wording Based on Source
The following describes instances where the wording differs depending on the source. This article does not decide that either source is wrong.| Item | Source A | Source B | This Article's Approach |
|---|---|---|---|
| Plans that support rotation | The What's New announcement of April 22, 2025, states that rotation is available for the Essentials and Plus plans. | The table on the feature plans page does not include a row for rotation. | Shows both. No statement about the Lite plan was found. |
| Refresh token validity period | The API reference specifies that the RefreshTokenValidity range is expressed in seconds, with a minimum of 0 and a maximum of 315360000, and that a value of 0 is replaced with the default of 30 days. | The What's New announcement of June 10, 2021 (the revocation announcement) states that the validity period can be set between 60 minutes and 10 years. | The units and presentation differ. This article gives either value only with its source. |
| Token storage | The caching page states that a client-side app must store tokens in a memory cache. | Amplify's default is localStorage. | The topics are different (Section 6.3). |
The date of the rotation announcement is the publication date of the What's New announcement. A list of Cognito update dates can be found on this site at AWS History and Timeline regarding Amazon Cognito.
8.2 Items Not Listed
The following items do not appear in the lists or enumerations (Documentation does not list).- A setting that requires PKCE. It is not among the parameters for
CreateUserPoolClient(24 parameters),UpdateUserPoolClient(23 parameters), or the properties ofAWS::Cognito::UserPoolClientin CloudFormation (23 properties). - A setting for DPoP and sender-constrained tokens. It is not in the same three lists either.
- The device authorization grant. It is not among the three values
code,implicit, andclient_credentialsof theAllowedOAuthFlowsenumeration, nor among the threegrant_typevaluesauthorization_code,refresh_token, andclient_credentialson the token endpoint page. - ROPC grant. The value
passwordis not listed on the token endpoint page undergrant_type. - A row for rotation. It is not in the table on the feature plans page.
8.3 Statements Not Found
For the following items, no statement was found despite searching with different terms and sources (No statement found).| Item | Terms Searched | Sources Searched |
|---|---|---|
| Requiring PKCE | require PKCE, enforce, code_challenge, public client | Developer Guide (app client page, PKCE page, authorization endpoint page, token endpoint page), API Reference, CloudFormation Reference, What's New announcement (through the latest, dated October 21, 2026) |
| Tokens bound by DPoP, Sender Constraints, and Mutual TLS | DPoP, Demonstrating Proof of Possession, RFC 9449, sender-constrained, proof of possession, mutual TLS | Developer Guide, API Reference, What's New announcement, AWS Blog, AWS re:Post |
| CIBA | CIBA, client initiated backchannel authentication | Developer Guide, AWS Blog, AWS re:Post |
| Exact Match for Redirect URI | exact match, wildcard, redirect_mismatch | Developer Guide, API Reference, SDK Type Description, AWS re:Post Knowledge Center |
| Default Rotation Behavior | RefreshTokenRotation, default, optionally | API Reference, CloudFormation Reference, refresh token page |
| Availability of Rotation in Lite | rotation, Lite, feature plan | feature plans page, refresh token page, What's New announcement |
| Linking Refresh Tokens (lifetime) with Sessions | session, refresh token, sign out | refresh token page, revocation page, managed login page |
| Introspection Endpoint (RFC 7662) | introspection, RFC 7662 | Developer Guide, API Reference |
| Relationship between Passkeys and FIDO CDA | hybrid, cross-device, CTAP | Developer Guide (feature plans page, authentication flow page) |
| Planned End of Implicit Grant | implicit, deprecat, legacy | Developer Guide, What's New announcement, AWS General Reference - Maintenance and End-of-Life page |
The Document History page in the Cognito developer guide was redirected to the first page of the developer guide when retrieved, so its content could not be read. The history of changes has not been read through.
There is an entry for Amazon Cognito Sync on the AWS General Reference page on services in maintenance. Cognito Sync is a separate feature from User Pools and is not the subject of this article. No statement about a planned end for user pool app clients, managed login, or the classic hosted UI was found. The feature plans page states that the classic hosted UI is available with all feature plans.
8.4 Relationship to Previously Published Articles
The previously published Amazon Cognito Federation Complete Implementation Guide covers topics such as app client configuration, PKCE, token validity periods, and how to use token refresh and revocation. This article will focus solely on mapping the requirements outlined in RFC 10017 and RFC 10027 to settings, leaving the specifics of configuration to the aforementioned guide. Where terminology or phrasing differs from that guide, this article references the text provided in Section 1.3 as the source.9. What the Demo Showed
This chapter documents building a single Cognito user pool in the us-east-1 Region, and testing specific behaviors that were not readily apparent from the documentation alone, for rows in Chapters 4 and 5. The observations presented here are observations (Observation) and do not represent guarantees from Cognito. These observations do not modify or replace the content in Chapters 4 through 8.The test was run on November 4, 2026 (Japan Standard Time). The configuration and results are as follows. Token values were not recorded. After the test, the stack, user pool, and domain were confirmed to be gone.
9.1 Configuration Tested
The following were created in us-east-1 with an AWS CloudFormation stack:- One user pool. The feature plan was set to Essentials, and deletion protection was disabled.
- One prefix domain. The branding version was set to the classic hosted UI.
- App client A. This client does not have a client secret. The
AllowedOAuthFlowsare set tocodeonly, with refresh token rotation enabled and a grace period of 10 seconds. TheExplicitAuthFlowsare set toALLOW_USER_PASSWORD_AUTH. - App client B. This client does not have a client secret. The
AllowedOAuthFlowsare set tocodeandimplicit, and refresh token rotation is disabled. TheExplicitAuthFlowsare set toALLOW_REFRESH_TOKEN_AUTHandALLOW_USER_PASSWORD_AUTH. - One user. This user was not assigned any email attributes.
Requests to the authorization endpoint and the token endpoint were sent over HTTPS from Python's standard library, and the Cognito API was called from the AWS CLI. The authorization code was obtained by signing in to the hosted UI in a browser.
Initially, app client A had
ALLOW_REFRESH_TOKEN_AUTH included in its ExplicitAuthFlows. During that initial creation, the creation of app client A failed with the following error:ALLOW_REFRESH_TOKEN_AUTH is not a permitted ExplicitAuthFlow when refresh token rotation is enabled.
Therefore,
ALLOW_REFRESH_TOKEN_AUTH was removed from app client A, and the stack was created again. This observation points in the same direction as the statement on the refresh token page (Section 5.6).9.2 Implicit and PKCE Parameters
The following table summarizes the responses to authorization requests prior to sign-in. In each case, the response was an HTTP 302 redirect.| Request | Client | Response Destination and Content |
|---|---|---|
response_type=token | A | Redirected to the callback. The URL fragment included error, error_description, and state. |
response_type=token | B | Redirected to the sign-in page. |
response_type=code and S256 code_challenge | A | Redirected to the sign-in page. |
code_challenge_method=plain | A | Redirected to the callback. The query string included error=invalid_request and error_description=unsupported_code_challenge_method. |
Sent only code_challenge_method without code_challenge | A | Redirected to the callback. The query string included error=invalid_request and error_description=missing_required_code_challenge_parameter. |
Sent only code_challenge without code_challenge_method | A | Returned with the same error as the previous row. |
| Sent without PKCE parameters | A | Redirected to the sign-in page. |
When a
response_type=token request was sent for client B and the user signed in, the callback URL fragment included access_token, id_token, token_type, expires_in, and state. There was no refresh_token. The access token's validity period was 3,600 seconds. RFC 10017 §7.2 uses MUST NOT to forbid the authorization server from issuing access tokens in this kind of response. Client A, which does not permit implicit, returned an error for the same request (Setting exists, Section 4.3).The authorization endpoint page states that the
code_challenge parameter is required when a code_challenge_method is specified. Requests that included only code_challenge without the code_challenge_method were also rejected. The authorization endpoint page lists this case, a request that provides code_challenge but not code_challenge_method, among its examples of incorrect formatting, and shows a redirect with error=invalid_request as the example response (Stated).9.3 Exchanging Authorization Codes Obtained Without Initiating PKCE
A sign-in with app client A produced an authorization code, which was exchanged at the token endpoint. The results are as follows:| Step | code_challenge in the authorization request | code_verifier in the exchange | Exchange Result |
|---|---|---|---|
| 7a | Sent using S256 | Not sent | HTTP 400, error=invalid_request |
| 7b | Sent using S256 | Sent | HTTP 200. Access, ID, and refresh tokens were returned. |
| 7c | Not sent | Not sent | HTTP 200. Access, ID, and refresh tokens were returned. |
Step 7a points in the same direction as the PKCE page statement that the verifier is checked for requests that start PKCE (Section 4.1). In step 7c, with app client A, which has no client secret, an authorization code obtained without initiating PKCE was successfully exchanged without a verifier. This observation points in the same direction as the fact that the list of app client settings has no setting that requires PKCE, and that the documentation states that
code_verifier is only required for requests that initiate PKCE.RFC 10017 §6.3.2.1 mandates that authorization servers
MUST enforce PKCE for public clients. This article does not conclude from this single observation that Cognito never enforces PKCE under any conditions. Only one app client in this configuration was tested. What is recorded as an observation is that, in this configuration, the client's request determined whether PKCE was used.9.4 Refresh Tokens
A and B were used withUSER_PASSWORD_AUTH to obtain refresh tokens.| Verification | Result |
|---|---|
A using GetTokensFromRefreshToken | A new refresh token was returned, different from the original token. |
| A, using the original token within the 10-second grace period | Successful. |
| A, waiting 15 seconds before using the original token | RefreshTokenReuseException, Refresh token reuse detected. |
A using InitiateAuth with REFRESH_TOKEN_AUTH | UnsupportedOperationException (error message below). |
B using GetTokensFromRefreshToken | A new ID and access token were returned. No new refresh token was returned. |
B using InitiateAuth with REFRESH_TOKEN_AUTH | Successful. No new refresh token was returned. |
A using the token endpoint with refresh_token grant | HTTP 200. A new refresh token was returned, different from the original token. |
B using the token endpoint with refresh_token grant | HTTP 200. No refresh token was returned. |
The error message for A's
REFRESH_TOKEN_AUTH is as follows:This API does not support refresh token rotation
Because
ALLOW_REFRESH_TOKEN_AUTH is not allowed on A, this article does not tie this rejection to rotation from the error message alone. The creation error in Section 9.1 is a more direct observation that this authentication flow is not compatible with token rotation.All results aligned with the descriptions in Sections 5.2 and 5.6. A's access token contained the
jti and origin_jti claims. The revocation page states that these claims are added to the tokens of app clients with revocation enabled.9.5 Revocation
The first attempt revoked a refresh token that rotation had already made unusable, so the error after revocation could not be told apart from the rotation reuse error. The test was therefore repeated with app client B, which has no rotation.| Verification Step | Result |
|---|---|
GetUser with the access token (before revocation) | Passed |
RevokeToken with the refresh token of B | Successful |
GetTokensFromRefreshToken with the revoked refresh token | NotAuthorizedException, Refresh Token has been revoked |
REFRESH_TOKEN_AUTH with the revoked refresh token | Same error |
exp value of the simultaneously issued access token | Still in the future |
GetUser with that access token | NotAuthorizedException, Access Token has been revoked |
Although the
exp value of the access token was still in the future, the Cognito API rejected the revoked access token. This observation points in the same direction as the first half of the statement on the revocation page (Section 5.7). The second half, that a JWT library verifying only the signature and expiration judges the token valid, was not tested.9.6 Token Endpoint CORS
Two requests were sent to the token endpoint, both with theOrigin: https://app.example.com header. One was an OPTIONS preflight request, and the other was a POST request with an invalid authorization code.| Request | Response Access-Control- Header |
|---|---|
OPTIONS | Access-Control-Allow-Origin: https://app.example.com, Access-Control-Allow-Credentials: true, Access-Control-Allow-Methods: POST, Access-Control-Allow-Headers: content-type, Access-Control-Max-Age: 1800 |
POST (HTTP 400, error=invalid_grant) | Access-Control-Allow-Origin: https://app.example.com, Access-Control-Allow-Credentials: true |
In both responses, the
Access-Control-Allow-Origin value was the same as the Origin value in the request, and it was not *. The token endpoint page states that this endpoint returns Access-Control-Allow-Origin: * (Section 4.7). This article does not override the documentation with this observation; it shows both. RFC 10017 §6.3.3.4 does not set the concrete CORS policy, so either value fits the form of the requirement to send the necessary CORS headers.9.7 What This Observation Does Not Show
- This observation is based on a test conducted on a single user pool in the us-east-1 Region on November 4, 2026. It does not reflect results from other Regions, different dates, or different feature plans.
- Only the classic hosted UI for domain branding was tested. Managed login was not tested.
- Only app clients without a client secret were tested. Confidential clients were not tested.
- Validation using JWT libraries, focusing solely on signature and expiration, was not tested.
- Whether the newer refresh token is also invalidated when reuse is detected was not tested.
- DPoP, device authorization grant, and CIBA were not tested because no setting for them was found.
- Response times were not recorded, nor were they compared.
10. Frequently Asked Questions About RFC 10017, RFC 10027, and Cognito
This chapter answers common questions, focusing on the concepts outlined in Section 1.1, in the scope of this article. The basis for each answer is indicated in parentheses.10.1 Cognito supports PKCE, so does it comply with RFC 10017?
PKCE support alone addresses only one side of the two requirements outlined in RFC 10017 §6.3.2.1 (that browser-based applications implement PKCE, and that authorization servers both support and enforce PKCE). Cognito's documentation states that it validates the verifier when PKCE is initiated in an authorization request. However, there is no setting to mandate PKCE in theCreateUserPoolClient parameters, nor in CloudFormation properties. The token endpoint page specifies that the code_verifier is required only for requests that initiate PKCE (Section 4.1). In the observation in Chapter 9, an authorization code obtained without starting PKCE could be exchanged for tokens without a verifier (Section 9.3). Furthermore, RFC 10017 includes other requirements beyond PKCE, such as refresh tokens, shared secrets, redirect URIs, implicit grant, and token storage (Chapters 4 through 6).10.2 Was the implicit grant deprecated in OAuth 2.1?
This article does not put it that way. As of November 4, 2026, OAuth 2.1 remains in the Internet-Draft stage (draft-ietf-oauth-v2-1-17). The RFCs that support the rationale for not using implicit grants are RFC 9700 and RFC 10017 §7.2. RFC 10017 §7.2 usesMUST NOT for authorization servers issuing access tokens in the authorization response, and MUST NOT for browser-based clients using the implicit grant. Cognito still lists implicit as a possible value for AllowedOAuthFlows, and positions implicit grants as legacy on the grants page. implicit can be removed per app client (see Section 4.3).10.3 If refresh token rotation is enabled, are sender-constrained tokens no longer needed?
One of the requirements outlined in RFC 10017 §6.3.2.3 states that authorization serversMUST implement either refresh token rotation or sender-constrained refresh tokens. If refresh token rotation is enabled, this requirement's formal condition is satisfied. However, RFC 10017 does not explicitly state that the two methods are equivalent. No mention of DPoP and sender-constrained tokens was found in Cognito's documentation (Section 5.4). In addition to this requirement, §6.3.2.3 has the lifetime requirements and a recommendation (SHOULD) regarding integration with sessions (Sections 5.3 and 5.5).10.4 Can Cognito be used with device authorization grants and CIBA?
The documentation supports only the following. Device authorization grants are not present in the enumeration ofAllowedOAuthFlows and are also not listed as a value for grant_type on the token endpoint page. No mention of CIBA could be found. An AWS Security Blog post from November 2, 2021, describes a configuration that uses AWS Lambda to create custom endpoints for device flows and integrates them with Cognito. In this scenario, implementing the mitigations outlined in RFC 10027 is the responsibility of the party creating the endpoint (see Section 7.4).10.5 What happens to applications using REFRESH_TOKEN_AUTH when rotation is enabled?
According to the refresh token page, REFRESH_TOKEN_AUTH is not available in app clients with rotation enabled. Applications that are refreshing tokens via the API will need to transition to using GetTokensFromRefreshToken. The refresh_token grant of the token endpoint remains available with rotation enabled and returns a new refresh token (see Section 5.6).10.6 Will revoking the token with RevokeToken immediately disable its use?
If a token is revoked using the RevokeToken API, it can no longer be used with Cognito's API. However, the documentation states that even revoked tokens are still recognized as valid by JWT libraries that only verify the signature and expiration date. If the resource server only validates the JWT itself, a revoked access token will still be accepted until its expiration date (see Section 5.7).10.7 Does Amplify's default localStorage implementation conflict with RFC 10017?
RFC 10017 §8.5 attaches no requirement word to persistent storage, including localStorage. What §8.5 states is that no storage method fully prevents token exfiltration when malicious code runs. Requirement words appear only for storing tokens in cookies with JavaScript (marked as NOT RECOMMENDED in §8.1) and for Service Workers (marked as MUST NOT in §8.2), as outlined in Chapter 6.10.8 When the BFF architecture is built with Cognito, what is the app client like?
RFC 10017 §6.1.3.1 usesMUST to require the BFF to use the authorization code grant as a confidential client. In Cognito, this corresponds to an app client that possesses a client secret and has AllowedOAuthFlows configured with the code flow. Once created, the presence or absence of a client secret cannot be changed (see Section 3.3). Cookie attributes, CSRF protection, and restrictions on outbound requests are requirements for the BFF itself (see Section 4.8).11. Summary
- RFC 10017 (BCP 212) and RFC 10027 (BCP 247) were published in August 2026. As of November 4, 2026, neither document has any errata.
- Many of the requirements outlined in RFC 10017 are
MUSTrequirements, addressed to authorization servers. What the Cognito side has are app client settings and per-request parameters. - Requirements with a setting include not issuing tokens in the authorization response, not requiring a shared secret from browser-based applications, registering redirect URIs, enabling refresh token rotation, and setting a maximum lifetime value. The configuration settings are, in order: removing
implicitfrom theAllowedOAuthFlows(for each app client),GenerateSecret(which cannot be changed after creation),CallbackURLs,RefreshTokenRotation, andRefreshTokenValidity. - Available, no setting to require it: PKCE; there is a statement about validating the verifier when PKCE is started in the authorization request, but there is no setting that makes it mandatory in the app client configuration.
- Requirements for which no setting was found include sender-constrained refresh tokens, a statement of exact redirect URI matching, and linking refresh tokens to the session.
- Requirements on the application side: BFF cookies and CSRF protection, browser token storage, CSRF protection using
stateornonce, and risk assessment as described in RFC 10027 §2. - In RFC 10027, the mappings to Cognito settings that could be confirmed are revocation (§6.1.6), the scope and lifetime settings (§6.1.9, §6.1.10), and, as components rather than settings, the combination of the authorization code grant and PKCE (§6.2.3.5, Application side). Device authorization grant is not listed in the
AllowedOAuthFlowsenumeration, and no mention of CIBA was found. - This article does not provide a comprehensive assessment of whether Cognito is fully compliant with the RFCs, nor does it state that it is not. It avoids stating that any feature is unsupported simply because a corresponding description is not found in the documentation.
12. References
IETF- RFC 10017: OAuth 2.0 for Browser-Based Applications
- RFC 10027: Best Current Practice for Security of Cross-Device Flows
- draft-ietf-oauth-browser-based-apps
- draft-ietf-oauth-cross-device-security
- RFC 9700: Best Current Practice for OAuth 2.0 Security
- RFC 6749: The OAuth 2.0 Authorization Framework
- RFC 7636: Proof Key for Code Exchange by OAuth Public Clients
- RFC 8628: OAuth 2.0 Device Authorization Grant
- RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP)
- RFC 7662: OAuth 2.0 Token Introspection
- draft-ietf-oauth-v2-1: The OAuth 2.1 Authorization Framework
Amazon Cognito Developer Guide
- Application-specific settings with app clients
- The redirect and authorization endpoint
- The token endpoint
- OAuth 2.0 grants
- Using PKCE in authorization code grants
- Refresh tokens
- Ending user sessions with token revocation
- Managing user pool token expiration and caching
- User pool feature plans
- User pool managed login
- Authentication flows
Amazon Cognito User Pools API Reference and AWS CloudFormation
- CreateUserPoolClient
- UpdateUserPoolClient
- RefreshTokenRotationType
- GetTokensFromRefreshToken
- RevokeToken
- AWS::Cognito::UserPoolClient
AWS Amplify, AWS Sign-In, and AWS General Reference
- Tokens and credentials (AWS Amplify Gen 2 Documentation)
- Sign in through the AWS Command Line Interface
- Services in Maintenance (AWS General Reference)
AWS What's New and AWS Security Blog
- Amazon Cognito now supports refresh token rotation (April 22, 2025)
- Amazon Cognito now supports targeted sign out through refresh token revocation (June 10, 2021)
- Implement OAuth 2.0 device grant flow by using Amazon Cognito and AWS Lambda (November 2, 2021)
Related Articles on This Site
- Amazon Cognito Federation Complete Implementation Guide - Google, Apple, Microsoft, OIDC, and SAML
- NIST IR 8587 Mapped to AWS Controls - Signing Keys, Audience, Token Lifetimes, Revocation, and What the Settings Leave Open
- OAuth 2.0 and OIDC Flow Visualizer and PKCE Generator - Authorization Code, Client Credentials, and S256 Challenge Builder
- AWS History and Timeline regarding Amazon Cognito - Overview, Functions, Features, Summary of Updates, and Introduction
- JWT and JOSE Standards History and Timeline - JWS, JWE, JWK, JWA, JWT, and How the Algorithm Registry Has Changed
- HTTP Security Headers Complete Reference - CSP, HSTS, COOP, COEP, Permissions Policy
- Passkeys and WebAuthn in Practice - Discoverable Credentials, Synced Versus Device-Bound Keys, and Why Account Recovery Decides the Design
- The AWS Credential Provider Chain Across SDKs and the CLI - What Each Link Supplies, Where the Order Differs by Language, and Why Precedence Is a Separate Mechanism
- Where AI Agent Authorization Standards Stand - RFCs, IETF Working Group Documents, Individual Drafts, and Specifications from Other Bodies
References:
Tech Blog with curated related content
Written by Hidekazu Konishi