AWS CognitoID VS AWS Session Token - ios

I'm a bit confused about the difference between an AWS session token and an AWS CognitoID, are they they same? because through this code
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:AWSRegionUSEast1
identityPoolId:#"my-identity-pool"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSUnknown credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
[[credentialsProvider getIdentityId] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"Error: %#", task.error);
}
else {
// the task result will contain the identity id
NSString *cognitoId = task.result;
// -------------------Outputs cognito Id------------------------
NSLog(#"%#,", task.result);
}
return nil;
}];
task.result gives back an AWS CognitoID but what about an AWS Session Token? How can I get it from my ios?

Amazon Cognito IdentityId is not the same as AWS temporary credentials. AWS temporary credentials consist of accessKey, secretKey, and sessionKey. AWSCognitoCredentialsProvider has properties with these names. See the API doc for more details.
In general, if you are using any AWS service clients in the AWS Mobile SDK for iOS, you do not need to retrieve the AWS temporary credentials manually. The SDK automatically retrieves them when it needs them.

Related

Why is AWS EC2 not working on iOS and MacOS?

So basically I'm writing a tool for managing some EC2 instances, nothing special.
I managed to get some AWS framework to build for MacOS (incredible that it is not officially supported) and I'm now trying to use the describeInstances() request of the framework.
I always get the same error : Domain=com.amazonaws.AWSEC2ErrorDomain Code=0
I've tried the same code on iOS, same issue.
I've tried on a python script, using the Boto3 library, and no problem here, the function returns my instances and the descriptions.
I already use AWSS3 and AWSSNS on the same MacOS project, with no issue.
I have my policies set on IAM, for EC2 set on "fullAccess"
Here's the code:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:AWSRegionUSEast1
identityPoolId:kPoolID];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
AWSEC2 *ec2 = [AWSEC2 defaultEC2];
AWSEC2DescribeInstancesRequest *request = [AWSEC2DescribeInstancesRequest new];
[ec2 describeInstances:request completionHandler:^(AWSEC2DescribeInstancesResult * _Nullable response, NSError * _Nullable error) {
if(error){
NSLog(#"%# = %#", #"EC2 describe Error", error);
}else{
NSLog(#"%# = %#", #"EC2 describe Response", response);
}
}];
Can anyone help me with this?
For some reason EC2 does not want to take the cognito pool is as a form of authentication, I had to connect using access and secret key to make it work.

Getting InvalidIdentityPoolConfigurationException when Retriving records from AWS DynamoDB iOS

I have used AWS DynamoDB in my app. i am using AWSDynamoDBObjectMapper for fetching records from database but getting InvalidIdentityPoolConfigurationException every time. i have set poolId and region in info.pilist,
Following is my code,
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
identityPoolId:IDENTITY_POOL_ID];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast2
credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
AWSDynamoDBObjectMapperConfiguration *objectMapperConfiguration = [[AWSDynamoDBObjectMapperConfiguration alloc] init];
[AWSDynamoDBObjectMapper registerDynamoDBObjectMapperWithConfiguration:configuration objectMapperConfiguration:objectMapperConfiguration forKey:#"USEast1DynamoDBObjectMapper"];
_dynamoDBObjectMapper = [AWSDynamoDBObjectMapper DynamoDBObjectMapperForKey:#"USEast1DynamoDBObjectMapper"];
return YES;
}
DynamoDBManager.m
+(void)loginWithFaceBook:(NSString*)fbId{
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
scanExpression.filterExpression = #"facebook_id = :val";
scanExpression.expressionAttributeValues = #{#":val":fbId};
[[AppContext.dynamoDBObjectMapper scan:[dynamo_user class]
expression:scanExpression]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"The request failed. Error: [%#]", task.error);
} else {
// AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
NSLog(#"The request sucesss. Result : [%#]", task.result);
}
return nil;
}];
}
MyViewController.m
[DynamoDBManager loginWithFaceBook:[result valueForKey:#"id"]];
Following s my error:
The request failed. Error: [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=5 "(null)" UserInfo={__type=InvalidIdentityPoolConfigurationException, message=Invalid identity pool configuration. Check assigned IAM roles for this pool.}]
Can anyone having idea about the above error? is any configuration missing in above code?
1. Adding Facebook as an authentication provider in Cognito Console.
I can see that you are using Facebook for authentication. In AWS Cognito Console, when creating the identity pool, you have to add Facebook App ID under "Authentication Providers" -> "Facebook"
2. Adding the sufficient permissions and roles.
Once the pool is created, you have to attach a Role with the Identity pool and the Role should have the sufficient IAM privileges.
For example, if you want to perform a query, the policy document of the role that is attached to the Identity pool should have the following lines:
"Action": [
"dynamodb: Query"
]
You have to add the appropriate actions for the DynamoDB operations you want to perform.

Creating a private Amazon API Gateway

I want to create an api for my app that is only accessible by my app. I have added the AWS Cognito identity to my appDelegate like so:
AWSCognitoCredentialsProvider *credentialsProvider = [[DeveloperAuthenticationProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#"poolId"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
__block NSString *cognitoId = nil;
// Retrieve your Amazon Cognito ID
[[credentialsProvider getIdentityId] continueWithBlock:^id(AWSTask *task)
{
if (task.error)
{
NSLog(#"Error: %#", task.error);
}
else
{
// the task result will contain the identity id
cognitoId = task.result;
}
return nil;
}];
How do I use this gonitoId that gets returned to make sure that this is the only app with the id that can access my api? Do I need to save this id and use it when accessing the api?
Thanks.
Securing the API with 'AWS_IAM' authorization will require that requests are signed with credentials in the same AWS account. Past that, if you are in control of the account then you should be able to ensure that only the Cognito roles have access by setting a fine-grained policy with the API Gateway actions and resources.
http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html#api-gateway-calling-api-permissions
The app should be receiving Cognito credentials when authenticated so you'll use in the API Gateway SDK. The generated SDKs are available in iOS Android and JavaScript.
http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-generate-sdk.html

How do I integrate cognito user pool with identity pool?

I'm practicing with the CognitoUserPoolsSample iOS Obj-C app and trying to add integration with Cognito Identity. I've set up a user pool and an identity pool with the user pool set up as an authentication provider for the identity pool. The user pool is working fine, but the users are not showing up in the identity pool.
Here's what I have in applicationDidFinishLaunchingWithOptions:
//setup service config
AWSServiceConfiguration *serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil];
//Configure user pool
AWSCognitoIdentityUserPoolConfiguration *userPoolConfiguration = [[AWSCognitoIdentityUserPoolConfiguration alloc] initWithClientId:#"CLIENT_ID" clientSecret:#"CLIENT_SECRET" poolId:#"POOL_ID"];
[AWSCognitoIdentityUserPool registerCognitoIdentityUserPoolWithConfiguration:serviceConfiguration userPoolConfiguration:userPoolConfiguration forKey:#"UserPool"];
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:#"UserPool"];
//configure identity pool
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:AWSRegionUSEast1
identityPoolId:#"IDENTITY_POOL_ID"
identityProviderManager:pool];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
Is this correct so far? What is the next step from here? How come when I sign up a new user it doesn't show up in the identity pool? The identity pool console shows zero identities created.
Hi The key thing here to understand is that when you call:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:AWSRegionUSEast1
identityPoolId:#"IDENTITY_POOL_ID"
identityProviderManager:pool];
The AWS framework will set everything up for you, and the cognito User Pool and integration with federated identity will work seamelessyly.
A key note which I initally overlooked is here: http://docs.aws.amazon.com/cognito/latest/developerguide/getting-credentials.html
[[credentialsProvider getIdentityId] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"Error: %#", task.error);
}
else {
// the task result will contain the identity id
NSString *cognitoId = task.result;
}
return nil;
}];
Which forces a refresh of your credentials from the server. Objects contained on the user and also the session can be used to confirm the login and associated cognito id, and sessions tokens.
Be careful not to also use MobileHubHelper with the above code. As the mobile HUB Helper will destroy all of that.
You need to supply the token from Cognito user pools to the Cognito federated identity service. This is exactly how you would integrate Facebook or Google or any other provider with Federated Identity service.
This dev guide page and blog post go over this process in details.

How do you include a password for Amazon DynamoDB access in iOS?

A part of my iOS app needs to save users' email addresses in a central database. I've elected to use Amazon DynamoDB. I don't need each app user to have their own credentials, I just would like to have one username/password for the app itself to write back to the database.
Using the Amazon sample code, I put this in the app delegate:
AWSCognitoCredentialsProvider *credentialsProvider = [AWSCognitoCredentialsProvider credentialsWithRegionType:CognitoRegionType
identityPoolId:CognitoIdentityPoolId];
AWSServiceConfiguration *configuration = [AWSServiceConfiguration configurationWithRegion:DefaultServiceRegionType
credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
Created a full access role in IAM Manager, then use the following code to write to the database:
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
NSString *uuid = [[NSUUID UUID] UUIDString];
NSString *emailAddress = ([self.emailAddress.text length]>0)?self.emailAddress.text:#"a#b.com";
EaSLIEmailList *emailListItem = [EaSLIEmailList new];
emailListItem.UUID = uuid;
emailListItem.EmailAddress = emailAddress;
NSMutableArray *tasks = [NSMutableArray array];
[tasks addObject:[dynamoDBObjectMapper save:emailListItem]];
[[BFTask taskForCompletionOfAllTasks:tasks]
continueWithExecutor:[BFExecutor mainThreadExecutor] withBlock:^id(BFTask *task) {
if (task.error) {
NSLog(#"Error: [%#]", task.error);
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return nil;
}];
This works absolutely fine, but I'm not sure that this is secure. I thought I should create a user and password to embed in the app.
I'd appreciate anyone's guidance on the best and simplest way to do this.
(My concern was that if I don't do this, then someone could access the database without going through the app).
Your backend could call the AWS Security Token Service to generate temporary credentials, which you then pass to the mobile device. These credentials could be assigned permissions to only specific items in DynamoDB (so even if the credentials were compromised, they would not reveal any other data).

Resources