Amazon Cognito Identity Pool can not be found - ios

I'm making an app that uploads photos to an S3 bucket using the AWS SDK with Amazon Cognito. When I run the function that does this I get an error in the console that says the Identity Pool [the id of my identity pool] can't be found. I've found a few solutions to this issue around the internet. However, none of them seem to work for me. Any ideas?

Assuming you have the correct identity pool id, you may not be connecting to the same region that the pool was created in. The region is the first portion of the identity pool id. Incorrect access policies will not cause this error. I caution against granting blanket access to your resources, if end users will only be reading and writing from s3, only provide that access, don't give them full access.

Make sure your ARN configuration for your Auth and Unauth are the full ARN

Each time I get this issue it is because the IAM role does not have permissions to view the pool OR the pool does not have Unauthenticated Identities
Add AmazonCognitoDeveloperAuthenticatedIdentities OR AmazonCognitoPowerUser to your IAM role
You will need some level of S3 access attached to your policy in the future to access S3.
Also, please add more information to your question. Code used, information about the pool set up, etc. Also, review my answer for Setting up Cognito
Edit:
Per #justderbā€™s comment - removed reference to AmazonS3FullAccess and updated appropriately.

Related

MS Graph API call getOffice365ActiveUserDetail() fails with HTTP 403 for Delegated permissions

Earlier i asked this question, where #Dev helped me. Now when i tried doing to Delegated permissions, its again throwing HTTP error 403. Application permission works for me. Only looks like issue with delegated permission. Strange? Any inputs will be of help.
#Alice, I see that you're using delegated permission scenario. If yes, then you need to allow apps to read service usage reports on behalf of a user. I would suggest you to work with your tenant administrator. They should have assigned the user the appropriate Azure AD limited administrator role - its needed, apart from the permissions that you specify in your code.
I tried the above in past and helped; so give a try. If you still face issues let me know. For more info you can refer the related document.

What am I doing wrong to get group.selected working in graph API?

I'm currently trying implement an app to read calendars only for a group that's permitted to the app. The idea behind this is that when I want to add a another calendar all I'd have to do is add the object to a specific o365 group. I'm taking the application approach over delegation that way I don't have anything actually logging in to utilize the app. Ultimately I'd like to stay away from any of the *.All permissions for security reasons.
Steps taken :
- created o365 group
- added resource objects and one user service account (just for testing) to the group
- registered app
- generated secret
- assigned group to the app
- granted admin consent to groups.selected via the azure portal
When I run a GET for group/{id}/members :
{'error': {'code': 'Authorization_RequestDenied', 'message': 'Insufficient privileges to complete the operation.', 'innerError': {'request-id': '473410a8-4db4-49d6-8d2c-92b9fbd4edb1', 'date': '2020-03-05T14:59:28'}}}
As per the docs
https://learn.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0&tabs=http
If you are using Application permissions to Get Members for a group. you will need User.Read.All, Group.Read.All, Directory.Read.All.
The usual issue is not granting that permissions to the application in Portal.azure.com and admin consenting it.
If you're confident with that. Then I'd eliminate your code as being the issue by using something like postman with your app id and client secret. We have a sample Postman collection here https://learn.microsoft.com/en-us/graph/use-postman . for delegated permissions you can use our Graph Explorer playground.
MS docs says:
Note: This permission is exposed in the Azure portal for a feature that is not available for general use. Do not use this permission as it is subject to change.
https://learn.microsoft.com/en-us/graph/permissions-reference

Properly adding permissions to MS Graph API to enable an app to delete users after logging in with admin account

I am writing a .Net Core 2.0 MVC-like app where users log in and then do such operations on an AAD B2C tenant such as add new user, edit user, delete user etc.
Listing and adding users was pretty easy to do, but now when I try to remove certain users, I get a 403 Forbidden error. I'm assuming it's because I missed permissions somewhere, but I don't really know where.
I have enabled literally ALL possible App permissions in my AAD B2C Tenant b2c-extensions-app and most of the ones that sound right (30 app+30 delegated) in apps.dev.microsoft.com. I added the account I log in to test to owner list, too. Any clues on why I keep getting those errors would be much appreciated. What are the things I could have missed?
// I found out that to delete users, Directory.AccessAsUser.All is required. I already have it in delegated permissions but I keep getting the same error.
// Yes, I did add myself as owner to b2c-extensions-app and I also added literally every possible permission to it. Windows Azure Active Directory has 7+9, Microsoft Graph has 37+78.
// Okay it seems that the same error occurs when I try to edit a user's password (or any contents, really), too.
Did you setup your permissions through Azure portal or PowerShell?
Delete permissions for a B2C application must be created using PowerShell.
You can find instructions on this page of Microsoft Docs, under the section 'Configure delete permissions for your application'.
Let me know if it helped!

iOS - AWS Cognito - "NotAuthorizedException" - Logins don't match

For some reason an account which I've registered using my app and tested before is now giving me an error when trying to log in using its details: "Logins don't match. Please include at least one valid login for this identity or identity pool."
I know the values I am using for it are definitely correct and other accounts are still able to login. What could be the cause of this error?
Any help would be greatly appreciated.
What the SDK is trying to tell you is that the identityId in your Federated Identity Pool (and which may be stored in a keychain in your device, and which may be re-established on restart from an existing session) does not match the login in your authentication provider which was returned by the "logins" method.
This can happen in a number of different ways, but this usually occurs because you attempt to log in as another user on the same authentication provider without first logging out.
The SDK recovers by retrying.
(This recovery does not really work because I think it takes 2 or 3 attempts to time out, and the recovery then leaves you in a state where subsequent logins fail with the same error. Restarting the app clears this. I have not fully investigated the defect in the retry/recovery process)
The solution is to prevent the app from logging in on a different ID with the same authentication provider (IdP) without first logging out of that authentication provider.

AWS web and mobile hub application

On AWS, I wish to create an application that allows a user to sign in via mobile, web or both.
I created a system using API Gateway, Lambdas and DynamoDB for the back end. I have sign in working for web using JavaScript but was having issues finding a Swift example for iOS of the same code (objective C only available). So I created a mobile hub application, imported my existing API and have a working iOS sign in.
The issue is that the iOS side uses the Mobile Hub so I now have 2 different User Pools so you can't sign up on web and log in on mobile (or vice versa).
I tried to change the settings in the iOS app to point to my web app Cognito User Pool settings and remove the secret but it errors as it can not be null or empty.
Why does the mobile hub require a client secret? The JavaScript documentation suggested was bad practice since code can be de-compiled and the secret extracted.
There doesn't seem to be any consistent documentation that explains, what I would guess, as the most common use case of a mobile and web app!
The other issue is that I can download my API client SDK for my API Gateway for use with web app and iOS app. But, the generated mobile hub app includes a REST based call? Am I going crazy here or does the official web approach not link to the official mobile approach?
So the key questions are:
Can or should I change the mobile apps to point at the original
Cognito?
if so should I remove the client secret?
can I effectively ignore the Mobile Hub after set up and use it purely for code generation? Assuming it was then working can I just use the generated client SDK for my API Gateway?
Is there a better way of setting up an iOS (later Android too) and web app?
I've spent considerable time and effort, and tried many approaches.
The "Mobile Hub" nicely sets up the user pool, identity pool, IAM roles etc.
The keys etc are mostly provided in the Info.plist file, although ( unwisely ) the developers of the user pool AWSSignInProvider made it have hardcoded keys in a configuration file.
SO:
If you don't intend to use the "Mobile Hub" console application for making changes to your mobile app configuration, then you won't need any more downloads. In that case, you don't have to worry about changes to Info.plist or the configuration file, and you can edit what you want.
It is unclear if you are going to use the mobile hub created identity pool and just want to insert your user pool, or if you want to change both pools. Obviously if you are using the same identity pool then some of the changes below will not be needed (they will be obvious because you will be changing them to be exactly the same).
So all you have to do is change the ID's to get everything hooked up correctly.
In general you need to fix all the downloaded keys and ID's in Info.plist and the configuration file, and then you need to update the server configuration. In more detail, here are the places you need to change it:
in the app:
update all the keys in Info.plist to be the keys you want. (specifically credentials provider and identity manager keys for google) But if you are using other mobile hub services, check the keys there too.
If you are using s3, and some of the other services the directory names/database names are also stored in the code... I leave it as an activity to find them.
in the file MySampleApp->AmazonAWS->AWSConfiguration.swift edit the keys provided by Mobile hub to match your user pool (do this while quietly swearing under your breath because they are not in Info.plist)
in the console:
put your app name in your user pool APP's list if it is not there, and record the user pool id, app id, and app secret.
click on federated identities and the identity pool created by mobile hub and update the authentication provider to use your cognito user pool id and app id.
if you are changing the identity pool too, then you will need to look at the IAM Roles for your auth and unauth users and specifically edit the policy that is named: .....yourapp....signin_MOBILEHUB_xxxxxxx, and change the identity pool id in that policy to be the one you want to use. Do this for both auth and unauth.
( you can change the id if you only use one pool, or add another to a list of id's like this if you will have multiple identity pools (for test...etc))
"Resource": [
"arn:aws:cognito-identity:*:*:identityPool/us-east-1:8s8df8f8-sd9fosd9f0sdf-999sd99fd",
"arn:aws:cognito-identity:*:*:identityPool/us-east-1:dfsf9099-sd9fosd9f0sdf-sd9f0sdf09f9s"
]
similarly, in the trust relationship associated with the roles, you need to fix the id's, (or handle multiple ID's if you want the role to serve multiple identity pools). Here is how to specify multiple id's there.
"Condition": {
"ForAllValues:StringLike": {
"cognito-identity.amazonaws.com:aud": [
"us-east-1:8s8df8f8-sd9fosd9f0sdf-999sd99fsdfdd",
"us-east-1:dfsf9099-sd9fosd9f0sdf-sd9f0sdf09f9s"
]
},
if you are using google too... you need to make sure that you have an identityProvider in the IAM configuration for google (mobile hub did that for you) and if you are using your own identity pool , in your federated identity pool authorization providers configuration you will need to select google open id provider (and put google in the authorized providers too (but I don't think this part is strictly needed))
facebook doesnt use OpenID Connect, it has a proprietary way of configuring into the authentication providers section, so enter those keys if needed in the identity pool authentication providers section.
And that should be enough to make it work.
And no you are not going crazy... the documentation does not match the current IOS SDK. Mobile hub uses the aws-mobilehub-helper-ios (github) which is built on TOP of the sdk, so the documentation does not apply to that either! Mobile Hub Helper has a nice design, so I recommend you use it, rather than the raw SDK.
(and lastly... and I am out of my depth here because I don't use API gateway, but my understanding was that the API Gateway is a way to get credentials to use AWS Services, and with the mobile hub app you will be using Cognito to get those credentials, so I am not sure you will need to bring the API Gateway into it...at all)
UPDATE
You may want to use no client secret for users of your javascript app, and use a IOS Mobile App on the same pool too. This can be done in two ways:
1) The better way is that you create two different client's in the user pool. For one you will generate a client secret, for the other you will UNCHECK the "generate client secret" box.
Then in your Federated Identity Pool you go to Authentication Providers, and click on Cognito, and specify TWO DIFFERENT PROVIDERS USING THE SAME USER POOL ID. (This is not really two different providers, but that is how the console makes you specify it). And you put the two different client ids in those providers.
Now both the IOS app and the Javascript app can access the pool and get authentication and credentials from the identityProvider and credentialsProvider.
2) A not so good way. The reason this way is worse is because I don't know the impact (if any) it has on the security of your mobile app. And at AWS there is nobody to ask the question to without buying a support contract. But the other way exists.
What you do is use the same client id in both apps, and you don't generate a client secret. To do this you put "nil" in the clientSecret. This works fine with some caveats.
First, the AWS Mobile Hub has a bug in it's AWSCognitoUserPoolsSignInProvider. That class requires that the clientSecret is non-null. But in the SDK, the only way to tell the SDK that you want no client secret is to pass nil! However there are workarounds.
(What I did was use the AWSCUPIdPSignInProvider.swift (that I wrote), which will work fine and I have a version that will take a nil for the secret. I did that because it was faster for me to test this out. you can find that signin provider on github if you want to use it)
But a better (more future proof) solution is probably to use the AWSCognitoUserPoolsSignInProvider that the mobile hub delivers, but change the code in AWSMobileClient to configure and register your own pool rather than letting AWSCognitoUserPoolsSignInProvider do it for you.
I haven't bothered to try this, (because we only have to do it because AWS has not gotten around to updating the github aws-mobilehub-helper-ios yet). But basically in AWSMobileClient instead of this code:
func setupUserPool() {
// register your user pool configuration
AWSCognitoUserPoolsSignInProvider.setupUserPoolWithId(AWSCognitoUserPoolId, cognitoIdentityUserPoolAppClientId: AWSCognitoUserPoolAppClientId, cognitoIdentityUserPoolAppClientSecret: AWSCognitoUserPoolClientSecret, region: AWSCognitoUserPoolRegion)
AWSSignInProviderFactory.sharedInstance().registerAWSSignInProvider(AWSCognitoUserPoolsSignInProvider.sharedInstance(), forKey:AWSCognitoUserPoolsSignInProviderKey)
}
you would have something like this code
func setupUserPool() {
// register your user pool configuration
// find the service configuration (we don't know if they set it as default)
let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1 (or your region), identityPoolId: "YourIdentityPoolId")
let configuration = AWSServiceConfiguration(region: .USWest2 (or your region), credentialsProvider: credentialProvider)
// configure and put your own user pool in the service configuration
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: AWSCognitoUserPoolAppClientId, clientSecret: nil, poolId:AWSCognitoUserPoolId)
// now we register that pool with the service configuration using the key they use
AWSCognitoIdentityUserPool.register(with: configuration, userPoolConfiguration: userPoolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
AWSSignInProviderFactory.sharedInstance().registerAWSSignInProvider(AWSCognitoUserPoolsSignInProvider.sharedInstance(), forKey:AWSCognitoUserPoolsSignInProviderKey)
}
But as I said above, solution 1, use two different clients and specify two different providers is preferred.

Resources