amplify-swift
amplify-swift copied to clipboard
feat(auth): Keychain Sharing (No App Reload Required)
Issue #
https://github.com/aws-amplify/amplify-swift/issues/2508 https://github.com/aws-amplify/amplify-swift/issues/3277
Description
This allows Amplify Swift developers to set the access group they would like the auth session to be shared on. This PR, as opposed to this PR, does not require the other app with which the auth session is being shared with to be reloaded. This helps immensely when writing a product with app extensions.
Changes made
AWSCognitoCredentialAuthCredentialStore
now uses access group to create keychain instance with said access group.
If an access group is specified:
- a different keychain service is used, specifically for shared items.
-
fetchAuthSession
reconfigures the plugin when called, so that app reload is not required
Migration:
- Amplify developers can specify if they want migration to happen by setting the
migrateKeychainItemsOfUserSession
totrue
within theaccessGroup
struct - migration involves moving any auth keychain items from the old access group (old access group name is stored in
UserDefaults
) to the new access group - migration is a batched operation, and the items will no longer be accessible from the old access group
Usage
Migrating to a Shared Keychain
To use a shared keychain:
- In Xcode, go to Project Settings → Signing & Capabilities
- Click +Capability
- Add Keychain Sharing capability
- Add a keychain group
- Repeat for all apps for which you want to share auth state, adding the same keychain group for all of them
To move to the shared keychain using this new keychain access group, specify the accessGroup
parameter when instantiating the AWSCognitoAuthPlugin
. If a user is currently signed-in, they will be logged out when first using the access group:
let accessGroup = AccessGroup(name: "\(teamID).com.example.sharedItems")
let secureStoragePreferences = AWSCognitoSecureStoragePreferences(
accessGroup: accessGroup)
try Amplify.add(
plugin: AWSCognitoAuthPlugin(
secureStoragePreferences: secureStoragePreferences))
try Amplify.configure()
If you would prefer the user session to be migrated (which will allow the user to continue to be signed-in), then specify the migrateKeychainItemsOfUserSession
boolean in the AccessGroup
struct to be true like so:
let accessGroup = AccessGroup.none(migrateKeychainItemsOfUserSession: true)
let secureStoragePreferences = AWSCognitoSecureStoragePreferences(
accessGroup: accessGroup)
try Amplify.add(
plugin: AWSCognitoAuthPlugin(
secureStoragePreferences: secureStoragePreferences))
try Amplify.configure()
Sign in a user with any sign-in method within one app that uses this access group. After reloading another app that uses this access group, the user will be signed in. Likewise, signing out of one app will sign out the other app after reloading it.
Migrating to another Shared Keychain
To move to a different access group, update the name parameter of the AccessGroup
to be the new access group. Set migrateKeychainItemsOfUserSession
to true
to migrate an existing user session under the previously used access group.
Migrating from a Shared Keychain
If you’d like to stop sharing state between this app and other apps, you can set the access group to be AccessGroup.none
or AccessGroup.none(migrateKeychainItemsOfUserSession: true)
if you’d like the session to be migrated.
General Checklist
- [x] Added new tests to cover change, if needed
- [x] Build succeeds with all target using Swift Package Manager
- [x] All unit tests pass
- [x] All integration tests pass
- [x] Security oriented best practices and standards are followed (e.g. using input sanitization, principle of least privilege, etc)
- [x] Documentation update for the change if required
- [x] PR title conforms to conventional commit style
- [x] New or updated tests include
Given When Then
inline code documentation and are named accordinglytestThing_condition_expectation()
- [x] If breaking change, documentation/changelog update with migration instructions
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.