Cognito Flutter Docs Gen2
Cognito Flutter Docs Gen2
Amplify Auth is powered by Amazon Cognito. Cognito is a robust user directory service that
handles user registration, authentication, account recovery, and other operations.
To get started with defining your authentication resource, open or create the auth resource file:
amplify/auth/resource.ts
/**
* Define and configure your auth resource
* @see https://docs.amplify.aws/gen2/build-a-backend/auth
*/
export const auth = defineAuth({
loginWith: {
email: true,
},
})
By default, your auth resource is scaffolded using email as the default login mechanism. You can
also configure your auth resource to allow signing in with phone numbers or an external
provider such as Google, Facebook, Amazon, or Sign in with Apple.
Note: At a minimum you will need to pass a loginWith value to set up how your users sign in to
your app. Signing in with email and password is configured by default if you do not provide any
value.
import 'amplify_outputs.dart';
Concepts
Amplify helps you secure your application while providing an easy sign-in experience for your
users. This experience is influenced by your security strategy. This security strategy includes the
authentication method, security credentials, and enabling additional verification when needed.
Authentication is a process to validate who you are (abbreviated as AuthN). The system
that does this validation is referred to as an Identity Provider or IdP. This can be your
own self-hosted IdP or a cloud service. Oftentimes, this IdP is an external provider such
as Apple, Facebook, Google, or Amazon.
Authorization is the process of validating what you can access (abbreviated as AuthZ).
This is sometimes done by looking at tokens with custom logic, predefined rules, or
signed requests with policies.
External provider federation which enables easier access for your users but shares data
with third parties.
You can improve security credentials and verification for these authentication methods by:
Modifying the default password policy to ensure your users create stronger passwords.
Requiring additional contact information from users before they can reset passwords.
Enabling multi-factor authentication (MFA) which adds a layer of security at sign-in but
may also add friction for your users.
Amplify Auth is powered by Amazon Cognito. Amazon Cognito is an identity and access
management service, enabling you to secure your web or mobile applications, and is comprised
of two services:
1. Amazon Cognito User Pools is a full-featured user directory service to handle user
registration, authentication, and account recovery
2. Amazon Cognito Federated Identities or Identity Pools is a service used to authorize your
users to interact with other AWS services
Amplify interfaces with User Pools to store your user information, including federation with
other OpenID providers like Apple, Facebook, Google, or Amazon, and leverages federated
identities to manage user access to AWS resources.
1. Clients pass the tokens to the backend that perform custom logic to allow or deny
actions
2. Clients sign the requests and the backend validates the signature, allowing or denying
actions depending on predefined policy. The predefined rules, known as IAM access
policies, are automatically configured by Amplify.
The first is a common authorization method for HTTP or GraphQL APIs, while the second is
necessary for interfacing with AWS services such as Amazon S3, Amazon Pinpoint, and others.
Amazon Cognito can be customized based on your security strategy for authentication.
However, some initial configuration options cannot be changed after the backend resources are
configured:
User attributes that are used to identify your individual users (such as email and phone)
cannot be renamed or deleted.
Sign-in methods (including username, email, and phone) cannot be added or changed
after the initial configuration. This includes both defining which attributes are used to
sign in and which attributes are required. Required attributes must have a value for all
users once set.
Verification methods (including username and email) are the same as required attributes
and cannot be removed once configured.
The sub attribute is a unique identifier within each user pool that cannot be modified
and can be used to index and search users.
If MFA is set to required with phone number for all users, you will need to include MFA
setup (i.e. mandating phone number) when users sign up.
Email
By default Amplify Auth is scaffolded with email as the default method for user sign-in.
amplify/auth/resource.ts
import { defineAuth } from "@aws-amplify/backend"
This will configure an email attribute that is required for sign-up and cannot be
changed.
User attributes
Amplify Auth stores user profile information in user attributes. When the default method for
user sign-in, Amplify Auth will automatically configure an email or phoneNumber attribute that
is required for sign-in.
To extend a user profile beyond the default email or phoneNumber attribute that is
automatically configured when specified in your auth resource's loginWith property, you can
configure attributes with the userAttributes property:
Warning: After you create your auth resource, you cannot switch an attribute between required
and not required.
amplify/auth/resource.ts
loginWith: {
email: true,
},
userAttributes: {
birthdate: {
mutable: true,
required: false,
},
})
Standard attributes
User attributes are defined as Cognito Standard Attributes. Attributes can be configured to
be required for user sign-up in addition to whether the values are mutable. When configuring
your resource to allow your users to login with email, an email must be specified for user sign-
up and cannot be changed later. However additional attributes can be configured to be optional,
and mutable after sign-up.
amplify/auth/resource.ts
loginWith: {
email: true,
},
userAttributes: {
address: {
mutable: true,
required: true,
},
birthdate: {
mutable: true,
required: false,
},
email: {
mutable: true,
required: true,
},
familyName: {
mutable: true,
required: false,
},
gender: {
mutable: true,
required: false,
},
// Maps to Cognito standard attribute 'given_name'
givenName: {
mutable: true,
required: false,
},
locale: {
mutable: true,
required: false,
},
middleName: {
mutable: true,
required: false,
},
fullname: {
mutable: true,
required: false,
},
nickname: {
mutable: true,
required: false,
},
mutable: true,
required: false,
},
profilePicture: {
mutable: true,
required: false,
},
preferredUsername: {
mutable: true,
required: false,
},
profilePage: {
mutable: true,
required: false,
},
timezone: {
mutable: true,
required: false,
},
lastUpdateTime: {
mutable: true,
required: false,
},
website: {
mutable: true,
required: false,
},
},
});
Custom attributes
In addition to the provided standard attributes, you can configure Custom Attributes. These are
attributes that are typically unique to your use case, such as a tenant ID or a user's display
name. Custom attributes are identified by the custom: prefix:
amplify/auth/resource.ts
loginWith: {
email: true,
},
userAttributes: {
"custom:display_name": {
dataType: "String",
mutable: true,
maxLen: 16,
minLen: 1,
},
"custom:favorite_number": {
dataType: "Number",
mutable: true,
min: 1,
max: 100,
},
"custom:is_beta_user": {
dataType: "Boolean",
mutable: true,
},
"custom:started_free_trial": {
dataType: "DateTime",
mutable: true,
},
},
})
Unlike standard attributes, custom attributes cannot natively be required for sign-up, however
can be codified to require some value by validating user attributes upon sign-up with a pre sign-
up trigger.
Custom attributes can also be configured with specific data types. The following data types are
supported:
String
Number
Boolean
DateTime
Shown in the snippet above, String and Number can be assigned minimum and maximum
constraints. This is useful to defer simple validations to the underlying service, although does
not extend to complex validations such as matching against a regular expression.
Multi-factor authentication
Amplify Auth supports multi-factor authentication (MFA) for user sign-in flows. MFA is an extra
layer of security used to make sure that users trying to gain access to an account are who they
say they are. It requires users to provide additional information to verify their identity. Amplify
Auth supports MFA with time-based one-time passwords (TOTP), text messages (SMS), and
email.
In this guide we will review how you can set up MFA with each of these methods and the
discuss tradeoffs between them to help you choose the right setup for your application. We will
also review how to set up MFA to remember a device and reduce sign-in friction for your users.
Use defineAuth to enable MFA for your app. The example below is setting up MFA with TOTP
but not SMS as you can see that the phone number is not a required attribute.
If you plan to use SMS for MFA, then the phoneNumber attribute must be marked as
required in your userAttributes. Note that if you have loginWith.phone as true this
attribute will automatically be marked as required.
If you plan to use email for MFA, then the email attribute must also be true must be
marked as required in your userAttributes. Note that if you
have loginWith.email as true this attribute will automatically be marked as required.
amplify/auth/resource.ts
loginWith: {
email: true
},
multifactor: {
mode: 'OPTIONAL',
totp: true,
},
userAttributes: {
phoneNumber: {
required: true
});
Note: Email-based MFA is currently not supported with defineAuth. We are working towards
supporting this feature. For more information, visit the feature request in GitHub.
To take advantage of this feature with an Amplify generated backend, the underlying CDK
construct can be extended manually. See overriding Cognito User Pool multi-factor
authentication options for more information.
When MFA is REQUIRED with SMS in your backend auth resource, you will need to pass the
phone number during sign-up API call. If you are using the email or username as the primary
sign-in mechanism, you will need to pass the phone_number attribute as a user attribute.
Similarly, when MFA is REQUIRED with email as your delivery mechanism, you will need to pass
an email address during the sign-up API call. If you are using phoneNumber or username as the
primary sign-in mechanism, you will need to pass the email attribute as a user attribute.
This configuration may change depending on the combination of MFA methods enabled in your
user pool.
When enabling MFA you will have two key decisions to make:
MFA enforcement: As part of this setup you will determine how MFA is enforced. If you
require MFA by setting MFA mode to REQUIRED, all your users will need to complete
MFA to sign in. If you keep it OPTIONAL, your users will have the choice whether to
enable MFA or not for their account.
MFA methods: You will also specify which MFA method you are using: TOTP (Time-based
One-time Password), SMS (text message), email, or any combination thereof. We
recommend that you use TOTP-based MFA as it is more secure and you can reserve SMS
or email for account recovery.
Learn more
If multiple MFA methods are enabled for the user, and none are set as preferred, the signIn API
will return continueSignInWithMFASelection as the next step in the auth flow. During this
scenario, the user should be prompted to select the MFA method they want to use to sign in
and their preference should be passed to confirmSignIn.
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.continueSignInWithMfaSelection:
return _handleMfaSelection(selection);
// ···
// ···
try {
confirmationValue: selection.confirmationValue,
);
return _handleSignInResult(result);
} on AuthException catch (e) {
If you are using the Authenticator component with Amplify, this feature works without any
additional code. The guide below is for writing your own implementation.
Once you have setup SMS as your second layer of authentication with MFA as shown above,
your users will get an authentication code via a text message to complete sign-in after they sign
in with their username and password.
Warning: In order to send SMS authentication codes, you must request an origination
number. Learn more about configuring your auth resource for production workloads.
You will need to pass phone_number as a user attribute to enable SMS MFA for your users
during sign-up. However, if the primary sign-in mechanism for your Cognito resource
is phone_number (without enabling username), then you do not need to pass it as an attribute.
Future<void> signUpWithPhoneVerification(
String username,
String password,
) async {
await Amplify.Auth.signUp(
username: username,
password: password,
options: SignUpOptions(
// ... if required
AuthUserAttributeKey.email: '[email protected]',
AuthUserAttributeKey.phoneNumber: '+18885551234',
},
),
);
By default, you have to verify a user account after they sign up using the confirmSignUp API,
which will send a one-time password to the user's phone number or email, depending on your
Amazon Cognito configuration.
Future<void> confirmSignUpPhoneVerification(
String username,
String otpCode,
) async {
await Amplify.Auth.confirmSignUp(
username: username,
confirmationCode: otpCode,
);
After a user signs in, if they have MFA enabled for their account, a challenge will be returned
that you would need to call the confirmSignIn API where the user provides their confirmation
code sent to their phone number.
If MFA is ON or enabled for the user, you must call confirmSignIn with the OTP sent to their
phone.
await Amplify.Auth.confirmSignIn(
confirmationValue: otpCode,
);
}
After a user has been signed in, call updateMFAPreference to record the MFA type as enabled
for the user and optionally set it as preferred so that subsequent logins default to using this
MFA type.
await cognitoPlugin.updateMfaPreference(
);
If you are using the Authenticator component with Amplify, this feature works without any
additional code. The guide below is for writing your own implementation.
You can use Time-based One-Time Password (TOTP) for multi-factor authentication (MFA) in
your web or mobile applications. The Amplify Auth category includes support for TOTP setup
and verification using authenticator apps, offering an integrated solution and enhanced security
for your users. These apps, such as Google Authenticator, Microsoft Authenticator, have the
TOTP algorithm built-in and work by using a shared secret key and the current time to generate
short-lived, six digit passwords.
After you initiate a user sign in with the signIn API where a user is required to set up TOTP as an
MFA method, the API call will return continueSignInWithTOTPSetup as a challenge and next step
to handle in your app. You will get that challenge if the following conditions are met:
The continueSignInWithTOTPSetup step signifies that the user must set up TOTP before they can
sign in. The step returns an associated value of type TOTPSetupDetails which must be used to
configure an authenticator app like Microsoft Authenticator or Google
Authenticator. TOTPSetupDetails provides a helper method called getSetupURI which generates
a URI that can be used, for example, in a button to open the user's installed authenticator app.
For more advanced use cases, TOTPSetupDetails also contains a sharedSecret which can be used
to either generate a QR code or be manually entered into an authenticator app.
Once the authenticator app is set up, the user can generate a TOTP code and provide it to the
library to complete the sign in process.
try {
username: username,
password: password,
);
return _handleSignInResult(result);
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.continueSignInWithTotpSetup:
// ···
}
The TOTP code can be obtained from the user via a text field or any other means. Once the user
provides the TOTP code, call confirmSignIn with the TOTP code as
the challengeResponse parameter.
try {
confirmationValue: totpCode,
);
return _handleSignInResult(result);
After a user has been signed in, call updateMFAPreference to record the MFA type as enabled
for the user and optionally set it as preferred so that subsequent logins default to using this
MFA type.
await cognitoPlugin.updateMfaPreference(
totp: MfaPreference.preferred,
);
TOTP MFA can be set up after a user has signed in. This can be done when the following
conditions are met:
Invoke the setUpTOTP API to generate a TOTPSetupDetails object which should be used to
configure an Authenticator app like Microsoft Authenticator or Google
Authenticator. TOTPSetupDetails provides a helper method called getSetupURI which generates
a URI that can be used, for example, in a button to open the user's installed Authenticator app.
For more advanced use cases, TOTPSetupDetails also contains a sharedSecret which can be used
to either generate a QR code or be manually entered into an Authenticator app.
that contains the sharedSecret which will be used to either to generate a QR code or can be
manually entered into an Authenticator app.
try {
Once the Authenticator app is set up, the user must generate a TOTP code and provide it to the
library. Pass the code to verifyTOTPSetup to complete the TOTP setup process.
try {
await Amplify.Auth.verifyTotpSetup(totpCode);
}
After TOTP setup is complete, call updateMFAPreference to record the MFA type as enabled for
the user and optionally set it as preferred so that subsequent logins default to using this MFA
type.
await cognitoPlugin.updateMfaPreference(
sms: MfaPreference.enabled,
totp: MfaPreference.preferred,
);
If a user loses access to their TOTP device, they will need to contact an administrator to get help
accessing their account. Based on the Cognito user pool configuration, the administrator can
use the AdminSetUserMFAPreference to either change the MFA preference to a different MFA
method or to disable MFA for the user.
In a scenario where MFA is marked as "Required" in the Cognito User Pool and another MFA
method is not set up, the administrator would need to first initiate
an AdminUpdateUserAttributes call and update the user's phone number attribute. Once this is
complete, the administrator can continue changing the MFA preference to SMS as suggested
above.
If you are using the Authenticator component with Amplify, this feature works without any
additional code. The guide below is for writing your own implementation.
Once you have setup email as your second layer of authentication with MFA as shown above,
your users will get an authentication code via email to complete sign-in after they sign in with
their username and password.
In order to send email authentication codes, the following prerequisites must be met:
Cognito must be configured to send emails using Amazon Simple Email Service (Amazon
SES).
Advanced Security Features (ASF) must be enabled in your user pool.
If account recovery is enabled in Cognito, the delivery method for recovery messages
cannot be set to Email only
Additional pricing applies for ASF. Learn more about Amazon Cognito pricing
You will need to pass email as a user attribute to enable email MFA for your users during sign-
up. However, if the primary sign-in mechanism for your Cognito resource is
already email (without enabling username), then you do not need to pass it as an attribute.
Future<void> signUpWithEmailVerification(
String username,
String password,
) async {
await Amplify.Auth.signUp(
username: username,
password: password,
options: SignUpOptions(
AuthUserAttributeKey.email: '[email protected]',
// ... if required
AuthUserAttributeKey.phoneNumber: '+18885551234',
},
),
);
By default, you have to verify a user account after they sign up using the confirmSignUp API.
Following the initial signUp request, a one-time passcode will be sent to the user's phone
number or email, depending on your Amazon Cognito configuration.
Future<void> confirmSignUpEmailVerification(
String username,
String otpCode,
) async {
await Amplify.Auth.confirmSignUp(
username: username,
confirmationCode: otpCode,
);
After a user signs in, if they have MFA enabled for their account, a challenge will be issued that
requires calling the confirmSignIn API with the user provided confirmation code sent to their
email address.
If MFA is ON or enabled for the user, you must call confirmSignIn with the OTP sent to their
email address.
await Amplify.Auth.confirmSignIn(
confirmationValue: otpCode,
);
After a user has been signed in, call updateMFAPreference to record the MFA type as enabled
for the user and optionally set it as preferred so that subsequent logins default to using this
MFA type.
await cognitoPlugin.updateMfaPreference(
);
}
Depending on your user pool configuration, it's possible that multiple MFA options may be
available to a given user. In order to avoid requiring your users to select an MFA method each
time they sign-in to your application, Amplify provides two utility APIs to manage an individual
user's MFA preferences.
Invoke the following API to get the current MFA preference and enabled MFA types, if any, for
the current user.
Invoke the following API to update the MFA preference for the current user.
Only one MFA method can be marked as preferred at a time. If the user has multiple MFA
methods enabled and tries to mark more than one MFA method as preferred, the API will throw
an error.
await cognitoPlugin.updateMfaPreference(
sms: MfaPreference.enabled,
totp: MfaPreference.preferred,
);
}
Remember a device
Remembering a device is useful in conjunction with MFA because it allows the second factor
requirement to be automatically met when your user signs in on that device and reduces
friction in their sign-in experience. By default, this feature is turned off.
Note: The device tracking and remembering features are not available if any of the following
conditions are met:
the federated OAuth flow with Cognito User Pools or Hosted UI is used, or
amplify/backend.ts
auth,
data
});
cfnUserPool.addPropertyOverride('DeviceConfiguration', {
ChallengeRequiredOnNewDevice: true,
DeviceOnlyRememberedOnUserPrompt: false
});
Understand key terms used for tracking devices
There are differences to keep in mind when working with remembered, forgotten, and tracked
devices.
Tracked: Every time the user signs in with a new device, the client is given the device key
at the end of a successful authentication event. We use this device key to generate a salt
and password verifier which is used to call the ConfirmDevice API. At this point, the
device is considered to be "tracked". Once the device is in a tracked state, you can use
the Amazon Cognito console to see the time it started to be tracked, last authentication
time, and other information about that device.
Remembered: Remembered devices are also tracked. During user authentication, the
device key and secret pair assigned to a remembered device is used to authenticate the
device to verify that it is the same device that the user previously used to sign in.
Forgotten: In the event that you no longer want to remember or track devices, you can
use the forgetDevice() API to remove devices from being both remembered and tracked.
Before you configure external sign-in with Amplify Auth you will need to set up your developer
account with each provider you are using.
Note: Amazon Cognito provides first class support for Facebook Login, Google Sign-In, Login
with Amazon, and Sign in with Apple for seamless setup. However you can configure other
Identity Providers that support SAML or OpenID Connect (OIDC).
Warning: When configuring external sign-in it's important to exercise caution when designating
attributes as "required." Different external identity providers have varied scopes in terms of the
information they respond back to Cognito with. User pool attributes that are initially set up as
"required" cannot be changed later, and may require you to migrate the users or create a new
user pool.
5. For platform, choose Website and select No, I'm not building a game.
6. Give your Facebook app a name and choose Create
app.
8. Note the App ID and the App Secret. You will use them in the next section in the CLI flow.
Your developer accounts with the external providers are now set up and you can return to the
Amplify specific configuration.
Configure external sign-in backend
The following is an example of how you would set up access to all of the external providers
supported by Amplify Auth. Please note you will need to configure
your callbackUrls and logoutUrls URLs for your application, which will inform your backend
resources how to behave when initiating sign in and sign out operations in your app.
Secrets must be created manually with ampx sandbox secret for use with cloud sandbox, or via
the Amplify Console for branch environments.
amplify/auth/resource.ts
loginWith: {
email: true,
externalProviders: {
google: {
clientId: secret('GOOGLE_CLIENT_ID'),
clientSecret: secret('GOOGLE_CLIENT_SECRET')
},
signInWithApple: {
clientId: secret('SIWA_CLIENT_ID'),
keyId: secret('SIWA_KEY_ID'),
privateKey: secret('SIWA_PRIVATE_KEY'),
teamId: secret('SIWA_TEAM_ID')
},
loginWithAmazon: {
clientId: secret('LOGINWITHAMAZON_CLIENT_ID'),
clientSecret: secret('LOGINWITHAMAZON_CLIENT_SECRET')
},
facebook: {
clientId: secret('FACEBOOK_CLIENT_ID'),
clientSecret: secret('FACEBOOK_CLIENT_SECRET')
},
callbackUrls: ["myapp://callback/"],
logoutUrls: ["myapp://signout/"],
});
You need to now inform your external provider of the newly configured authentication resource
and its OAuth redirect URI:
2. Choose My Apps from the top navigation bar, and on the Apps page, choose your app
you created before.
3. On the left navigation bar, choose Products. Add Facebook Login if it isn't already added.
4. If already added, choose Settings under
the Configure dropdown.
5. Under Valid OAuth Redirect URIs type your user pool domain with
the /oauth2/idpresponse endpoint.
https://<your-user-pool-domain>/oauth2/idpresponse
Learn more about using social identity providers with user pool
You can determine the pieces of data you want to retrieve from each external provider when
setting them up in the amplify/auth/resource.ts file using scopes.
amplify/auth/resource.ts
loginWith: {
email: true,
externalProviders: {
loginWithAmazon: {
clientId: secret('LOGINWITHAMAZON_CLIENT_ID'),
clientSecret: secret('LOGINWITHAMAZON_CLIENT_SECRET'),
scopes: ['email']
},
callbackUrls: ["myapp://callback/"],
logoutUrls: ["myapp://signout/"],
});
Attribute mapping
Identity provider (IdP) services store user attributes in different formats. When using external
IdPs with Amazon Cognito user pools, attribute mapping allows you to standardize these varying
formats into a consistent schema.
Learn more about mapping IdP attributes to user pool profiles and tokens.
Note: When a federated user signs in to your application, a mapping must be present for each
attribute that your user pool requires. Additionally, you must also ensure that the target of each
attribute mapping is mutable. Amazon Cognito will attempt to update each mapped attribute
when a user signs in regardless of whether the latest value already matches the existing
information. If these criteria are not met, Amazon Cognito will return an error and the sign in
attempt will fail.
amplify/auth/resource.ts
loginWith: {
email: true,
externalProviders: {
loginWithAmazon: {
clientId: secret('LOGINWITHAMAZON_CLIENT_ID'),
clientSecret: secret('LOGINWITHAMAZON_CLIENT_SECRET'),
attributeMapping: {
email: 'email'
},
callbackUrls: ["myapp://callback/"],
logoutUrls: ["myapp://signout/"],
});
To setup a OIDC provider, you can configure them in your amplify/auth/resource.ts file. For
example, if you would like to setup a Microsoft EntraID provider, you can do so as follows:
amplify/auth/resource.ts
email: true,
externalProviders: {
oidc: [
name: 'MicrosoftEntraID',
clientId: secret('MICROSOFT_ENTRA_ID_CLIENT_ID'),
clientSecret: secret('MICROSOFT_ENTRA_ID_CLIENT_SECRET'),
issuerUrl: '<your-issuer-url>',
},
],
callbackUrls: ["myapp://callback/"],
logoutUrls: ["myapp://signout/"],
},
},
});
To setup a SAML provider, you can configure them in your amplify/auth/resource.ts file. For
example, if you would like to setup a Microsoft EntraID provider, you can do so as follows:
amplify/auth/resource.ts
loginWith: {
email: true,
externalProviders: {
saml: {
name: 'MicrosoftEntraIDSAML',
metadata: {
},
},
callbackUrls: ["myapp://callback/"],
logoutUrls: ["myapp://signout/"],
},
},
});
Amplify Auth interacts with its underlying Amazon Cognito user pool as an OpenID Connect
(OIDC) provider. When users successfully authenticate you receive OIDC-compliant JSON web
tokens (JWT). These tokens are used to identity your user, and access resources.
Access tokens are used to verify the bearer of the token (i.e. the Cognito user) is authorized to
perform an action against a resource. Below is an example payload of an access token vended
by Cognito:
"sub": "54288468-e051-706d-a73f-03892273d7e9",
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_yoKn9s4Tq",
"client_id": "1sg675g08g6g0e9f64grv9n5sk",
"origin_jti": "0eadb994-a6e0-419e-b309-a7a0d522d72f",
"event_id": "b180897a-181c-4f73-94bb-a2946e8b4ef1",
"token_use": "access",
"scope": "aws.cognito.signin.user.admin",
"auth_time": 1714241873,
"exp": 1714245473,
"iat": 1714241873,
"jti": "57f10a4d-a1f2-453b-8672-d1cfa8187047",
"username": "54288468-e051-706d-a73f-03892273d7e9"
ID tokens are intended to be used within your frontend application only. This token contains
personally identifiable information (PII) and should not be used to authorize access against a
resource. Below is an example of an ID token with the default Amplify Auth configuration of
email and password auth.
"sub": "54288468-e051-706d-a73f-03892273d7e9",
"email_verified": true,
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_yoKn9s4Tq",
"cognito:username": "54288468-e051-706d-a73f-03892273d7e9",
"origin_jti": "0eadb994-a6e0-419e-b309-a7a0d522d72f",
"aud": "1sg675g08g6g0e9f64grv9n5sk",
"event_id": "b180897a-181c-4f73-94bb-a2946e8b4ef1",
"token_use": "id",
"auth_time": 1714241873,
"exp": 1714245473,
"iat": 1714241873,
"jti": "bb69af10-3ce0-47c2-8d8d-5bdc8630ab58",
"email": "[email protected]"
When additional user attributes are specified for Amplify Auth, their values will be found in the
ID token. For example, if a nickname attribute is requested it will be available on the ID token
with the nickname claim:
{
"sub": "54288468-e051-706d-a73f-03892273d7e9",
"email_verified": true,
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_yoKn9s4Tq",
"cognito:username": "54288468-e051-706d-a73f-03892273d7e9",
"origin_jti": "0eadb994-a6e0-419e-b309-a7a0d522d72f",
"aud": "1sg675g08g6g0e9f64grv9n5sk",
"event_id": "b180897a-181c-4f73-94bb-a2946e8b4ef1",
"token_use": "id",
"auth_time": 1714241873,
+ "nickname": "hello",
"exp": 1714245473,
"iat": 1714241873,
"jti": "bb69af10-3ce0-47c2-8d8d-5bdc8630ab58",
"email": "[email protected]"
Conversely, user pool group claims are found in both the access token and ID token on
the cognito:groups claim:
"sub": "54288468-e051-706d-a73f-03892273d7e9",
"email_verified": true,
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_yoKn9s4Tq",
"cognito:username": "54288468-e051-706d-a73f-03892273d7e9",
"cognito:groups": ["ADMINS"],
"origin_jti": "0eadb994-a6e0-419e-b309-a7a0d522d72f",
"aud": "1sg675g08g6g0e9f64grv9n5sk",
"event_id": "b180897a-181c-4f73-94bb-a2946e8b4ef1",
"token_use": "id",
"auth_time": 1714241873,
"nickname": "hello",
"exp": 1714245473,
"iat": 1714241873,
"jti": "bb69af10-3ce0-47c2-8d8d-5bdc8630ab58",
"email": "[email protected]"
Visit the AWS documentation for using tokens with Cognito user pools to learn more about
tokens, how they're used with Cognito, and their intended usage.
Amplify Flutter securely manages credentials and user identity information. You do not need to
store, refresh, or delete credentials yourself. Amplify Flutter stores auth data on the device
using platform capabilities such as Keychain Services on iOS and macOS
and EncryptedSharedPreferences on Android.
Amplify will refresh the access token and ID token as long as the refresh token is valid. Once the
refresh token expires, the user will need to reauthenticate to obtain a new one.
Some platform specific option can be customized with the out of the box options. In the
example below, credentials will be stored in-memory on Web instead of the default behavior of
using browser storage.
await Amplify.addPlugin(
AmplifyAuthCognito(
secureStorageFactory: AmplifySecureStorage.factoryFrom(
webOptions: WebSecureStorageOptions(
persistenceOption: WebPersistenceOption.inMemory,
),
),
),
);
If you would like further customization, you can provide your own factory for
creating SecureStorageInterface instances to AmplifyAuthCognito. The example below shows
the use of a custom implementation that stores data in-memory on all platforms.
await Amplify.addPlugin(
AmplifyAuthCognito(secureStorageFactory: InMemoryStorage.new),
);
InMemoryStorage(this.scope);
///
@override
_data['${scope.name}.$key'] = value;
@override
return _data['${scope.name}.$key'];
}
@override
_data.remove('${scope.name}.$key');
Token Revocation
Token revocation is enabled automatically in Amplify Auth. To revoke tokens you can
invoke await Amplify.Auth.signOut(options: const signOutOptions(globalSignOut: true)) to
globally sign out your user from all of their devices.
The quickest way to get started with Amplify Auth in your frontend application is with
the Authenticator component, which provides a customizable UI and complete authentication
flows.
The Authenticator component is automatically configured based on the outputs generated from
your backend. To learn more about the Authenticator and how to customize its appearance,
visit the Amplify UI documentation.
Sign-up
Amplify provides a client library that enables you to interact with backend resources such as
Amplify Auth.
The quickest way to get started with Amplify Auth in your frontend application is with
the Authenticator component, which provides a customizable UI and complete authentication
flows.
To get started, you can use the signUp() API to create a new user in your backend:
/// Signs a user up with a username, password, and email. The required
String? phoneNumber,
}) async {
try {
final userAttributes = {
AuthUserAttributeKey.email: email,
};
username: username,
password: password,
options: SignUpOptions(
userAttributes: userAttributes,
),
);
await _handleSignUpResult(result);
switch (result.nextStep.signUpStep) {
case AuthSignUpStep.confirmSignUp:
_handleCodeDelivery(codeDeliveryDetails);
break;
case AuthSignUpStep.done:
safePrint('Sign up is complete');
break;
safePrint(
);
The signUp API response will include a nextStep property, which can be used to determine if
further action is required. It may return the following next steps:
confirmSignU The sign up needs to be confirmed by collecting a code from the user and
p calling confirmSignUp.
Confirm sign-up
By default, each user that signs up remains in the unconfirmed status until they verify with a
confirmation code that was sent to their email or phone number. The following are the default
verification methods used when either phone or email are used as loginWith options.
Login option User account verification channel
email Email
You can confirm the sign-up after receiving a confirmation code from the user:
Future<void> confirmUser({
}) async {
try {
username: username,
confirmationCode: confirmationCode,
);
await _handleSignUpResult(result);
Sign-in
Amplify provides a client library that enables you to interact with backend resources such as
Amplify Auth.
The quickest way to get started with Amplify Auth in your frontend application is with
the Authenticator component, which provides a customizable UI and complete authentication
flows.
try {
username: username,
password: password,
);
await _handleSignInResult(result);
Depending on your configuration and how the user signed up, one or more confirmations will
be necessary. Use the SignInResult returned from Amplify.Auth.signIn to check the next step for
signing in. When the value is done, the user has successfully signed in.
switch (result.nextStep.signInStep) {
case AuthSignInStep.confirmSignInWithSmsMfaCode:
_handleCodeDelivery(codeDeliveryDetails);
break;
case AuthSignInStep.confirmSignInWithNewPassword:
break;
case AuthSignInStep.confirmSignInWithCustomChallenge:
safePrint(prompt);
break;
case AuthSignInStep.resetPassword:
username: username,
);
await _handleResetPasswordResult(resetResult);
break;
case AuthSignInStep.confirmSignUp:
username: username,
);
_handleCodeDelivery(resendResult.codeDeliveryDetails);
break;
case AuthSignInStep.done:
safePrint('Sign in is complete');
break;
safePrint(
'A confirmation code has been sent to ${codeDeliveryDetails.destination}. '
);
The signIn API response will include a nextStep property, which can be used to determine if
further action is required. It may return the following next steps:
For more information on handling the MFA steps that may be returned, see multi-factor
authentication.
When you have Email or SMS MFA enabled, Cognito will send messages to your users on your
behalf. Email and SMS messages require that your users have email address and phone number
attributes respectively. It is recommended to set these attributes as required in your user pool if
you wish to use either Email MFA or SMS MFA. When these attributes are required, a user must
provide these details before they can complete the sign up process.
If you have set MFA to be required and you have activated more than one authentication factor,
Cognito will prompt new users to select an MFA factor they want to use. Users must have a
phone number to select SMS and an email address to select email MFA.
If a user doesn't have the necessary attributes defined for any available message based MFA,
Cognito will prompt them to set up TOTP.
Visit the multi-factor authentication documentation to learn more about enabling MFA on your
backend auth resource.
Confirm sign-in
Following sign in, you will receive a nextStep in the sign-in result of one of the following types.
Collect the user response and then pass to the confirmSignIn API to complete the sign in flow.
confirmSignInWithTotpM The sign-in must be confirmed with a TOTP code from the
faCode user. Complete the process with confirmSignIn.
confirmSignInWithSmsMf The sign-in must be confirmed with a SMS code from the user.
aCode Complete the process with confirmSignIn.
confirmSignInWithOtpCo The sign-in must be confirmed with a code from the user (sent
de via SMS or Email). Complete the process with confirmSignIn.
continueSignInWithMfaS The user must select their mode of MFA verification before
election signing in. Complete the process with confirmSignIn.
Note: you must call confirmSignIn in the same app session as you call signIn. If you close the
app, you will need to call signIn again. As a result, for testing purposes, you'll at least need an
input field where you can enter the code sent via SMS and pass it to confirmSignIn.
How It Works
Sign-in with web UI will display the sign-in UI inside a webview. After the sign-in process is
complete, the sign-in UI will redirect back to your app.
Platform Setup
Web
To use Hosted UI in your Flutter web application locally, you must run the app with the --web-
port=3000 argument (with the value being whichever port you assigned to localhost host when
configuring your redirect URIs).
Android
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
<application>
...
<activity
android:name=".MainActivity" android:exported="true">
<intent-filter>
</intent-filter>
</activity>
...
</application>
macOS
Open XCode and enable the App Sandbox capability and then select "Incoming Connections
(Server)" under "Network".
iOS, Windows and Linux
You're now ready to launch sign in with your external provider's web UI.
try {
provider: AuthProvider.google,
);
Password
ign-out
Amplify provides a client library that enables you to interact with backend resources such as
Amplify Auth.
The quickest way to get started with Amplify Auth in your frontend application is with
the Authenticator component, which provides a customizable UI and complete authentication
flows.
if (result is CognitoCompleteSignOut) {
You can also sign out users from all devices by performing a global sign-out. This will also
invalidate all refresh tokens issued to a user. The user's current access and ID tokens will remain
valid on other devices until the refresh token expires (access and ID tokens expire one hour after
they are issued).
);
if (result is CognitoCompleteSignOut) {
// Retry the global sign out using the access token, if desired
// ...
Amplify Auth provides access to current user sessions and tokens to help you retrieve your
user's information to determine if they are signed in with a valid session and control their
access to your app.
An intentional decision with Amplify Auth was to avoid any public methods exposing credentials
or manipulating them.
With Auth, you simply sign in and it handles everything else needed to keep the credentials up
to date and vend them to the other categories.
However, if you need to access them in relation to working with an API outside Amplify or want
access to AWS specific identifying information (e.g. IdentityId), you can access these
implementation details by calling fetchAuthSession on the Cognito Auth Plugin. This will return
a CognitoAuthSession, which has additional attributes compared to AuthSession, which is
typically returned by fetchAuthSession. See the example below:
try {
Sometimes it can be helpful to retrieve the instance of the underlying plugin which has more
specific typing. In case of Cognito, calling fetchAuthSession on the Cognito plugin returns AWS-
specific values such as the identity ID, AWS credentials, and Cognito User Pool tokens.
try {
}
}
PREVIOUS
User attributes such as email address, phone number help you identify individual users.
Defining the user attributes you include for your user profiles makes user data easy to manage
at scale. This information will help you personalize user journeys, tailor content, provide
intuitive account control, and more. You can capture information upfront during sign-up or
enable customers to update their profile after sign-up. In this section we take a closer look at
working with user attributes, how to set them up and manage them.
Custom attributes can be passed in with the userAttributes option of the signUp API:
Future<void> _signUp({
}) async {
final userAttributes = {
AuthUserAttributeKey.email: email,
};
await Amplify.Auth.signUp(
username: username,
password: password,
options: SignUpOptions(
userAttributes: userAttributes,
),
);
You can retrieve user attributes for your users to read in their profile using
the fetchUserAttributes API. This helps you personalize their frontend experience as well as
control what they will see.
try {
You can use the updateUserAttribute API to create or update existing user attributes.
Future<void> updateUserEmail({
}) async {
try {
userAttributeKey: AuthUserAttributeKey.email,
value: newEmail,
);
_handleUpdateUserAttributeResult(result);
User attribute updates may require additional verification before they're complete. Check
the UpdateUserAttributeResult returned from Amplify.Auth.updateUserAttribute to see which
next step, if any, is required. When the update is complete, the next step will be done.
void _handleUpdateUserAttributeResult(
UpdateUserAttributeResult result,
){
switch (result.nextStep.updateAttributeStep) {
case AuthUpdateAttributeStep.confirmAttributeWithCode:
_handleCodeDelivery(codeDeliveryDetails);
break;
case AuthUpdateAttributeStep.done:
break;
safePrint(
const attributes = [
AuthUserAttribute(
userAttributeKey: AuthUserAttributeKey.email,
value: '[email protected]',
),
AuthUserAttribute(
userAttributeKey: AuthUserAttributeKey.familyName,
value: 'MyFamilyName',
),
];
try {
attributes: attributes,
);
result.forEach((key, value) {
switch (value.nextStep.updateAttributeStep) {
case AuthUpdateAttributeStep.confirmAttributeWithCode:
break;
case AuthUpdateAttributeStep.done:
});
Some attributes require confirmation for the attribute update to complete. If the attribute
needs to be confirmed, part of the result of
the updateUserAttribute or updateUserAttributes APIs will
be CONFIRM_ATTRIBUTE_WITH_CODE. A confirmation code will be sent to the delivery medium
mentioned in the delivery details. When the user gets the confirmation code, you can present a
UI to the user to enter the code and invoke the confirmUserAttribute API with their input:
try {
await Amplify.Auth.confirmUserAttribute(
userAttributeKey: AuthUserAttributeKey.email,
confirmationCode: '390739',
);
userAttributeKey: AuthUserAttributeKey.email,
);
_handleCodeDelivery(result.codeDeliveryDetails);
Amplify Auth emits events during authentication flows, which enables you to react to user flows
in real time and trigger custom business logic. For example, you may want to capture data,
synchronize your app's state, and personalize the user's experience. You can listen to and
respond to events across the Auth lifecycle such as sign-in and sign-out.
AWS Cognito Auth Plugin sends important events through Amplify Hub. You can listen to these
events like the following:
switch (event.type) {
case AuthHubEventType.signedIn:
break;
case AuthHubEventType.signedOut:
break;
case AuthHubEventType.sessionExpired:
break;
case AuthHubEventType.userDeleted:
break;
});
Empowering users to delete their account can improve trust and transparency. You can
programmatically enable self-service account deletion with Amplify Auth.
If you have not yet created an Amplify Gen 2 app, visit the quickstart.
You can quickly set up account deletion for your users with the Amplify Libraries. Invoking
the deleteUser API to delete a user from the Auth category will also sign out your user.
If your application uses a Cognito User Pool, which is the default configuration, this action will
only delete the user from the Cognito User Pool. It will have no effect if you are federating with
a Cognito Identity Pool alone.
Before invoking the deleteUser API, you may need to first delete associated user data that is not
stored in Cognito. For example, if you are using Amplify Data to persist user data, you could
follow these instructions to delete associated user data. This allows you to address any
guidelines (such as GDPR) that require your app to delete data associated with a user who
deletes their account.
try {
await Amplify.Auth.deleteUser();
}
We recommend you update your UI to let your users know that their account is deleted and test
the functionality with a test user. Note that your user will be signed out of your application
when they delete their account.
PREVIOUS
NEXT
Multi-step sign-in
On this page
Multi-step sign-in
After a user has finished signup, they can proceed to sign in. Amplify Auth signin flows can be
multi step processes. The required steps are determined by the configuration you provided
when you define your auth resources like described on Manage MFA Settings page.
Depending on the configuration, you may need to call various APIs to finish authenticating a
user's signin attempt. To identify the next step in a signin flow, inspect the nextStep parameter
in the signin result.
When Amplify adds a new enumeration value (e.g., a new enum class entry or sealed class
subtype in Kotlin, or a new enum value in Swift/Dart/Kotlin), it will publish a new minor version
of the Amplify Library. Plugins that switch over enumeration values should include default
handlers (an else branch in Kotlin or a default statement in Swift/Dart/Kotlin) to ensure that
they are not impacted by new enumeration values.
The Amplify.Auth.signIn API returns a SignInResult object which indicates whether the sign-in
flow is complete or whether additional steps are required before the user is signed in.
If the sign-in step is not done, one or more additional steps are required. These are
explained in detail below.
The signInStep property is an enum of type AuthSignInStep. Depending on its value, your code
should take one of the actions mentioned on this page.
Future<SignInResult> signInWithCognito(
String username,
String password,
) async {
username: username,
password: password,
);
return _handleSignInResult(result);
switch (result.nextStep.signInStep) {
case AuthSignInStep.continueSignInWithMfaSelection:
case AuthSignInStep.continueSignInWithMfaSetupSelection:
case AuthSignInStep.continueSignInWithEmailMfaSetup:
case AuthSignInStep.confirmSignInWithOtpCode:
case AuthSignInStep.continueSignInWithTotpSetup:
// Handle TOTP setup case
case AuthSignInStep.confirmSignInWithTotpMfaCode:
case AuthSignInStep.confirmSignInWithSmsMfaCode:
case AuthSignInStep.confirmSignInWithNewPassword:
case AuthSignInStep.confirmSignInWithCustomChallenge:
case AuthSignInStep.resetPassword:
case AuthSignInStep.confirmSignUp:
case AuthSignInStep.done:
safePrint('Sign in is complete');
If the next step is confirmSignInWithSmsMfaCode, Amplify Auth has sent the user a random
code over SMS and is waiting for the user to verify that code. To handle this step, your app's UI
must prompt the user to enter the code. After the user enters the code, pass the value to
the confirmSignIn API.
switch (result.nextStep.signInStep) {
case AuthSignInStep.confirmSignInWithSmsMfaCode:
final codeDeliveryDetails = result.nextStep.codeDeliveryDetails!;
_handleCodeDelivery(codeDeliveryDetails);
// ...
safePrint(
);
try {
confirmationValue: mfaCode,
);
return _handleSignInResult(result);
If the next step is confirmSignInWithTOTPCode, you should prompt the user to enter the TOTP
code from their associated authenticator app during set up. The code is a six-digit number that
changes every 30 seconds. The user must enter the code before the 30-second window expires.
After the user enters the code, your implementation must pass the value to Amplify
Auth confirmSignIn API.
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.confirmSignInWithTotpMfaCode:
// ···
try {
confirmationValue: totpCode,
);
return _handleSignInResult(result);
If the next step is confirmSignInWithOtpCode, Amplify Auth has sent the user a random code to
their email address and is waiting for the user to verify that code. To handle this step, your app's
UI must prompt the user to enter the code. After the user enters the code, pass the value to
the confirmSignIn API.
switch (result.nextStep.signInStep) {
case AuthSignInStep.confirmSignInWithOtpCode:
_handleCodeDelivery(codeDeliveryDetails);
// ...
safePrint(
);
try {
confirmationValue: mfaCode,
);
return _handleSignInResult(result);
If the next step is continueSignInWithMFASelection, the user must select the MFA method to
use. Amplify Auth currently supports SMS, TOTP, and email as MFA methods. After the user
selects an MFA method, your implementation must pass the selected MFA method to Amplify
Auth using confirmSignIn API.
The MFA types which are currently supported by Amplify Auth are:
MfaType.sms
MfaType.totp
MfaType.email
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.continueSignInWithMfaSelection:
return _handleMfaSelection(selection);
// ···
// ···
}
Future<void> _handleMfaSelection(MfaType selection) async {
try {
confirmationValue: selection.confirmationValue,
);
return _handleSignInResult(result);
If the next step is continueSignInWithEmailMfaSetup, then the user must provide an email
address to complete the sign in process. Once this value has been collected from the user, call
the confirmSignIn API to continue.
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.continueSignInWithEmailMfaSetup:
// Prompt user to enter an email address they would like to use for MFA
// ···
try {
final result = await Amplify.Auth.confirmSignIn(
confirmationValue: emailAddress,
);
return _handleSignInResult(result);
If the next step is continueSignInWithTOTPSetup, then the user must provide a TOTP code to
complete the sign in process. The step returns an associated value of
type TOTPSetupDetails which would be used for generating TOTP. TOTPSetupDetails provides a
helper method called getSetupURI that can be used to generate a URI, which can be used by
native password managers for TOTP association. For example. if the URI is used on Apple
platforms, it will trigger the platform's native password manager to associate TOTP with the
account. For more advanced use cases, TOTPSetupDetails also contains the sharedSecret that
will be used to either generate a QR code or can be manually entered into an authenticator app.
Once the authenticator app is set up, the user can generate a TOTP code and provide it to the
library to complete the sign in process.
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.continueSignInWithTotpSetup:
// ···
}
// Then, pass the TOTP code to `confirmSignIn`
try {
confirmationValue: totpCode,
);
return _handleSignInResult(result);
If the next step is continueSignInWithMfaSetupSelection, then the user must indicate which of
the available MFA methods they would like to setup. After the user selects an MFA method to
setup, your implementation must pass the selected MFA method to the confirmSignIn API.
The MFA types which are currently supported by Amplify Auth are:
MfaType.sms
MfaType.totp
MfaType.email
switch (result.nextStep.signInStep) {
// ···
case AuthSignInStep.continueSignInWithMfaSetupSelection:
// ···
// ···
try {
confirmationValue: selection.confirmationValue,
);
return _handleSignInResult(result);
For example, your custom challenge Lambda may pass a prompt to the frontend which requires
the user to enter a secret code.
switch (result.nextStep.signInStep) {
// ...
case AuthSignInStep.confirmSignInWithCustomChallenge:
// ...
To complete this step, you should prompt the user for the custom challenge answer, and pass
the answer to the confirmSignIn API.
try {
confirmationValue: answer,
);
return _handleSignInResult(result);
If failAuthentication=true is returned by the Lambda, Cognito will invalidate the session of the
request. This is represented by a NotAuthorizedException and requires restarting the sign-in
flow by calling Amplify.Auth.signIn again.
If the next step is confirmSignInWithNewPassword, Amplify Auth requires the user choose a
new password they proceeding with the sign in.
Prompt the user for a new password and pass it to the confirmSignIn API.
switch (result.nextStep.signInStep) {
// ...
case AuthSignInStep.confirmSignInWithNewPassword:
// ...
try {
confirmationValue: newPassword,
);
return _handleSignInResult(result);
Reset password
If the next step is resetPassword, Amplify Auth requires that the user reset their password
before proceeding. Use the resetPassword API to guide the user through resetting their
password, then call Amplify.Auth.signIn when that's complete to restart the sign-in flow.
switch (result.nextStep.signInStep) {
// ...
case AuthSignInStep.resetPassword:
username: username,
);
await _handleResetPasswordResult(resetResult);
// ...
switch (result.nextStep.updateStep) {
case AuthResetPasswordStep.confirmResetPasswordWithCode:
_handleCodeDelivery(codeDeliveryDetails);
case AuthResetPasswordStep.done:
safePrint(
);
Confirm Signup
If the next step is resetPassword, Amplify Auth requires that the user confirm their email or
phone number before proceeding. Use the resendSignUpCode API to send a new sign up code
to the registered email or phone number, followed by confirmSignUp to complete the sign up.
switch (result.nextStep.signInStep) {
// ...
case AuthSignInStep.confirmSignUp:
username: username,
);
_handleCodeDelivery(resendResult.codeDeliveryDetails);
// ...
safePrint(
);
Future<void> confirmSignUp({
required String username,
}) async {
try {
await Amplify.Auth.confirmSignUp(
username: username,
confirmationCode: confirmationCode,
);
Once the sign up is confirmed, call Amplify.Auth.signIn again to restart the sign-in flow.
Done
The sign-in flow is complete when the next step is done, which means the user is successfully
authenticated. As a convenience, the SignInResult also provides the isSignedIn property, which
will be true if the next step is done.
switch (result.nextStep.signInStep) {
// ...
case AuthSignInStep.done:
safePrint('Sign in is complete');
PREVIOUS
Delete user account
To get started, create an "ADMINS" group that will be used to authorize the mutation:
amplify/auth/resource.ts
loginWith: {
email: true,
},
groups: ["ADMINS"]
})
amplify/data/add-user-to-group/resource.ts
name: "add-user-to-group",
})
Then, in your auth resources, grant access for the function to perform
the addUserToGroup action. Learn more about granting access to auth resources.
amplify/auth/resource.ts
import { defineAuth } from "@aws-amplify/backend"
loginWith: {
email: true,
},
groups: ["ADMINS"],
allow.resource(addUserToGroup).to(["addUserToGroup"])
],
})
You're now ready to define the custom mutation. Here you will use the newly-
created addUserToGroup function resource to handle the addUserToGroup mutation. This
mutation can only be called by a user in the "ADMINS" group.
amplify/data/resource.ts
addUserToGroup: a
.mutation()
.arguments({
userId: a.string().required(),
groupName: a.string().required(),
})
.authorization((allow) => [allow.group("ADMINS")])
.handler(a.handler.function(addUserToGroup))
.returns(a.json())
})
schema,
authorizationModes: {
defaultAuthorizationMode: "iam",
},
})
Lastly, create the function's handler using the exported client schema to type the handler
function, and the generated env to specify the user pool ID you'd like to interact with:
amplify/data/add-user-to-group/handler.ts
import {
AdminAddUserToGroupCommand,
CognitoIdentityProviderClient,
} from "@aws-sdk/client-cognito-identity-provider"
Username: userId,
GroupName: groupName,
UserPoolId: env.AMPLIFY_AUTH_USERPOOL_ID,
})
return response
Manage passwords
Amplify Auth provides a secure way for your users to change their password or recover a
forgotten password.
By default, your users can retrieve access to their accounts if they forgot their password by
using either their phone or email. The following are the default account recovery methods used
when either phone or email are used as login options.
email Email
Reset Password
To reset a user's password, use the resetPassword API which will send a reset code to the
destination (e.g. email or SMS) based on the user's settings.
try {
username: username,
);
await _handleResetPasswordResult(result);
switch (result.nextStep.updateStep) {
case AuthResetPasswordStep.confirmResetPasswordWithCode:
_handleCodeDelivery(codeDeliveryDetails);
break;
case AuthResetPasswordStep.done:
break;
To complete the password reset process, invoke the confirmResetPassword API with the code
your user received and the new password they want to set.
Future<void> confirmResetPassword({
}) async {
try {
username: username,
newPassword: newPassword,
confirmationCode: confirmationCode,
);
Update password
You can update a signed in user's password using the updatePassword API.
Future<void> updatePassword({
}) async {
try {
await Amplify.Auth.updatePassword(
oldPassword: oldPassword,
newPassword: newPassword,
);
You can always change the channel used by your authentication resources by overriding the
following setting.
amplify/auth/resource.ts
loginWith: {
email: true
},
accountRecovery: 'EMAIL_ONLY'
});
MinLength: 8 characters
requireLowercase: true
requireUppercase: true
requireNumbers: true
requireSymbols: true
tempPasswordValidity: 3 days
You can customize the password format acceptable by your auth resource by modifying the
underlying cfnUserPool resource:
amplify/backend.ts
auth,
});
cfnUserPool.policies = {
passwordPolicy: {
minimumLength: 32,
requireLowercase: true,
requireNumbers: true,
requireSymbols: true,
requireUppercase: true,
temporaryPasswordValidityDays: 20,
},
};
PREVIOUS
The Auth category can be configured to perform a custom authentication flow defined by you.
The following guide shows how to setup a simple passwordless authentication flow.
Prerequisites
Amplify requires a minimum target platform for iOS (13.0), Android (API level 24), and macOS
(10.15). Refer to Flutter's supported deployment platforms when targeting Web, Windows, or
Linux. Additional setup is required for some target platforms. Please see the platform setup for
more details on platform specific setup.
Configure Auth
Register a user
The flow as mentioned above requires a username and a valid email id as parameters to register
a user. Invoke the following api to initiate a sign up flow.
Because authentication flows in Cognito can be switched via your configuration, it is still
required that users register with a password.
try {
AuthUserAttributeKey.email: '[email protected]',
AuthUserAttributeKey.phoneNumber: '+15559101234',
};
username: 'myusername',
password: 'mysupersecurepassword',
);
}
The next step in the sign up flow is to confirm the user. A confirmation code will be sent to the
email id provided during sign up. Enter the confirmation code received via email in
the confirmSignUp call.
Future<void> confirmUser({
}) async {
try {
username: username,
confirmationCode: confirmationCode,
);
await _handleSignUpResult(result);
Sign in a user
Implement a UI to get the username from the user. After the user enters the username you can
start the sign in flow by calling the following method:
String? challengeHint;
setState(() {
isSignedIn = result.isSignedIn;
challengeHint = result.nextStep.additionalInfo['hint'];
});
Please note that you will be prevented from successfully calling signIn if a user has already
signed in and a valid session is active. You must first call signOut to remove the original session.
To get a custom challenge from the user, create an appropriate UI for the user to submit the
required value, and pass that value into the confirmSignin() API.
try {
/// Enter the random number generated by your Create Auth Challenge trigger
confirmationValue: generatedNumber,
);
}
Once the user provides the correct response, they should be authenticated in your application.
During a confirmSignIn call, if failAuthentication: true is returned by the Lambda, the session of
the request gets invalidated by Cognito, and a NotAuthorizedException is thrown. To recover,
the user must initiate a new sign in by calling Amplify.Auth.signIn.
The example in this documentation demonstrates the passwordless custom authentication flow.
However, it is also possible to require that users supply a valid password as part of the custom
authentication flow.
To require a valid password, you can alter the DefineAuthChallenge code to handle
a PASSWORD_VERIFIER step:
if (
){
event.response.issueTokens = false;
event.response.failAuthentication = false;
event.response.challengeName = 'PASSWORD_VERIFIER';
} else if (
){
event.response.issueTokens = false;
event.response.failAuthentication = false;
event.response.challengeName = 'CUSTOM_CHALLENGE';
} else if (
){
event.response.issueTokens = true;
event.response.failAuthentication = false;
} else {
event.response.issueTokens = false;
event.response.failAuthentication = true;
return event;
};
NEXT
Email customization
On this page
Prerequisites
Configure Auth
Register a user
Sign in a user
By default, Amplify Auth resources are scaffolded with email as the default method for your
users to sign in. When you users sign up they receive a verification email to confirm their
ownership of the email they specified during sign-up. Emails such as the verification email can
be customized with your app's brand identity.
To get started, change the email attribute of loginWith from true to an object to begin
customizing its default behavior:
amplify/auth/resource.ts
loginWith: {
- email: true,
+ email: {
+ verificationEmailStyle: "CODE",
+ },
},
})
In some cases, you may set up a user account on behalf of a user in the Amplify console. In this
case, Amplify Auth will send an invitation email to the user welcoming them to your application.
This email includes a brief welcome message, along with the email address they can log in with
and the temporary password you've set up for them.
If you'd like to customize that email, you can override the userInvitation attribute of
the email object:
amplify/auth/resource.ts
loginWith: {
- email: true,
+ email: {
+ verificationEmailStyle: "CODE",
+ userInvitation: {
+ `We're happy to have you! You can now login with username ${user()} and temporary
password ${code()}`,
+ },
+ },
},
})
riggers
Amplify Auth's behavior can be customized through the use of triggers. A trigger is defined as a
Function, and is a mechanism to slot some logic to execute during the authentication flow. For
example, you can use triggers to validate whether emails include an allowlisted domain, add a
user to a group upon confirmation, or create a "UserProfile" model upon account confirmation.
When you have a Lambda trigger assigned to your user pool, Amazon Cognito interrupts its
default flow to request information from your function. Amazon Cognito generates a JSON event
and passes it to your function. The event contains information about your user's request to
create a user account, sign in, reset a password, or update an attribute. Your function then has
an opportunity to take action, or to send the event back unmodified.
To get started, define a function and specify the triggers property on your auth resource:
amplify/auth/resource.ts
loginWith: {
email: true,
},
triggers: {}
})
Prerequisites
When configuring Social sign-in, it's important to exercise caution when designating attributes
as "required." Different social identity providers have varied scopes in terms of the information
they respond back to Cognito with. User pool attributes that are initially set up as "required"
cannot be changed later, and may require you to migrate the users or create a new user pool.
This library's Cognito plugin currently supports the Authorization Code Grant OAuth Flow.
Update the auth/resource.ts file like the following to enable the sign-in and sign-out capabilities
with a web ui.
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
callbackUrls: ["myapp://callback/"],
logoutUrls: ["myapp://signout/"],
},
},
});
How It Works
Sign-in with web UI will display the sign-in UI inside a webview. After the sign-in process is
complete, the sign-in UI will redirect back to your app.
Platform Setup
Web
To use Hosted UI in your Flutter web application locally, you must run the app with the --web-
port=3000 argument (with the value being whichever port you assigned to localhost host when
configuring your redirect URIs).
Android
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
<application>
...
<activity
android:name=".MainActivity" android:exported="true">
<intent-filter>
</intent-filter>
</activity>
...
</application>
macOS
Open XCode and enable the App Sandbox capability and then select "Incoming Connections
(Server)" under "Network".
iOS, Windows and Linux
try {
try {
provider: AuthProvider.google,
);
safePrint('Result: $result');
Facebook
Login With Amazon
Apple
This will bypass the permissions dialog that is displayed to the end user during sign in and sign
out. However, it will also prevent reuse of existing sessions from the user's browser. For
example, if the user is logged into Google in their browser and try to sign in using Google in your
app, they would now need to re-enter their credentials.
await Amplify.Auth.signInWithWebUI(
pluginOptions: CognitoSignInWithWebUIPluginOptions(
isPreferPrivateSession: true,
),
),
);
PREVIOUS
Moving to production
Amplify Auth provisions Amazon Cognito resources that are provisioned with limited capabilities
for sending email and SMS messages. In its default state, it is not intended to handle production
workloads, but is sufficient for developing your application and associated business logic.
Email
Cognito provides a default email functionality that limits how many emails can be sent in one
day. When considering production workloads, Cognito can be configured to send emails
using Amazon Simple Email Service (Amazon SES).
All new AWS accounts default to a "sandbox" status with Amazon SES. This comes with the
primary caveat that you can only send mail to verified email addresses and domains
To get started with Amazon SES in production, you must first request production access. Once
you submit your request the submission cannot be modified, however you will receive a
response from AWS within 24 hours.
After you have configured your account for production access and have verified
your sender email, you can configure your Cognito user pool to send emails using the verified
sender:
amplify/auth/resource.ts
/**
* @see https://docs.amplify.aws/react/build-a-backend/auth
*/
loginWith: {
email: true,
},
senders: {
email: {
fromEmail: "[email protected]",
},
},
})
Now when emails are sent on new user sign-ups, password resets, etc., the sending account will
be your verified email! To customize further, you can change the display name of the sender, or
optionally apply a custom address for your users to reply.
amplify/auth/resource.ts
/**
* @see https://docs.amplify.aws/react/build-a-backend/auth
*/
loginWith: {
email: true,
},
senders: {
email: {
fromEmail: "[email protected]",
fromName: "MyApp",
replyTo: "[email protected]"
},
},
})
SMS
In order to send SMS authentication codes, you must request an origination number.
Authentication codes will be sent from the origination number. If your AWS account is in the
SMS sandbox, you must also add a destination phone number, which can be done by going to
the Amazon Pinpoint Console, selecting SMS and voice in the navigation pane, and selecting
Add phone number in the Destination phone numbers tab. To check if your AWS account is in
the SMS sandbox, go to the SNS console, select the Text messaging (SMS) tab from the
navigation pane, and check the status under the Account information section.
dvanced workflows
With identity federation, you don't need to create custom sign-in code or manage your own
user identities. Instead, users of your app can sign in using a well-known external identity
provider (IdP), such as Login with Amazon, Facebook, Google, or any other OpenID Connect
(OIDC)-compatible IdP. They can receive an authentication token, and then exchange that token
for temporary security credentials in AWS that map to an IAM role with permissions to use the
resources in your AWS account. Using an IdP helps you keep your AWS account secure because
you don't have to embed and distribute long-term security credentials with your application.
Imagine that you are creating a mobile app that accesses AWS resources, such as a game that
runs on a mobile device and stores player and score information using Amazon S3 and
DynamoDB.
When you write such an app, you make requests to AWS services that must be signed with an
AWS access key. However, we strongly recommend that you do not embed or distribute long-
term AWS credentials with apps that a user downloads to a device, even in an encrypted store.
Instead, build your app so that it requests temporary AWS security credentials dynamically
when needed using identity federation. The supplied temporary credentials map to an AWS role
that has only the permissions needed to perform the tasks required by the mobile app.
You can use federateToIdentityPool to get AWS credentials directly from Cognito Federated
Identities and not use User Pool federation. If you logged in
with Auth.signIn you cannot call federateToIdentityPool as Amplify will perform this federation
automatically for you in the background. In general, you should only
call Auth.federatedSignIn() when using OAuth flows.
You can use the escape hatch API federateToIdentityPool with a valid token from other social
providers.
final cognitoPlugin =
Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey);
provider: AuthProvider.google,
);
Note that when federated, APIs such as Auth.getCurrentUser will throw an error as the user is
not authenticated with User Pools.
Retrieve Session
After federated login, you can retrieve the session using the Auth.fetchAuthSession API.
Token Refresh
By default, Amplify will NOT automatically refresh the tokens from the federated providers. You
will need to handle the token refresh logic and provide the new token to
the federateToIdentityPool API.
Clear Session
You can clear the federated session using the clearFederationToIdentityPool API.
final cognitoPlugin =
Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey);
await cognitoPlugin.clearFederationToIdentityPool();
clearFederationToIdentityPool will only clear the session from the local cache; the developer
needs to handle signing out from the federated identity provider.
You can provide a custom identity ID to the federateToIdentityPool API. This is useful when you
want to use the same identity ID across multiple sessions.
final cognitoPlugin =
Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey);
token: googleIdToken,
provider: AuthProvider.google,
options: FederateToIdentityPoolOptions(
developerProvidedIdentityId: identityId,
),