diff --git a/src/directory/directory.js b/src/directory/directory.js
index cc5cf5c968b..1fecc9a1dd7 100644
--- a/src/directory/directory.js
+++ b/src/directory/directory.js
@@ -288,6 +288,11 @@ const directory = {
route: '/lib/auth/signin',
filters: ['android', 'flutter', 'ios']
},
+ {
+ title: 'Switching authentication flows',
+ route: '/lib/auth/switch-auth',
+ filters: ['ios']
+ },
{
title: 'Sign in with custom flow',
route: '/lib/auth/signin_with_custom_flow',
@@ -363,6 +368,11 @@ const directory = {
route: '/lib/auth/escapehatch',
filters: ['android', 'ios']
},
+ {
+ title: 'Advanced workflows',
+ route: '/lib/auth/advanced',
+ filters: ['ios']
+ },
{
title: 'Under the hood',
route: '/lib/auth/overview',
diff --git a/src/fragments/lib/auth/ios/advanced/advanced.mdx b/src/fragments/lib/auth/ios/advanced/advanced.mdx
new file mode 100644
index 00000000000..5d64af4d187
--- /dev/null
+++ b/src/fragments/lib/auth/ios/advanced/advanced.mdx
@@ -0,0 +1,93 @@
+## Subscribing Events
+
+You can take specific actions when users sign-in or sign-out by subscribing authentication events in your app. Please see our [Hub Module Developer Guide](/lib/utilities/hub) for more information.
+
+## Identity Pool Federation
+
+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 web 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.
+
+With web 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.
+
+You can use `federateToIdentityPool` to get AWS credentials directly from Cognito Federated Identities and not use User Pool federation. If you have logged in with `Auth.signIn` you **can not** 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.
+
+```swift
+func federateToIdentityPools() async throws {
+ guard let authCognitoPlugin = try Amplify.Auth.getPlugin(
+ for: "awsCognitoAuthPlugin") as? AWSCognitoAuthPlugin else {
+ fatalError("Unable to get the Auth plugin")
+ }
+ do {
+ let result = try await authCognitoPlugin.federateToIdentityPool(
+ withProviderToken: "YOUR_TOKEN", for: .facebook)
+ print("Federation successful with result: \(result)")
+ } catch {
+ print("Failed to federate to identity pools with error: \(error)")
+ }
+}
+```
+
+
+Note that when federated, API's 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 session using the `Auth.fetchAuthSession` API.
+
+### Token Refresh
+
+
+NOTE: Automatic authentication token refresh is NOT supported when federated.
+
+
+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.
+
+```swift
+func clearFederationToIdentityPools() async throws {
+ guard let authCognitoPlugin = try Amplify.Auth.getPlugin(
+ for: "awsCognitoAuthPlugin") as? AWSCognitoAuthPlugin else {
+ fatalError("Unable to get the Auth plugin")
+ }
+ do {
+ try await authCognitoPlugin.clearFederationToIdentityPool()
+ print("Federation cleared successful")
+ } catch {
+ print("Clear federation failed with error: \(error)")
+ }
+}
+```
+
+
+clearFederationToIdentityPool will only clear the session from local cache, developer need to handle signing out from the federated provider.
+
+
+### Provide Custom Identity Id
+
+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 devices.
+
+```swift
+func federateToIdentityPoolsUsingCustomIdentityId() async throws {
+ guard let authCognitoPlugin = try Amplify.Auth.getPlugin(
+ for: "awsCognitoAuthPlugin") as? AWSCognitoAuthPlugin else {
+ fatalError("Unable to get the Auth plugin")
+ }
+ do {
+ let identityId = "YOUR_CUSTOM_IDENTITY_ID"
+ let result = try await authCognitoPlugin.federateToIdentityPool(
+ withProviderToken: "YOUR_TOKEN",
+ for: .facebook,
+ options: .init(developerProvidedIdentityID: identityId))
+ print("Federation successful with result: \(result)")
+ } catch {
+ print("Failed to federate to identity pools with error: \(error)")
+ }
+}
+```
\ No newline at end of file
diff --git a/src/fragments/lib/auth/ios/signin_with_custom_flow/50_custom_challenge.mdx b/src/fragments/lib/auth/ios/signin_with_custom_flow/50_custom_challenge.mdx
index ca36673b446..b6d51393e97 100644
--- a/src/fragments/lib/auth/ios/signin_with_custom_flow/50_custom_challenge.mdx
+++ b/src/fragments/lib/auth/ios/signin_with_custom_flow/50_custom_challenge.mdx
@@ -50,6 +50,8 @@ The Amplify CLI can be used to generate triggers required by a custom authentica
> More information on available triggers can be found in the [Cognito documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html).
+### Custom Auth Flow with SRP
+
Cognito User Pool allows to start the custom authentication flow with SRP as the first step. If you would like to use this flow, setup Define Auth Lambda trigger to handle SRP_A as the first challenge as shown below:
```javascript
@@ -78,10 +80,71 @@ exports.handler = (event, context) => {
};
```
-If your lambda is setup to start with `SRP` as the first step, make sure to initiate the signIn process with `SRP` as the authentication flow:
+If your lambda is setup to start with `SRP` as the first step, make sure to initiate the signIn process with `customWithSRP` as the authentication flow:
```swift
-let options = AWSAuthSignInOptions(authFlowType: .customWithSRP)
-let signInResult = try await Amplify.Auth.signIn(username: username,
- options: .init(pluginOptions: options))
+let options = AWSAuthSignInOptions(
+ authFlowType: .customWithSRP)
+let signInResult = try await Amplify.Auth.signIn(
+ username: username,
+ password: password,
+ options: .init(pluginOptions: options))
+```
+
+### CAPTCHA-based authentication
+
+Here is the sample for creating a CAPTCHA challenge with a Lambda Trigger.
+
+The `Create Auth Challenge Lambda Trigger` creates a CAPTCHA as a challenge to the user. The URL for the CAPTCHA image and the expected answer is added to the private challenge parameters:
+
+```javascript
+export const handler = async (event) => {
+ if (!event.request.session || event.request.session.length === 0) {
+ event.response.publicChallengeParameters = {
+ captchaUrl: ,
+ };
+ event.response.privateChallengeParameters = {
+ answer: ,
+ };
+ event.response.challengeMetadata = "CAPTCHA_CHALLENGE";
+ }
+ return event;
+};
+```
+
+This `Define Auth Challenge Lambda Trigger` defines a custom challenge:
+
+```javascript
+export const handler = async (event) => {
+ if (!event.request.session || event.request.session.length === 0) {
+ // If we don't have a session or it is empty then send a CUSTOM_CHALLENGE
+ event.response.challengeName = "CUSTOM_CHALLENGE";
+ event.response.failAuthentication = false;
+ event.response.issueTokens = false;
+ } else if (event.request.session.length === 1 && event.request.session[0].challengeResult === true) {
+ // If we passed the CUSTOM_CHALLENGE then issue token
+ event.response.failAuthentication = false;
+ event.response.issueTokens = true;
+ } else {
+ // Something is wrong. Fail authentication
+ event.response.failAuthentication = true;
+ event.response.issueTokens = false;
+ }
+
+ return event;
+};
+```
+
+The `Verify Auth Challenge Response Lambda Trigger` is used to verify a challenge answer:
+
+```javascript
+export const handler = async (event, context) => {
+ if (event.request.privateChallengeParameters.answer === event.request.challengeAnswer) {
+ event.response.answerCorrect = true;
+ } else {
+ event.response.answerCorrect = false;
+ }
+
+ return event;
+};
```
\ No newline at end of file
diff --git a/src/fragments/lib/auth/ios/switch-auth/switch-auth.mdx b/src/fragments/lib/auth/ios/switch-auth/switch-auth.mdx
new file mode 100644
index 00000000000..bd27c6fc054
--- /dev/null
+++ b/src/fragments/lib/auth/ios/switch-auth/switch-auth.mdx
@@ -0,0 +1,95 @@
+`AWSCognitoAuthPlugin` allows you to switch between different auth flows while initiating signIn. You can configure the flow in the `amplifyconfiguration.json` file or pass the `authFlowType` as a runtime parameter to the `signIn` api call.
+
+For client side authentication there are four different flows that can be configured during runtime:
+
+1. `userSRP`: The `userSRP` flow uses the SRP protocol (Secure Remote Password) where the password never leaves the client and is unknown to the server. This is the recommended flow and is used by default.
+
+2. `userPassword`: The `userPassword` flow will send user credentials unencrypted to the back-end. 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.
+
+3. `customWithSRP`: The `customWithSRP` flow is used to start with SRP authentication and then switch to custom authentication. This is useful if you want to use SRP for the initial authentication and then use custom authentication for subsequent authentication attempts.
+
+4. `customWithoutSRP`: The `customWithoutSRP` flow is used to start authentication flow **WITHOUT** SRP and then use a series of challenge and response cycles that can be customized to meet different requirements.
+
+`Auth` can be configured to use the different flows at runtime by calling `signIn` with `AuthSignInOptions`'s `authFlowType` as `AuthFlowType.userPassword`, `AuthFlowType.customAuthWithoutSrp` or `AuthFlowType.customAuthWithSrp`. If you do not specify the `AuthFlowType` in `AuthSignInOptions`, the default flow (`AuthFlowType.userSRP`) will be used.
+
+```swift
+public enum AuthFlowType: String {
+
+ /// Authentication flow for the Secure Remote Password (SRP) protocol
+ case userSRP
+
+ /// Authentication flow for custom flow which are backed by lambda triggers.
+ /// Note that `custom`will always begin with a SRP flow.
+ @available(*, deprecated, message: "Use of custom is deprecated, use customWithSrp or customWithoutSrp instead")
+ case custom
+
+ /// Authentication flow which start with SRP and then move to custom auth flow
+ case customWithSRP
+
+ /// Authentication flow which starts without SRP and directly moves to custom auth flow
+ case customWithoutSRP
+
+ /// Non-SRP authentication flow; user name and password are passed directly.
+ /// If a user migration Lambda trigger is set, this flow will invoke the user migration
+ /// Lambda if it doesn't find the user name in the user pool.
+ case userPassword
+}
+```
+
+
+
+Runtime configuration will take precedence and will override any auth flow type configuration present in amplifyconfiguration.json
+
+
+
+> 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)
+
+## USER_PASSWORD_AUTH flow
+
+A use case for the `USER_PASSWORD_AUTH` authentication flow is migrating users into Amazon Cognito
+
+A user migration Lambda trigger helps migrate users from a legacy user management system into your user pool. If you choose the USER_PASSWORD_AUTH authentication flow, users don't have to reset their passwords during user migration. This flow sends your users' passwords to the service over an encrypted SSL connection during authentication.
+
+When you have migrated all your users, switch flows to the more secure SRP flow. The SRP flow doesn't send any passwords over the network.
+
+```swift
+func signIn(username: String, password: String) async throws {
+
+ let option = AWSAuthSignInOptions(authFlowType: .userPassword)
+ do {
+ let result = try await Amplify.Auth.signIn(
+ username: username,
+ password: password,
+ options: AuthSignInRequest.Options(pluginOptions: option))
+ print("Sign in succeeded with result: \(result)")
+ } catch {
+ print("Failed to sign in with error: \(error)")
+ }
+}
+```
+
+### Setup auth backend
+
+In order to use the authentication flow `USER_PASSWORD_AUTH`, your Cognito app client has to be configured to allow it. In the AWS Console, this is done by ticking the checkbox at General settings > App clients > Show Details (for the affected client) > Enable username-password (non-SRP) flow. If you're using the AWS CLI or CloudFormation, update your app client by adding `USER_PASSWORD_AUTH` to the list of "Explicit Auth Flows".
+
+### Migrate users with Amazon Cognito
+
+Amazon Cognito provides a trigger to migrate users from your existing user directory seamlessly into Cognito. You achieve this by configuring your User Pool's "Migration" trigger which invokes a Lambda function whenever a user that does not already exist in the user pool authenticates, or resets their password.
+
+In short, the Lambda function will validate the user credentials against your existing user directory and return a response object containing the user attributes and status on success. An error message will be returned if an error occurs. There's a documentation [here](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-import-using-lambda.html) on how to set up this migration flow and more detailed instructions [here](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-migrate-user.html#cognito-user-pools-lambda-trigger-syntax-user-migration) on how the lambda should handle request and response objects.
+
+## CUSTOM_AUTH flow
+
+Amazon Cognito User Pools supports customizing the authentication flow to enable custom challenge types, in addition to a password in order to verify the identity of users. The custom authentication flow is a series of challenge and response cycles that can be customized to meet different requirements. These challenge types may include CAPTCHAs or dynamic challenge questions.
+
+To define your challenges for custom authentication flow, you need to implement three Lambda triggers for Amazon Cognito.
+
+The flow is initiated by calling `signIn` with `AuthSignInOptions` configured with `AuthFlowType.customAuthWithSrp` OR `AuthFlowType.customAuthWithoutSrp`.
+
+Follow the instructions in [Custom Auth Sign In](/lib/auth/signin_with_custom_flow) to learn about how to integrate custom authentication flow in your application with the Auth APIs.
+
+
+
+For more information about working with Lambda Triggers for custom authentication challenges, please visit [Amazon Cognito Developer Documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html).
+
+
\ No newline at end of file
diff --git a/src/pages/lib/auth/advanced/q/platform/[platform].mdx b/src/pages/lib/auth/advanced/q/platform/[platform].mdx
index f608319032f..61f6f045dd8 100644
--- a/src/pages/lib/auth/advanced/q/platform/[platform].mdx
+++ b/src/pages/lib/auth/advanced/q/platform/[platform].mdx
@@ -3,6 +3,10 @@ export const meta = {
description: `Learn more about advanced workflows in the Amplify auth category. This includes subscribing to events, identity pool federation, auth-related Lambda triggers and working with AWS service objects.`,
};
+import ios0 from "/src/fragments/lib/auth/ios/advanced/advanced.mdx";
+
+
+
import js0 from "/src/fragments/lib/auth/js/advanced.mdx";
diff --git a/src/pages/lib/auth/switch-auth/q/platform/[platform].mdx b/src/pages/lib/auth/switch-auth/q/platform/[platform].mdx
index f33b2474e2d..60b2ea6e9b8 100644
--- a/src/pages/lib/auth/switch-auth/q/platform/[platform].mdx
+++ b/src/pages/lib/auth/switch-auth/q/platform/[platform].mdx
@@ -3,6 +3,10 @@ export const meta = {
description: `Learn more about how to switch between different auth flows in Amplify.`,
};
+import ios0 from "/src/fragments/lib/auth/ios/switch-auth/switch-auth.mdx";
+
+
+
import js0 from "/src/fragments/lib/auth/js/switch-auth.mdx";