In my app, all the users start with an identityId from Cognito (directly got from Cognito/GetId from the app) and the authenticated users update the identityId through developer authentication (GetOpenIdTokenForDeveloperIdentity with old IdentityId set via developer side server). The authenticated users can logout/login anytime, but the developer side token changes once logged out or when the token expires.
What's the best way to manage to keep the same identityId for a user in the conditions above?
For instance: when the same user logs out then logs in.
What I need in this case is to associate to this user:
Calling GetOpenIdTokenForDeveloperIdentity( IdentityB , DEVDOMAIN: TokenB ) means creating a new user right? So should I...
Is there a better way?
Thanks.
EDIT:
TokenA / TokenB are access tokens for the developer side server API. They change every time the user logs in, they expire in 2 weeks.
The code I use for log out:
// Code in Logout
AWSCognitoCredentialsProvider* credentialsProvider = [AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider;
[credentialsProvider clearKeychain];
[[AWSCognito defaultCognito] wipe];
After login/logout, I'm updating the user's identityId this way:
AWSCognitoCredentialsProvider* credentialsProvider = [AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider;
NSString* previousIdToken = credentialsProvider.logins[IDPROVIDER_OURSERVICE];
if (previousIdToken == nil || ![idToken isEqualToString:previousIdToken])
{
if (idToken.length == 0)
{
// Logout
credentialsProvider.logins = @{ };
return [credentialsProvider getIdentityId];
}
else
{
// Login/Update
credentialsProvider.logins = @{ IDPROVIDER_OURSERVICE:idToken };
return [credentialsProvider refresh];
}
}
return [AWSTask taskWithResult:idToken];
I'm also running the following code on startup, to clear credentials when users reinstall the app (as uninstall = logout in my app)
// Initialization code
AppIdentityProvider* appIdentityProvider = [[AppIdentityProvider alloc] initWithRegionType:AWSRegionUSEast1
identityId:nil
accountId:COGNITO_ACOUNT_ID
identityPoolId:COGNITO_IDENTITY_POOL_ID
logins:logins];
AWSCognitoCredentialsProvider* credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
identityProvider:appIdentityProvider
unauthRoleArn:nil
authRoleArn:nil];
if ([AppContext sharedInstance].appInitRunCount == 1)
{
// Restart as guest after an uninstall
NSLog(@"=== AppUserManager: First run: clearing keychain");
[[AWSCognito defaultCognito] wipe];
[credentialsProvider clearKeychain];
}
AWSServiceConfiguration* configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1
credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
[[credentialsProvider getIdentityId] continueWithSuccessBlock:^id(AWSTask *task) {
[self testCognito];
return nil;
}];
My custom identity provider looks like this:
@interface AppIdentityProvider : AWSAbstractCognitoIdentityProvider
// ...
@end
@interface AppIdentityProvider ()
@property (nonatomic, strong, readwrite) NSString *token;
@end
@implementation AppIdentityProvider
@synthesize token = _token;
-(id)initWithRegionType:(AWSRegionType)regionType
identityId:(NSString*)identityId
accountId:(NSString*)accountId
identityPoolId:(NSString*)identityPoolId
logins:(NSDictionary*)logins
{
self = [super initWithRegionType:regionType
identityId:identityId
accountId:accountId
identityPoolId:identityPoolId
logins:logins];
if (self == nil)
return nil;
return self;
}
-(BOOL)isAuthenticatedWithOurService
{
return self.logins != nil && [self.logins objectForKey:IDPROVIDER_OURSERVICE] != nil;
}
- (AWSTask *)getIdentityId
{
if (self.identityId != nil)
return [AWSTask taskWithResult:self.identityId];
if (![self isAuthenticatedWithOurService])
return [super getIdentityId];
return [[AWSTask taskWithResult:nil] continueWithBlock:^id(AWSTask *task) {
if (self.identityId != nil)
return [AWSTask taskWithResult:self.identityId];
return [self refresh];
}];
}
- (AWSTask *)refresh
{
AWSTaskCompletionSource *source = [AWSTaskCompletionSource taskCompletionSource];
if (![self isAuthenticatedWithOurService])
return [super getIdentityId];
ApiRequest* authApi = [[ApiRequestManager sharedInstance] generateAuthApiByIdToken:self.logins[IDPROVIDER_OURSERVICE]];
[authApi requestAsyncCompletionHandler:^(ApiRequest *request)
{
NSDictionary *response = request.response;
if ([request hasSucceeded] && [[response valueForKey:@"result"] intValue] == 1)
{
self.token = [[response valueForKey:@"data"] valueForKey:@"token"];
self.identityId = [[response valueForKey:@"data"] valueForKey:@"identityId"];
[source setResult:self.identityId];
}
else
{
[source setError:[NSError errorWithDomain:@"refresh" code:0 userInfo:response]];
}
}];
return source.task;
}
@end
You should not use a randomly generated token which changes on sign in as a user identifier, if you want the user to always have the same identity id. We identify the user uniquely based on the identifier you pass us. For example, you can use the user name in the logins map when you call GetOpenIdTokenForDeveloperIdentity from your backend.
If we already have an identity generated for the identifier and that identity does not match the identity you passed in the request, we will merge these two along with their datasets.
More details about developer authenticated flow can be found in our dev guide .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.