From 828585385e36977bd67956ee1854c8f14fffbacf Mon Sep 17 00:00:00 2001 From: salihgueler Date: Mon, 15 Apr 2024 14:32:24 +0300 Subject: [PATCH 1/5] Move the accessing credentials code for Flutter, iOS and Android to Gen 2 docs. --- src/directory/directory.mjs | 3 + .../auth/access-credentials/index.mdx | 242 ++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx diff --git a/src/directory/directory.mjs b/src/directory/directory.mjs index 8e83e9f5d5d..99623b2fd82 100644 --- a/src/directory/directory.mjs +++ b/src/directory/directory.mjs @@ -61,6 +61,9 @@ export const directory = { { path: 'src/pages/[platform]/build-a-backend/auth/set-up-auth/index.mdx' }, + { + path: 'src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx' + }, { path: 'src/pages/[platform]/build-a-backend/auth/enable-sign-up/index.mdx' }, diff --git a/src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx new file mode 100644 index 00000000000..10ef4e366f5 --- /dev/null +++ b/src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx @@ -0,0 +1,242 @@ +import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; + +export const meta = { + title: 'Accessing Credentials', + description: 'Use AWS Cognito Auth plugin to access auth credentials with Amplify Gen 2', + platforms: [ + 'android', + 'flutter', + 'swift', + ] +}; + +export const getStaticPaths = async () => { + return getCustomStaticPath(meta.platforms); +}; + +export function getStaticProps(context) { + return { + props: { + platform: context.params.platform, + meta + } + }; +} + + +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: + +```dart +Future fetchAuthSession() async { + try { + final result = await Amplify.Auth.fetchAuthSession(); + safePrint('User is signed in: ${result.isSignedIn}'); + } on AuthException catch (e) { + safePrint('Error retrieving auth session: ${e.message}'); + } +} +``` + +### Retrieving AWS credentials + +Sometimes it can be helpful to retrieve the instance of the underlying plugin +which has more specific typing. In the 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. + +```dart +Future fetchCognitoAuthSession() async { + try { + final cognitoPlugin = Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey); + final result = await cognitoPlugin.fetchAuthSession(); + final identityId = result.identityIdResult.value; + safePrint("Current user's identity ID: $identityId"); + } on AuthException catch (e) { + safePrint('Error retrieving auth session: ${e.message}'); + } +} +``` + + +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 casting the result of fetchAuthSession as follows: + + + + +```java +Amplify.Auth.fetchAuthSession( + result -> { + AWSCognitoAuthSession cognitoAuthSession = (AWSCognitoAuthSession) result; + switch(cognitoAuthSession.getIdentityIdResult().getType()) { + case SUCCESS: + Log.i("AuthQuickStart", "IdentityId: " + cognitoAuthSession.getIdentityIdResult().getValue()); + break; + case FAILURE: + Log.i("AuthQuickStart", "IdentityId not present because: " + cognitoAuthSession.getIdentityIdResult().getError().toString()); + } + }, + error -> Log.e("AuthQuickStart", error.toString()) +); +``` + + + + +```kotlin +Amplify.Auth.fetchAuthSession( + { + val session = it as AWSCognitoAuthSession + when (session.identityIdResult.type) { + AuthSessionResult.Type.SUCCESS -> + Log.i("AuthQuickStart", "IdentityId = ${session.identityIdResult.value}") + AuthSessionResult.Type.FAILURE -> + Log.w("AuthQuickStart", "IdentityId not found", session.identityIdResult.error) + } + }, + { Log.e("AuthQuickStart", "Failed to fetch session", it) } +) +``` + + + + +```kotlin +try { + val session = Amplify.Auth.fetchAuthSession() as AWSCognitoAuthSession + val id = session.identityIdResult + if (id.type == AuthSessionResult.Type.SUCCESS) { + Log.i("AuthQuickStart", "IdentityId: ${id.value}") + } else if (id.type == AuthSessionResult.Type.FAILURE) { + Log.i("AuthQuickStart", "IdentityId not present: ${id.error}") + } +} catch (error: AuthException) { + Log.e("AuthQuickStart", "Failed to fetch session", error) +} +``` + + + + +```java +RxAmplify.Auth.fetchAuthSession() + .subscribe( + result -> { + AWSCognitoAuthSession cognitoAuthSession = (AWSCognitoAuthSession) result; + + switch (cognitoAuthSession.getIdentityIdResult().getType()) { + case SUCCESS: + Log.i("AuthQuickStart", "IdentityId: " + cognitoAuthSession.getIdentityIdResult().getValue()); + break; + case FAILURE: + Log.i("AuthQuickStart", "IdentityId not present because: " + cognitoAuthSession.getIdentityIdResult().getError().toString()); + } + }, + error -> Log.e("AuthQuickStart", error.toString()) + ); +``` + + + + +## Force refreshing session + +You can ask the plugin to force refresh the internal session by setting the `forceRefresh` option when calling the fetchAuthSession API. + + + + +```java +AuthFetchSessionOptions options = AuthFetchSessionOptions.builder().forceRefresh(true).build(); +``` + + + + +```kotlin +val option = AuthFetchSessionOptions.builder().forceRefresh(true).build() +``` + + + + +```kotlin +val option = AuthFetchSessionOptions.builder().forceRefresh(true).build() +``` + + + + +```java +AuthFetchSessionOptions options = AuthFetchSessionOptions.builder().forceRefresh(true).build(); +``` + + + + + +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 casting the result of fetchAuthSession as follows: + +```swift +import AWSPluginsCore + +do { + let session = try await Amplify.Auth.fetchAuthSession() + + // Get user sub or identity id + if let identityProvider = session as? AuthCognitoIdentityProvider { + let usersub = try identityProvider.getUserSub().get() + let identityId = try identityProvider.getIdentityId().get() + print("User sub - \(usersub) and identity id \(identityId)") + } + + // Get AWS credentials + if let awsCredentialsProvider = session as? AuthAWSCredentialsProvider { + let credentials = try awsCredentialsProvider.getAWSCredentials().get() + // Do something with the credentials + } + + // Get cognito user pool token + if let cognitoTokenProvider = session as? AuthCognitoTokensProvider { + let tokens = try cognitoTokenProvider.getCognitoTokens().get() + // Do something with the JWT tokens + } +} catch let error as AuthError { + print("Fetch auth session failed with error - \(error)") +} catch { +} +``` +If you have enabled guest user in Cognito Identity Pool and no user is signed in, you will be able to access only identityId and AWS credentials. All other session details will give you an error. + +```swift +import AWSPluginsCore + +do { + let session = try await Amplify.Auth.fetchAuthSession() + + // Get identity id + if let identityProvider = session as? AuthCognitoIdentityProvider { + let identityId = try identityProvider.getIdentityId().get() + print("Identity id \(identityId)") + } + + // Get AWS credentials + if let awsCredentialsProvider = session as? AuthAWSCredentialsProvider { + let credentials = try awsCredentialsProvider.getAWSCredentials().get() + // Do something with the credentials + } +} catch let error as AuthError { + print("Fetch auth session failed with error - \(error)") +} catch { + print("Unexpected error: \(error)") +} +``` + +## Force refreshing session + +You can ask the plugin to force refresh the internal session by passing an api options `forceRefresh` while calling the fetchAuthSession api. + +```swift +Amplify.Auth.fetchAuthSession(options: .forceRefresh()) + +``` + From 7503ae7b0d8e5062cce8bc694f53c9324199dd73 Mon Sep 17 00:00:00 2001 From: salihgueler Date: Mon, 15 Apr 2024 14:54:58 +0300 Subject: [PATCH 2/5] Update the name and add managing credentials. --- src/directory/directory.mjs | 5 +- .../index.mdx | 0 .../auth/managing-credentials/index.mdx | 86 +++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) rename src/pages/[platform]/build-a-backend/auth/{access-credentials => accessing-credentials}/index.mdx (100%) create mode 100644 src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx diff --git a/src/directory/directory.mjs b/src/directory/directory.mjs index 99623b2fd82..2ac159450e1 100644 --- a/src/directory/directory.mjs +++ b/src/directory/directory.mjs @@ -62,7 +62,10 @@ export const directory = { path: 'src/pages/[platform]/build-a-backend/auth/set-up-auth/index.mdx' }, { - path: 'src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx' + path: 'src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx' }, { path: 'src/pages/[platform]/build-a-backend/auth/enable-sign-up/index.mdx' diff --git a/src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx similarity index 100% rename from src/pages/[platform]/build-a-backend/auth/access-credentials/index.mdx rename to src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx diff --git a/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx new file mode 100644 index 00000000000..cfd4fe3c178 --- /dev/null +++ b/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx @@ -0,0 +1,86 @@ +import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; + +export const meta = { + title: 'Manage credentials', + description: + 'Learn how to manage auth credentials for apps with Gen 2.', + platforms: [ + 'flutter', + ] +}; + +export const getStaticPaths = async () => { + return getCustomStaticPath(meta.platforms); +}; + +export function getStaticProps(context) { + return { + props: { + platform: context.params.platform, + meta + } + }; +} + + + +The Amplify Auth category persists authentication-related information to make it available to other Amplify categories and to your application. + +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](https://developer.apple.com/documentation/security/keychain_services/) on iOS and macOS and [EncryptedSharedPreferences](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences) on Android. + + + +Amplify will refresh the [Access Token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html) and [ID Token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html) as long as the [Refresh Token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-refresh-token.html) 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. + +```dart +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. + +```dart +await Amplify.addPlugin( + AmplifyAuthCognito(secureStorageFactory: InMemoryStorage.new), +); +``` + +```dart +class InMemoryStorage implements SecureStorageInterface { + InMemoryStorage(this.scope); + + /// The scope of the item being stored. + /// + /// This can be used as a namespace for stored items. + final AmplifySecureStorageScope scope; + + static final Map _data = {}; + + @override + void write({required String key, required String value}) { + _data['${scope.name}.$key'] = value; + } + + @override + String? read({required String key}) { + return _data['${scope.name}.$key']; + } + + @override + void delete({required String key}) { + _data.remove('${scope.name}.$key'); + } +} +``` + From 80b1cccc87a1b60c37840646792202e9412b82f1 Mon Sep 17 00:00:00 2001 From: Muhammed Salih Guler Date: Tue, 16 Apr 2024 16:01:31 +0300 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: josef --- .../build-a-backend/auth/managing-credentials/index.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx index cfd4fe3c178..98c8c556f4a 100644 --- a/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/managing-credentials/index.mdx @@ -28,9 +28,9 @@ The Amplify Auth category persists authentication-related information to make it 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](https://developer.apple.com/documentation/security/keychain_services/) on iOS and macOS and [EncryptedSharedPreferences](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences) on Android. - + -Amplify will refresh the [Access Token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html) and [ID Token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html) as long as the [Refresh Token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-refresh-token.html) is valid. Once the Refresh token expires, the user will need to reauthenticate to obtain a new one. +Amplify will refresh the [access token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html) and [ID token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html) as long as the [refresh token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-refresh-token.html) is valid. Once the refresh token expires, the user will need to reauthenticate to obtain a new one. From 645b66c3cd8cddeaf7237dd46b7830daf3065c0b Mon Sep 17 00:00:00 2001 From: salihgueler Date: Tue, 16 Apr 2024 16:13:33 +0300 Subject: [PATCH 4/5] Add the missing paragraphs. --- .../auth/accessing-credentials/index.mdx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx index 10ef4e366f5..f295b4234d1 100644 --- a/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx @@ -24,6 +24,10 @@ export function getStaticProps(context) { } +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: ```dart @@ -58,6 +62,10 @@ Future fetchCognitoAuthSession() async { ``` +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 casting the result of fetchAuthSession as follows: @@ -174,6 +182,10 @@ AuthFetchSessionOptions options = AuthFetchSessionOptions.builder().forceRefresh +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 casting the result of fetchAuthSession as follows: ```swift From fc74b37db44790649548462c488547d621c6eac7 Mon Sep 17 00:00:00 2001 From: Muhammed Salih Guler Date: Thu, 18 Apr 2024 23:28:58 +0300 Subject: [PATCH 5/5] Update src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx Co-authored-by: josef --- .../build-a-backend/auth/accessing-credentials/index.mdx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx b/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx index f295b4234d1..bc6cac4ac40 100644 --- a/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx +++ b/src/pages/[platform]/build-a-backend/auth/accessing-credentials/index.mdx @@ -43,10 +43,7 @@ Future fetchAuthSession() async { ### Retrieving AWS credentials -Sometimes it can be helpful to retrieve the instance of the underlying plugin -which has more specific typing. In the 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. +Sometimes it can be helpful to retrieve the instance of the underlying plugin which has more specific typing. In the 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. ```dart Future fetchCognitoAuthSession() async {