[Amazon Cognito] New feature: Original Identity Systems Supported



This post is English translation of “[Amazon Cognito] Facebook / Google / Amazon だけじゃない!独自の認証システムも利用可能になりました!” written by Yuki Suwa, an iOS and Android Developer at underscore, Inc.

Custom Identity Provider become available

Yesterday(9/30)、Developer Authenticated Identities became available for all mobile App Developers. This feature is provided by Amazon Cognito.

As an Identity Provider, AWS had supported Amazon, Facebook, and Google accounts so far. However, this update enables to use any Service Provider. If you have any authentication system besides, the authenticated users can use unique Identity ID and temporary AWS credentials.


So far, custom(separately developed) authentication system have been used to identify the uniqueness of the end user. Based on the system, authentication and authorization are proceeded.

In the recent years、the idea of Web identity has become general, thus the number of web services which authenticates the identity using the authentication system of Facebook, Google, Twitter and so on has increased. However, sometime you encounters problem of the Web identity system. For example, When you develop a mobile application which intends to be used for the limited number of users, you have to manage user identity by your own authentication system as Web Identity is available for all who owns the account of the public web services.

So far, such authentication cannot be handled by Amazon Cognito, but this update changed the situation.

How to use

The new feature enables to issue temporary AWS Credentials by using your own authentication system thus you need to implement a server-side authentication system. You can get Identity ID and Open ID connect token, which are issued by Cognito and temporary AWS credential can be received via STS by using these IDs.



You need to use the latest version of AWS SDK. example version are below:

  • AWS SDK for Java 1.8.11
  • AWS SDK for iOS 2.0.8
  • AWS SDK for Android 2.1.0


the following steps are required to get AWS Credentials using Cognito.

  1. Get access token of some Web Service
  2. Request Open ID token to your authentication system by passing the access token and Identity Pool ID as parameters.
  3. Get Cognito credentials based on the open ID Token acquired in the previous step.
  4. Now you can access AWS services by the Cognito credentials.


I chose Java as a Server-Side language、Android as client app.


As a first step, let's take a look at server-side implementation. You can get Open ID Connect Token by calling GetOpenIdTokenForDeveloperIdentity API. You can get Open ID connect Token tied with the request which includes userID issued by the original authentication system. It might be good to implement with the server side login logic and return the response toward client as an additional information.

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	BasicAWSCredentials credentials = new BasicAWSCredentials("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY");
	AmazonCognitoIdentityClient client = new AmazonCognitoIdentityClient(credentials);
	// Set user ID to CustomProvider
	HashMap<String, String> map = new HashMap<String, String>();
	map.put("CustomProvider", "userId");
	// Get Open ID Connect Token
	GetOpenIdTokenForDeveloperIdentityRequest tokenRequest = new GetOpenIdTokenForDeveloperIdentityRequest();
	// Identity Pool must be created prior to the execution.
	// set login inf
	// Duration of generated open ID connect token
	GetOpenIdTokenForDeveloperIdentityResult developerIdentityResult = client.getOpenIdTokenForDeveloperIdentity(tokenRequest);

	// return Open ID Connect Token

Client app implementation (Android)

You need to create custom provider class which extends AWSAbstractCognitoIdentityProvider abstract class. CognitoCachingCredentialsProvider used in this class handles your original provider as a identity provider for Cognito. refresh() method returns open ID connect token provided by the server program implemented formerly. getProviderName() method returns the name of your original service provider.

public class CognitoTask extends AsyncTaskLoader<Boolean> {

  private static final String accountId = "xxxxxxxxxxxx";
  private static final String poolId = "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
  private static final String unauthArn = "arn:aws:iam::xxxxxxxxxxxx:role/Cognito_CognitoSampleUnauth_DefaultRole";
  private static final String authArn = "arn:aws:iam::xxxxxxxxxxxx:role/Cognito_CognitoSampleAuth_DefaultRole";
  public CognitoTask(Context context) {

  public Boolean loadInBackground() {
    // generate STS instance
    AWSSecurityTokenServiceClient sts = new AWSSecurityTokenServiceClient(new AnonymousAWSCredentials());
    // generate CustomProvider
    AWSCognitoIdentityProvider provider = new CustomProvider(accountId, poolId);
    // Set userID
    HashMap<String, String> logins = new HashMap<String, String>();
    map.put("CustomProvider", "userId");
    // receive temporary AWS credential
    CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(getContext(), provider, unauthArn, authArn, sts);
    AWSSessionCredentials credentials = credentialsProvider.getCredentials();
    Log.d("credentials" , "accessKey:" + credentials.getAWSAccessKeyId());
    Log.d("credentials" , "secretKey:" + credentials.getAWSSecretKey());
    return true;
   * Implementation class of AWSAbstractCognitoIdentityProvider
  public class CustomProvider extends AWSAbstractCognitoIdentityProvider {

    public CustomProvider(String accountId, String identityPoolId) {
      super(accountId, identityPoolId);

    public String refresh() {
      return getOpenIDConnectToken();

    public String getProviderName() {
      // return provider name (decide any proper value)
      return "CustomProvider";
   * get Open ID connect token
   * @return Open ID Connect Token
  private String getOpenIDConnectToken() {
    String idToken = "";
    return idToken;

You may get the temporary AWS credential by the above step.

Client app implementation (iOS)

In addition to Android, I implemented iOS. The basic process of implementation is same as Android. You need to create the subclass of AWSAbstractIdentityProvider , then implement getIdentityId: method and refresh: method. The return value is BFTask, which is a task object of Bolts. Bolts You can call any callback by using BFTaskCompletionSource.


#import <AWSCore.h>

@interface CustomIdentityProvider : AWSAbstractIdentityProvider

@property (nonatomic, strong) AWSCognitoIdentity *cib;
@property (nonatomic, strong) NSString *accountId;
@property (nonatomic, strong) NSString *identityPoolId;
@property (nonatomic, strong) NSString *identityId;
@property (nonatomic, strong) NSString *token;



#import "CustomIdentityProvider.h"

@implementation CustomIdentityProvider

@synthesize accountId = _accountId;
@synthesize identityPoolId = _identityPoolId;
@synthesize identityId = _identityId;
@synthesize token = _token;

- (BFTask *)getIdentityId
    if (self.identityId) {
        // return BFTask if identityId is provided
        return [BFTask taskWithResult:nil];
    } else {
        // exec refresh if identityId is not provided
        return [[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) {
            if (!self.identityId) {
                return [self refresh];
            return nil;

- (BFTask *)refresh
    // get Open ID connect Token by the API request to authentication server
    NSURL *url = [NSURL URLWithString:@"YOUR_SERVER_API_URL"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
        if (data) {
            // retrieve identity ID and Open ID connect Token from the response.
            NSError *jsonError = nil;
            NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data
            NSLog(@"result: %@", result);
            self.identityId = result[@"identityId"];
            self.token = result[@"token"];
        } else {
           NSLog(@"error: %@", error);
    return ;


At last, the following code needs to be implemented. When you use iOS, set AWSServiceConfiguration to AWSServiceManager to retrieve AWS credentials.

static NSString* const kAccountId = "xxxxxxxxxxxx";
static NSString* const kIdentityPoolId = "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
static NSString* const kUnauthArn = "arn:aws:iam::xxxxxxxxxxxx:role/Cognito_CognitoSampleUnauth_DefaultRole";
static NSString* const kAuthArn = "arn:aws:iam::xxxxxxxxxxxx:role/Cognito_CognitoSampleAuth_DefaultRole";

// generate CustomIdentityProvider
CustomIdentityProvider *customIdentityProvider = [CustomIdentityProvider new];
customIdentityProvider.accountId = kAccountId;
customIdentityProvider.identityPoolId = kIdentityPoolId;
customIdentityProvider.logins = @{@"CustomProvider" : @"userId"};

// generate AWSCognitoCredentialsProvider
AWSCognitoCredentialsProvider *provider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1

// register AWS credential
AWSServiceConfiguration *configuration = [AWSServiceConfiguration configurationWithRegion:AWSRegionUSEast1
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;

// Authentication
[[provider getIdentityId] continueWithSuccessBlock:^id(BFTask *task){
    NSString* cognitoId = provider.identityId;
    NSLog(@"cognitoId: %@", cognitoId);
    NSLog(@"logins: %@", provider.logins);
    return nil;


At the moment of the release of Amazon Cognito, some developer said "Why Twitter isn't supported?". But I think this new feature of Cognito can spread the possibility of the mobile app further.