Skip to content

Commit 91241f7

Browse files
scanlonpjjarvispjosefaidt
authored
chore(auth): add js passwordless changes (#8129)
* chore(auth): add js passwordless changes * chore(auth): add filters and a react-native callout; code spacing * chore(auth): add sign in updates * Update src/pages/[platform]/build-a-backend/auth/manage-users/manage-webauthn-credentials/index.mdx Co-authored-by: James Jarvis <[email protected]> * chore(auth): add associate api to the manage webauthn page * Update src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx Co-authored-by: josef <[email protected]> * chore(auth): use string literals * chore(auth): add signin next step types * add js sign up examples * chore(auth): improve wording * chore(auth): add first factor selection to confirm sign-in next steps * Update src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx Co-authored-by: James Jarvis <[email protected]> * Update src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx Co-authored-by: James Jarvis <[email protected]> * chore(auth): review feedback - formatting and wording * chore(auth): move user auth flow info into switching flows page --------- Co-authored-by: James Jarvis <[email protected]> Co-authored-by: josef <[email protected]>
1 parent 4e08e55 commit 91241f7

File tree

4 files changed

+340
-16
lines changed
  • src/pages/[platform]/build-a-backend/auth

4 files changed

+340
-16
lines changed

src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx

+89-4
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,10 @@ The `signIn` API response will include a `nextStep` property, which can be used
259259
| `CONFIRM_SIGN_IN_WITH_NEW_PASSWORD_REQUIRED` | The user was created with a temporary password and must set a new one. Complete the process with `confirmSignIn`. |
260260
| `CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE` | The sign-in must be confirmed with a custom challenge response. Complete the process with `confirmSignIn`. |
261261
| `CONFIRM_SIGN_IN_WITH_TOTP_CODE` | The sign-in must be confirmed with a TOTP code from the user. Complete the process with `confirmSignIn`. |
262-
| `CONFIRM_SIGN_IN_WITH_SMS_CODE` | The sign-in must be confirmed with a SMS code from the user. Complete the process with `confirmSignIn`. |
263-
| `CONFIRM_SIGN_IN_WITH_EMAIL_CODE` | The sign-in must be confirmed with a EMAIL code from the user. Complete the process with `confirmSignIn`. |
262+
| `CONFIRM_SIGN_IN_WITH_SMS_CODE` | The sign-in must be confirmed with an SMS code from the user. Complete the process with `confirmSignIn`. |
263+
| `CONFIRM_SIGN_IN_WITH_EMAIL_CODE` | The sign-in must be confirmed with an EMAIL code from the user. Complete the process with `confirmSignIn`. |
264+
| `CONFIRM_SIGN_IN_WITH_PASSWORD` | The sign-in must be confirmed with the password from the user. Complete the process with `confirmSignIn`. |
265+
| `CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION` | The user must select their mode of first factor authentication. Complete the process by passing the desired mode to the `challengeResponse` field of `confirmSignIn`. |
264266
| `CONTINUE_SIGN_IN_WITH_MFA_SELECTION` | The user must select their mode of MFA verification before signing in. Complete the process with `confirmSignIn`. |
265267
| `CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION` | The user must select their mode of MFA verification to setup. Complete the process by passing either `"EMAIL"` or `"TOTP"` to `confirmSignIn`. |
266268
| `CONTINUE_SIGN_IN_WITH_TOTP_SETUP` | The TOTP setup process must be continued. Complete the process with `confirmSignIn`. |
@@ -591,6 +593,8 @@ Following sign in, you will receive a `nextStep` in the sign-in result of one of
591593
| `CONFIRM_SIGN_IN_WITH_TOTP_CODE` | The sign-in must be confirmed with a TOTP code from the user. Complete the process with `confirmSignIn`. |
592594
| `CONFIRM_SIGN_IN_WITH_SMS_CODE` | The sign-in must be confirmed with a SMS code from the user. Complete the process with `confirmSignIn`. |
593595
| `CONFIRM_SIGN_IN_WITH_EMAIL_CODE` | The sign-in must be confirmed with a EMAIL code from the user. Complete the process with `confirmSignIn`. |
596+
| `CONFIRM_SIGN_IN_WITH_PASSWORD` | The sign-in must be confirmed with the password from the user. Complete the process with `confirmSignIn`. |
597+
| `CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION` | The user must select their mode of first factor authentication. Complete the process by passing the desired mode to the `challengeResponse` field of `confirmSignIn`. |
594598
| `CONTINUE_SIGN_IN_WITH_MFA_SELECTION` | The user must select their mode of MFA verification before signing in. Complete the process with `confirmSignIn`. |
595599
| `CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION` | The user must select their mode of MFA verification to setup. Complete the process by passing either `"EMAIL"` or `"TOTP"` to `confirmSignIn`. |
596600
| `CONTINUE_SIGN_IN_WITH_TOTP_SETUP` | The TOTP setup process must be continued. Complete the process with `confirmSignIn`. |
@@ -1113,7 +1117,18 @@ Your application's users can also sign in using passwordless methods. To learn m
11131117

11141118
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
11151119

1116-
{/* */}
1120+
To request an OTP code via SMS for authentication, the challenge is passed as the challenge response to the confirm sign in API.
1121+
1122+
Amplify will respond appropriately to Cognito and return the challenge as sign in next step: `CONFIRM_SIGN_IN_WITH_SMS_CODE`:
1123+
1124+
```ts
1125+
const { nextStep } = await confirmSignIn({
1126+
challengeResponse: "SMS_OTP"
1127+
});
1128+
1129+
// nextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_SMS_CODE'
1130+
handleNextSignInStep(nextStep);
1131+
```
11171132

11181133
</InlineFilter>
11191134
<InlineFilter filters={["android"]}>
@@ -1205,7 +1220,18 @@ func confirmSignIn() -> AnyCancellable {
12051220

12061221
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
12071222

1208-
{/* */}
1223+
To request an OTP code via email for authentication, the challenge is passed as the challenge response to the confirm sign in API.
1224+
1225+
Amplify will respond appropriately to Cognito and return the challenge as sign in next step: `CONFIRM_SIGN_IN_WITH_EMAIL_CODE`:
1226+
1227+
```ts
1228+
const { nextStep } = await confirmSignIn({
1229+
challengeResponse: "EMAIL_OTP"
1230+
});
1231+
1232+
// nextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_EMAIL_CODE'
1233+
handleNextSignInStep(nextStep);
1234+
```
12091235

12101236
</InlineFilter>
12111237
<InlineFilter filters={["android"]}>
@@ -1290,3 +1316,62 @@ func confirmSignIn() -> AnyCancellable {
12901316
</BlockSwitcher>
12911317

12921318
</InlineFilter>
1319+
1320+
### WebAuthn Passkeys
1321+
1322+
{/* blurb with supplemental information about handling sign-in, events, etc. */}
1323+
1324+
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
1325+
1326+
The WebAuthn credential flow is initiated by passing the challenge name to the confirm sign in api.
1327+
1328+
```ts
1329+
const { nextStep } = await confirmSignIn({
1330+
challengeResponse: "WEB_AUTHN",
1331+
});
1332+
1333+
// nextStep.signInStep === 'DONE'
1334+
handleNextSignInStep(nextStep);
1335+
```
1336+
1337+
</InlineFilter>
1338+
<InlineFilter filters={["android"]}>
1339+
1340+
{/* */}
1341+
1342+
</InlineFilter>
1343+
<InlineFilter filters={["flutter"]}>
1344+
1345+
{/* */}
1346+
1347+
</InlineFilter>
1348+
<InlineFilter filters={["swift"]}>
1349+
1350+
{/* */}
1351+
1352+
</InlineFilter>
1353+
1354+
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
1355+
1356+
### Password or SRP
1357+
1358+
Traditional password based authentication is available from this flow as well. To initiate this flow from select challenge, either `PASSWORD` or `PASSWORD_SRP` is passed as the challenge response.
1359+
1360+
```ts
1361+
const { nextStep } = await confirmSignIn({
1362+
challengeResponse: "PASSWORD_SRP", // or "PASSWORD"
1363+
});
1364+
1365+
// in both cases
1366+
// nextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_PASSWORD'
1367+
handleNextSignInStep(nextStep);
1368+
1369+
const { nextStep: nextNextStep } = await confirmSignIn({
1370+
challengeResponse: "Test123#",
1371+
});
1372+
1373+
// nextNextStep.signInStep === 'DONE'
1374+
handleNextSignInStep(nextNextStep);
1375+
```
1376+
1377+
</InlineFilter>

src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-up/index.mdx

+82-3
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,40 @@ Your application's users can also sign up using passwordless methods. To learn m
538538

539539
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
540540

541-
{/* */}
541+
```typescript
542+
// Sign up using a phone number
543+
const { nextStep: signUpNextStep } = await signUp({
544+
username: 'james',
545+
options: {
546+
userAttributes: {
547+
phone_number: '+15555551234',
548+
},
549+
},
550+
});
551+
552+
if (signUpNextStep.signUpStep === 'DONE') {
553+
console.log(`SignUp Complete`);
554+
}
555+
556+
if (signUpNextStep.signUpStep === 'CONFIRM_SIGN_UP') {
557+
console.log(
558+
`Code Delivery Medium: ${signUpNextStep.codeDeliveryDetails.deliveryMedium}`,
559+
);
560+
console.log(
561+
`Code Delivery Destination: ${signUpNextStep.codeDeliveryDetails.destination}`,
562+
);
563+
}
564+
565+
// Confirm sign up with the OTP received
566+
const { nextStep: confirmSignUpNextStep } = await confirmSignUp({
567+
username: 'james',
568+
confirmationCode: '123456',
569+
});
570+
571+
if (confirmSignUpNextStep.signUpStep === 'DONE') {
572+
console.log(`SignUp Complete`);
573+
}
574+
```
542575

543576
</InlineFilter>
544577
<InlineFilter filters={["android"]}>
@@ -653,7 +686,40 @@ func confirmSignUp(for username: String, with confirmationCode: String) -> AnyCa
653686

654687
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
655688

656-
{/* */}
689+
```typescript
690+
// Sign up using an email address
691+
const { nextStep: signUpNextStep } = await signUp({
692+
username: 'james',
693+
options: {
694+
userAttributes: {
695+
696+
},
697+
},
698+
});
699+
700+
if (signUpNextStep.signUpStep === 'DONE') {
701+
console.log(`SignUp Complete`);
702+
}
703+
704+
if (signUpNextStep.signUpStep === 'CONFIRM_SIGN_UP') {
705+
console.log(
706+
`Code Delivery Medium: ${signUpNextStep.codeDeliveryDetails.deliveryMedium}`,
707+
);
708+
console.log(
709+
`Code Delivery Destination: ${signUpNextStep.codeDeliveryDetails.destination}`,
710+
);
711+
}
712+
713+
// Confirm sign up with the OTP received
714+
const { nextStep: confirmSignUpNextStep } = await confirmSignUp({
715+
username: 'james',
716+
confirmationCode: '123456',
717+
});
718+
719+
if (confirmSignUpNextStep.signUpStep === 'DONE') {
720+
console.log(`SignUp Complete`);
721+
}
722+
```
657723

658724
</InlineFilter>
659725
<InlineFilter filters={["android"]}>
@@ -768,8 +834,21 @@ func confirmSignUp(for username: String, with confirmationCode: String) -> AnyCa
768834

769835
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
770836

771-
{/* */}
837+
```typescript
838+
// Confirm sign up with the OTP received and auto sign in
839+
const { nextStep: confirmSignUpNextStep } = await confirmSignUp({
840+
username: 'james',
841+
confirmationCode: '123456',
842+
});
772843

844+
if (confirmSignUpNextStep.signUpStep === 'COMPLETE_AUTO_SIGN_IN') {
845+
const { nextStep } = await autoSignIn();
846+
847+
if (nextStep.signInStep === 'DONE') {
848+
console.log('Successfully signed in.');
849+
}
850+
}
851+
```
773852
</InlineFilter>
774853
<InlineFilter filters={["android"]}>
775854

src/pages/[platform]/build-a-backend/auth/connect-your-frontend/switching-authentication-flows/index.mdx

+62-6
Original file line numberDiff line numberDiff line change
@@ -145,28 +145,84 @@ Follow the instructions in [Custom Auth Sign In](/gen1/[platform]/build-a-backen
145145

146146
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
147147

148-
For client side authentication there are three different flows:
148+
For client side authentication there are four different flows:
149149

150-
1. `USER_SRP_AUTH`: The `USER_SRP_AUTH` flow uses the [SRP protocol (Secure Remote Password)](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) where the password never leaves the client and is unknown to the server. This is the recommended flow and is used by default.
150+
1. `USER_AUTH`: The `USER_AUTH` flow is designed to be flexible and supports both password and passwordless sign in factors. `USER_AUTH` can do username-password and SRP authentication without the other flows being configured. This flow doesn't include CUSTOM_AUTH. This is the recommended flow.
151151

152-
2. `USER_PASSWORD_AUTH`: The `USER_PASSWORD_AUTH` flow will send user credentials to the backend without applying SRP encryption. If you want to migrate users to Cognito using the "Migration" trigger and avoid forcing users to reset their passwords, you will need to use this authentication type because the Lambda function invoked by the trigger needs to verify the supplied credentials.
152+
2. `USER_SRP_AUTH`: The `USER_SRP_AUTH` flow uses the [SRP protocol (Secure Remote Password)](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) where the password never leaves the client and is unknown to the server.
153153

154-
3. `CUSTOM_WITH_SRP` & `CUSTOM_WITHOUT_SRP`: Allows for a series of challenge and response cycles that can be customized to meet different requirements.
154+
3. `USER_PASSWORD_AUTH`: The `USER_PASSWORD_AUTH` flow will send user credentials unencrypted to the backend. If you want to migrate users to Cognito using the "Migration" trigger and avoid forcing users to reset their passwords, you will need to use this authentication type because the Lambda function invoked by the trigger needs to verify the supplied credentials.
155+
156+
4. `CUSTOM_WITH_SRP` & `CUSTOM_WITHOUT_SRP`: Allows for a series of challenge and response cycles that can be customized to meet different requirements.
155157

156158
The Auth flow can be customized when calling `signIn`, for example:
157159

158160
```ts title="src/main.ts"
159161
await signIn({
160-
username: "[email protected]",
162+
username: "[email protected]",
161163
password: "hunter2",
162164
options: {
163-
authFlowType: 'USER_PASSWORD_AUTH'
165+
authFlowType: 'USER_AUTH'
164166
}
165167
})
166168
```
167169

168170
> For more information about authentication flows, please visit [AWS Cognito developer documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-custom-authentication-flow)
169171
172+
## USER_AUTH flow
173+
174+
In order to facilitate the new passwordless sign in options, Cognito is introducing a new auth flow type known as `USER_AUTH`. This flow is designed to be flexible and supports both password and passwordless sign in factors.
175+
176+
### Set up auth backend
177+
178+
Configure supported flows in your Cognito app client. In the AWS Console, this is done by ticking the checkboxes at General settings > App clients > App client information (Edit) > App client flows. If you're using the AWS CLI or CloudFormation, update your app client by adding `USER_AUTH` to the list of "Explicit Auth Flows".
179+
180+
### User authentication flow
181+
182+
The `USER_AUTH` sign in flow will support the following methods of first factor authentication: `WEB_AUTHN`, `EMAIL_OTP`, `SMS_OTP`, `PASSWORD`, and `PASSWORD_SRP`.
183+
184+
```ts
185+
type AuthFactorType =
186+
| "WEB_AUTHN"
187+
| "EMAIL_OTP"
188+
| "SMS_OTP"
189+
| "PASSWORD"
190+
| "PASSWORD_SRP";
191+
```
192+
193+
If the desired first factor is known before the sign in flow is initiated it can be passed to the initial sign in call.
194+
195+
Password flows will require the password to be passed in the same step. Passwordless flows do not require user input, and the challenges will be handled in the next sign in step:
196+
197+
```ts
198+
// PASSWORD_SRP / PASSWORD
199+
// sign in with preferred challenge as password
200+
// note password must be provided in same step
201+
const { nextStep } = await signIn({
202+
username: "[email protected]",
203+
password: "hunter2",
204+
options: {
205+
authFlowType: "USER_AUTH",
206+
preferredChallenge: "PASSWORD_SRP" // or "PASSWORD"
207+
},
208+
});
209+
210+
// WEB_AUTHN / EMAIL_OTP / SMS_OTP
211+
// sign in with preferred passwordless challenge
212+
// no user input required at this step
213+
const { nextStep } = await signIn({
214+
username: "[email protected]",
215+
options: {
216+
authFlowType: "USER_AUTH",
217+
preferredChallenge: "WEB_AUTHN" // or "EMAIL_OTP" or "SMS_OTP"
218+
},
219+
});
220+
```
221+
222+
If the desired first factor is not known, the flow will continue to select an available first factor.
223+
224+
> For more information about determining a first factor, and signing in with passwordless authorization factors, please visit the [concepts page for passwordless](/[platform]/build-a-backend/auth/concepts/passwordless/)
225+
170226
## USER_PASSWORD_AUTH flow
171227

172228
A use case for the `USER_PASSWORD_AUTH` authentication flow is migrating users into Amazon Cognito

0 commit comments

Comments
 (0)