AWS Cognito - 如何更新经过开发人员身份验证的用户令牌?
AWS Cognito - How to update developer authenticated users token?
在我的应用程序中,所有用户都以来自 Cognito 的 identityId(直接从应用程序的 Cognito/GetId 获得)开始,经过身份验证的用户通过开发人员身份验证更新 identityId(GetOpenIdTokenForDeveloperIdentity,旧的 IdentityId 通过开发人员设置服务器)。
经过身份验证的用户可以随时 logout/login,但开发人员端令牌会在注销或令牌过期后更改。
在上述情况下,为用户保持相同 identityId 的最佳方法是什么?
例如:当同一用户注销然后登录时。
- 用户第一次运行应用。他获得 IdentityA 作为未经身份验证的 identityId,登录为空。他在 DatasetA.
上保存了一些数据
- 用户使用USER/PASSWORD登录。他获得 {"DEVDOMAIN":"TokenA"} 作为登录名。 GetOpenIdTokenForDeveloperIdentity(IdentityA, DEVDOMAIN:TokenA) links 他们,用户使用 IdentityA[=82 进行身份验证=] 和 DatasetA 被保留。
- 用户注销。他得到未经验证的 IdentityB,logins/dataset 为空。他在 DatasetB.
上保存了一些数据
- 用户使用USER/PASSWORD登录。他获得 {"DEVDOMAIN":"TokenB"} 作为登录名。
在这种情况下我需要关联到这个用户:
- 最新代币TokenB.
- 以同一用户身份访问 AWS 的 IdentityId。
- DatasetB 合并到 DatasetA.
调用 GetOpenIdTokenForDeveloperIdentity(IdentityB, DEVDOMAIN:TokenB) 意味着创建一个新用户对吗?
那我应该...
- 在开发者端数据库中保存当前在 Cognito 上注册的用户令牌 (tokenA) 和第一个不会更改的 identityId (identityA )
- 调用GetOpenIdTokenForDeveloperIdentity(IdentityB,DEVDOMAIN:TokenB)临时linkIdentityB 和 TokenB
- 然后调用 MergeDeveloperIdentities(TokenB to TokenA)(我希望这会合并数据集...)
- 也许调用 DeleteIdentities(IdentityB) 因为它永远不会被使用?
- 然后告诉应用"you are IdentityA"
有没有更好的方法?
谢谢。
编辑:
TokenA / TokenB 是开发者端服务器 API 的访问令牌。
每次用户登录时它们都会更改,它们将在 2 周后过期。
我使用的登出密码:
// Code in Logout
AWSCognitoCredentialsProvider* credentialsProvider = [AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider;
[credentialsProvider clearKeychain];
[[AWSCognito defaultCognito] wipe];
在 login/logout 之后,我将以这种方式更新用户的 identityId:
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];
我还在 运行 启动时使用以下代码,以在用户重新安装应用程序时清除凭据(因为在我的应用程序中卸载 = 注销)
// 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;
}];
我的自定义身份提供商如下所示:
@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
如果您希望用户始终具有相同的身份 ID,则不应使用在登录时更改的随机生成的令牌作为用户标识符。我们根据您传递给我们的标识符唯一地识别用户。例如,您可以在从后端调用 GetOpenIdTokenForDeveloperIdentity 时使用登录映射中的用户名。
如果我们已经为标识符生成了一个身份,并且该身份与您在请求中传递的身份不匹配,我们会将这两个与其数据集合并。
有关开发人员身份验证流程的更多详细信息,请参阅 our dev guide。
在我的应用程序中,所有用户都以来自 Cognito 的 identityId(直接从应用程序的 Cognito/GetId 获得)开始,经过身份验证的用户通过开发人员身份验证更新 identityId(GetOpenIdTokenForDeveloperIdentity,旧的 IdentityId 通过开发人员设置服务器)。 经过身份验证的用户可以随时 logout/login,但开发人员端令牌会在注销或令牌过期后更改。
在上述情况下,为用户保持相同 identityId 的最佳方法是什么?
例如:当同一用户注销然后登录时。
- 用户第一次运行应用。他获得 IdentityA 作为未经身份验证的 identityId,登录为空。他在 DatasetA. 上保存了一些数据
- 用户使用USER/PASSWORD登录。他获得 {"DEVDOMAIN":"TokenA"} 作为登录名。 GetOpenIdTokenForDeveloperIdentity(IdentityA, DEVDOMAIN:TokenA) links 他们,用户使用 IdentityA[=82 进行身份验证=] 和 DatasetA 被保留。
- 用户注销。他得到未经验证的 IdentityB,logins/dataset 为空。他在 DatasetB. 上保存了一些数据
- 用户使用USER/PASSWORD登录。他获得 {"DEVDOMAIN":"TokenB"} 作为登录名。
在这种情况下我需要关联到这个用户:
- 最新代币TokenB.
- 以同一用户身份访问 AWS 的 IdentityId。
- DatasetB 合并到 DatasetA.
调用 GetOpenIdTokenForDeveloperIdentity(IdentityB, DEVDOMAIN:TokenB) 意味着创建一个新用户对吗? 那我应该...
- 在开发者端数据库中保存当前在 Cognito 上注册的用户令牌 (tokenA) 和第一个不会更改的 identityId (identityA )
- 调用GetOpenIdTokenForDeveloperIdentity(IdentityB,DEVDOMAIN:TokenB)临时linkIdentityB 和 TokenB
- 然后调用 MergeDeveloperIdentities(TokenB to TokenA)(我希望这会合并数据集...)
- 也许调用 DeleteIdentities(IdentityB) 因为它永远不会被使用?
- 然后告诉应用"you are IdentityA"
有没有更好的方法?
谢谢。
编辑:
TokenA / TokenB 是开发者端服务器 API 的访问令牌。 每次用户登录时它们都会更改,它们将在 2 周后过期。
我使用的登出密码:
// Code in Logout
AWSCognitoCredentialsProvider* credentialsProvider = [AWSServiceManager defaultServiceManager].defaultServiceConfiguration.credentialsProvider;
[credentialsProvider clearKeychain];
[[AWSCognito defaultCognito] wipe];
在 login/logout 之后,我将以这种方式更新用户的 identityId:
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];
我还在 运行 启动时使用以下代码,以在用户重新安装应用程序时清除凭据(因为在我的应用程序中卸载 = 注销)
// 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;
}];
我的自定义身份提供商如下所示:
@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
如果您希望用户始终具有相同的身份 ID,则不应使用在登录时更改的随机生成的令牌作为用户标识符。我们根据您传递给我们的标识符唯一地识别用户。例如,您可以在从后端调用 GetOpenIdTokenForDeveloperIdentity 时使用登录映射中的用户名。
如果我们已经为标识符生成了一个身份,并且该身份与您在请求中传递的身份不匹配,我们会将这两个与其数据集合并。
有关开发人员身份验证流程的更多详细信息,请参阅 our dev guide。