i try to Accessing aws Services Using an Identity pool after Sign-in by this aws Doc
https://docs.aws.amazon.com/en_us/cognito/latest/developerguide/amazon-cognito-integrating-user-pools-with-identity-pools.html
but in Integrating a User Pool with an Identity Pool part,
i can't add the token in the swift code
let serviceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: nil)
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: "YOUR_CLIENT_ID", clientSecret: "YOUR_CLIENT_SECRET", poolId: "YOUR_USER_POOL_ID")
AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: "UserPool")
let pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YOUR_IDENTITY_POOL_ID", identityProviderManager:pool)
In javascript and android both have credentialsProvider.logins .
i got the message like this:
Message: The security token included in the request is invalid.
or i need to call aws sts api by this doc?
https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/id_credentials_temp_request.html
Thanks for help.
first i try this
let identity = AWSCognitoIdentity.default()
let input = AWSCognitoIdentityGetCredentialsForIdentityInput()
input?.identityId = identityid
input?.logins = ["cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXX":identityToken]
identity.getCredentialsForIdentity(input!).continueWith(block: { (task:AWSTask<AWSCognitoIdentityGetCredentialsForIdentityResponse>) -> Any? in
if (task.error != nil) {
print("Error: " + task.error!.localizedDescription)
}
else {
self.accessKey = (task.result?.credentials?.accessKeyId)!
self.secrectKey = (task.result?.credentials?.secretKey)!
self.sessionToken = (task.result?.credentials?.sessionToken)
}
return task;
})
but it's not work, i'm not sure what happen. i use https to get aws iot shadow, it will return null value and get 403 message.
then i change the official doc code like this
let serviceConfiguration = AWSServiceConfiguration(region: .USEast1,credentialsProvider: nil)
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: "YOUR_CLIENT_ID", clientSecret: "YOUR_CLIENT_SECRET", poolId: "YOUR_USER_POOL_ID")
AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: "UserPool")
let pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "YOUR_IDENTITY_POOL_ID", identityProviderManager:pool)
then use this code
credentialsProvider.credentials().continueWith(block: { (task) -> AnyObject? in
if (task.error != nil) {
print("Error: " + task.error!.localizedDescription)
}
else {
let credentials = task.result!
self.accessKey = credentials.accessKey
self.secrectKey = credentials.secretKey
self.session = credentials.sessionKey! }
return task;
})
but this code is not use idtoken i got from cognito login, maybe this just let me access service, then i can parse the idtoken to get the idtoken detail message.
hope this will help to someone.
in addition to this, the import things is to attachPrincipalPolicy you temporary credential with iot, when you login cognito, you will get credential identityID,
then used this identityID to attach.
or you will get 403 forbidden, and a null return values.
FYR
https://github.com/awslabs/aws-sdk-ios-samples/blob/master/IoT-Sample/Swift/IoTSampleSwift/ConnectionViewController.swift
Related
I am using the swift package AWSiOSSDKV2 from https://github.com/aws-amplify/aws-sdk-ios-spm
I can log in using the SDK but how can I use refresh Token to generate new accessToken using their SDK?
func login() {
let pool = AWSCognitoIdentityUserPool(forKey: PortalUserConfig.POOL_NAME)
if let user = pool?.getUser() {
user.getSession(username, password: password, validationData: nil).continueWith(block: { task -> Any? in
if let error = task.error {
let errorMessage = (error as NSError).userInfo["message"] as? String
} else {
guard let accessToken = task.result?.accessToken else {
return nil
}
print(accessToken)
let refreshToken = task.result?.refreshToken
print(refreshToken)
}
return nil
})
}
}
The Amplify library will automatically fetch new id and access tokens if they have expired and the refresh token is still valid. You can adjust the lifetime of your refresh tokens in the settings for your User Pool client. To learn more about OAuth token lifetime strategies, you can read up on the options over at OAuth.com.
There are some similar question however none of those solve my problem.
Using Xcode 11.1
MacOS Cataline 10.15
I clone this "active-directory-b2c-ios-swift-native-msal" and try to run getting Error "Could not acquire token: Error Domain=MSALErrorDomain Code=-50000 "(null)" UserInfo={MSALErrorDescriptionKey=Failed to start an interactive session, MSALInternalErrorCodeKey=-42008, MSALCorrelationIDKey=C9207A45-6A7D-416B-90E4-93E08F28A637}"
After changing B2C details same issue getting .
Please let me know what is issue, Is this issue for Xcode/OS/MSAL version or some issue with Code??
I tried with default configuration mention in git repo "active-directory-b2c-ios-swift-native-msal" and also tried after below changed let kTenantName = "dovervsg.onmicrosoft.com" // Your tenant name
let kClientID = "xxxxxxxxxxxxxxxxxxxxxxx" // Your client ID from the portal when you created your application
let kSignupOrSigninPolicy = "B2C_1-policy" // Your signup and sign-in policy you created in the portal
let kEditProfilePolicy = "b2c_1_edit_profile" // Your edit policy you created in the portal
let kResetPasswordPolicy = "B2C_1_reset_password" // Your reset password policy you created in the portal
let kGraphURI = "https://dev-vsg.dovertech.co.in" // This is your backend API that you've configured to accept your app's tokens
let kScopes: [String] = ["https://dovervsg.onmicrosoft.com/User.Read"] // This is a scope that you've configured your backend API to look for.
// tried with this scope format as well, let kScopes: [String] = ["https://dovervsg.onmicrosoft.com/api/User.Read"] // This is a scope that you've configured your backend API to look for.
let kTenantName = "dovervsg.onmicrosoft.com" // Your tenant name
let kClientID = "xxxxxxxxxxxxxxxxxxxxxxx" // Your client ID from the portal when you created your application
let kSignupOrSigninPolicy = "B2C_1-policy" // Your signup and sign-in policy you created in the portal
let kEditProfilePolicy = "b2c_1_edit_profile" // Your edit policy you created in the portal
let kResetPasswordPolicy = "B2C_1_reset_password" // Your reset password policy you created in the portal
let kGraphURI = "https://dev-vsg.dovertech.co.in" // This is your backend API that you've configured to accept your app's tokens
let kScopes: [String] = ["https://dovervsg.onmicrosoft.com/User.Read"] // This is a scope that you've configured your backend API to look for.
// tried with this scope format as well, let kScopes: [String] = ["https://dovervsg.onmicrosoft.com/api/User.Read"] // This is a scope that you've configured your backend API to look for
// DO NOT CHANGE - This is the format of OIDC Token and Authorization endpoints for Azure AD B2C.
let kEndpoint = "https://login.microsoftonline.com/tfp/%#/%#"
var application: MSALPublicClientApplication!
var accessToken: String?
#IBOutlet weak var loggingText: UITextView!
#IBOutlet weak var signoutButton: UIButton!
#IBOutlet weak var callGraphApiButton: UIButton!
#IBOutlet weak var editProfileButton: UIButton!
#IBOutlet weak var refreshTokenButton: UIButton!
override func viewDidAppear(_ animated: Bool) {
//super.viewDidLoad()
do {
/**
Initialize a MSALPublicClientApplication with a MSALPublicClientApplicationConfig.
MSALPublicClientApplicationConfig can be initialized with client id, redirect uri and authority.
Redirect uri will be constucted automatically in the form of "msal<your-client-id-here>://auth" if not provided.
The scheme part, i.e. "msal<your-client-id-here>", needs to be registered in the info.plist of the project
*/
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
// Provide configuration for MSALPublicClientApplication
// MSAL will use default redirect uri when you provide nil
let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: nil, authority: authority)
self.application = try MSALPublicClientApplication(configuration: pcaConfig)
} catch {
self.updateLoggingText(text: "Unable to create application \(error)")
}
}
/**
This button will invoke the authorization flow and send the policy specified to the B2C server.
Here we are using the `kSignupOrSignInPolicy` to sign the user in to the app. We will store this
accessToken for subsequent calls.
*/
#IBAction func authorizationButton(_ sender: UIButton) {
do {
/**
authority is a URL indicating a directory that MSAL can use to obtain tokens. In Azure B2C
it is of the form `https://<instance/tfp/<tenant>/<policy>`, where `<instance>` is the
directory host (e.g. https://login.microsoftonline.com), `<tenant>` is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com), and `<policy>` is the policy you wish to
use for the current user flow.
*/
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
/**
Acquire a token for a new account using interactive authentication
- scopes: Permissions you want included in the access token received
in the result in the completionBlock. Not all scopes are
gauranteed to be included in the access token returned.
- completionBlock: The completion block that will be called when the authentication
flow completes, or encounters an error.
*/
let webViewParameters = MSALWebviewParameters(parentViewController: self)
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: webViewParameters)
parameters.promptType = .selectAccount
print( parameters.promptType = .selectAccount)
parameters.authority = authority
debugPrint( parameters.authority = authority)
application.acquireToken(with: parameters) { (result, error) in
guard let result = result else {
self.updateLoggingText(text: "Could not acquire token: \(error ?? "No error informarion" as! Error)")
return
}
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "Empty")")
self.signoutButton.isEnabled = true
self.callGraphApiButton.isEnabled = true
self.editProfileButton.isEnabled = true
self.refreshTokenButton.isEnabled = true
}
} catch {
self.updateLoggingText(text: "Unable to create authority \(error)")
}
}
#IBAction func editProfile(_ sender: UIButton) {
do {
/**
authority is a URL indicating a directory that MSAL can use to obtain tokens. In Azure B2C
it is of the form `https://<instance/tfp/<tenant>/<policy>`, where `<instance>` is the
directory host (e.g. https://login.microsoftonline.com), `<tenant>` is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com), and `<policy>` is the policy you wish to
use for the current user flow.
*/
let authority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
/**
Acquire a token for a new account using interactive authentication
- scopes: Permissions you want included in the access token received
in the result in the completionBlock. Not all scopes are
gauranteed to be included in the access token returned.
- completionBlock: The completion block that will be called when the authentication
flow completes, or encounters an error.
*/
let thisAccount = try self.getAccountByPolicy(withAccounts: application.allAccounts(), policy: kEditProfilePolicy)
let webViewParameters = MSALWebviewParameters(parentViewController: self)
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: webViewParameters)
parameters.authority = authority
parameters.account = thisAccount
application.acquireToken(with: parameters) { (result, error) in
if let error = error {
self.updateLoggingText(text: "Could not edit profile: \(error)")
} else {
self.updateLoggingText(text: "Successfully edited profile")
}
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}
}
#IBAction func refreshToken(_ sender: UIButton) {
do {
/**
authority is a URL indicating a directory that MSAL can use to obtain tokens. In Azure B2C
it is of the form `https://<instance/tfp/<tenant>/<policy>`, where `<instance>` is the
directory host (e.g. https://login.microsoftonline.com), `<tenant>` is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com), and `<policy>` is the policy you wish to
use for the current user flow.
*/
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
/**
Acquire a token for an existing account silently
- scopes: Permissions you want included in the access token received
in the result in the completionBlock. Not all scopes are
gauranteed to be included in the access token returned.
- account: An account object that we retrieved from the application object before that the
authentication flow will be locked down to.
- completionBlock: The completion block that will be called when the authentication
flow completes, or encounters an error.
*/
guard let thisAccount = try self.getAccountByPolicy(withAccounts: application.allAccounts(), policy: kSignupOrSigninPolicy) else {
self.updateLoggingText(text: "There is no account available!")
return
}
let parameters = MSALSilentTokenParameters(scopes: kScopes, account:thisAccount)
parameters.authority = authority
self.application.acquireTokenSilent(with: parameters) { (result, error) in
if let error = error {
let nsError = error as NSError
// interactionRequired means we need to ask the user to sign-in. This usually happens
// when the user's Refresh Token is expired or if the user has changed their password
// among other possible reasons.
if (nsError.domain == MSALErrorDomain) {
if (nsError.code == MSALError.interactionRequired.rawValue) {
// Notice we supply the account here. This ensures we acquire token for the same account
// as we originally authenticated.
let webviewParameters = MSALWebviewParameters(parentViewController: self)
let parameters = MSALInteractiveTokenParameters(scopes: self.kScopes, webviewParameters: webviewParameters)
parameters.account = thisAccount
self.application.acquireToken(with: parameters) { (result, error) in
guard let result = result else {
self.updateLoggingText(text: "Could not acquire new token: \(error ?? "No error informarion" as! Error)")
return
}
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "empty")")
}
return
}
}
self.updateLoggingText(text: "Could not acquire token: \(error)")
return
}
guard let result = result else {
self.updateLoggingText(text: "Could not acquire token: No result returned")
return
}
self.accessToken = result.accessToken
self.updateLoggingText(text: "Refreshing token silently")
self.updateLoggingText(text: "Refreshed access token is \(self.accessToken ?? "empty")")
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}
}
#IBAction func callApi(_ sender: UIButton) {
guard let accessToken = self.accessToken else {
self.updateLoggingText(text: "Operation failed because could not find an access token!")
return
}
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30
let url = URL(string: self.kGraphURI)
var request = URLRequest(url: url!)
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
self.updateLoggingText(text: "Calling the API....")
urlSession.dataTask(with: request) { data, response, error in
guard let validData = data else {
self.updateLoggingText(text: "Could not call API: \(error ?? "No error informarion" as! Error)")
return
}
let result = try? JSONSerialization.jsonObject(with: validData, options: [])
guard let validResult = result as? [String: Any] else {
self.updateLoggingText(text: "Nothing returned from API")
return
}
self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
}.resume()
}
#IBAction func signoutButton(_ sender: UIButton) {
do {
/**
Removes all tokens from the cache for this application for the provided account
- account: The account to remove from the cache
*/
let thisAccount = try self.getAccountByPolicy(withAccounts: application.allAccounts(), policy: kSignupOrSigninPolicy)
if let accountToRemove = thisAccount {
try application.remove(accountToRemove)
} else {
self.updateLoggingText(text: "There is no account to signing out!")
}
self.signoutButton.isEnabled = false
self.callGraphApiButton.isEnabled = false
self.editProfileButton.isEnabled = false
self.refreshTokenButton.isEnabled = false
self.updateLoggingText(text: "Signed out")
} catch {
self.updateLoggingText(text: "Received error signing out: \(error)")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
if self.accessToken == nil {
signoutButton.isEnabled = false
callGraphApiButton.isEnabled = false
editProfileButton.isEnabled = false
refreshTokenButton.isEnabled = false
}
}
func getAccountByPolicy (withAccounts accounts: [MSALAccount], policy: String) throws -> MSALAccount? {
for account in accounts {
// This is a single account sample, so we only check the suffic part of the object id,
// where object id is in the form of <object id>-<policy>.
// For multi-account apps, the whole object id needs to be checked.
if let homeAccountId = account.homeAccountId, let objectId = homeAccountId.objectId {
if objectId.hasSuffix(policy.lowercased()) {
return account
}
}
}
return nil
}
/**
The way B2C knows what actions to perform for the user of the app is through the use of `Authority URL`.
It is of the form `https://<instance/tfp/<tenant>/<policy>`, where `<instance>` is the
directory host (e.g. https://login.microsoftonline.com), `<tenant>` is a
identifier within the directory itself (e.g. a domain associated to the
tenant, such as contoso.onmicrosoft.com), and `<policy>` is the policy you wish to
use for the current user flow.
*/
func getAuthority(forPolicy policy: String) throws -> MSALB2CAuthority {
guard let authorityURL = URL(string: String(format: self.kEndpoint, self.kTenantName, policy)) else {
throw NSError(domain: "SomeDomain",
code: 1,
userInfo: ["errorDescription": "Unable to create authority URL!"])
}
return try MSALB2CAuthority(url: authorityURL)
}
func updateLoggingText(text: String) {
DispatchQueue.main.async{
self.loggingText.text = text
}
}
}
After run getting error above
The sample has been updated and should be working as expected now. It is now updated to handle *.b2clogin.com and now adds sui_si and edit profile to the known authorities list.
let siginPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
// Provide configuration for MSALPublicClientApplication
// MSAL will use default redirect uri when you provide nil
let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: nil, authority: siginPolicyAuthority)
pcaConfig.knownAuthorities = [siginPolicyAuthority, editProfileAuthority]
self.application = try MSALPublicClientApplication(configuration: pcaConfig)
and
func getAuthority(forPolicy policy: String) throws -> MSALB2CAuthority {
guard let authorityURL = URL(string: String(format: self.kEndpoint, self.kAuthorityHostName, self.kTenantName, policy)) else {
throw NSError(domain: "SomeDomain",
code: 1,
userInfo: ["errorDescription": "Unable to create authority URL!"])
}
return try MSALB2CAuthority(url: authorityURL)
}
Q & A Style: See Answer Below
How Can I get the username from a user logged in with Cognito?
I've done this and my user is logged in, now what?
AWSAuthUIViewController.presentViewController(
with: self.navigationController!,
configuration: config, completionHandler: { (provider: AWSSignInProvider, error: Error?) in
if error == nil {
//get parameters
}
} else {
print(error as Any)
}
})
}
Prerequisites:
App registered with MobileHub
Cognito Setup in MobileHub
Mobilehub integrated with Swift Project using AWS SDK
If you're like me, you did this with little to no difficulty and now you're stuck trying to get the username and other parameters from the logged in user. There are a lot of answers, but thus far, I haven't stumbled upon one that gets you all the way there.
I was able to piece this together from various sources:
func getUsername() {
//to check if user is logged in with Cognito... not sure if this is necessary
let identityManager = AWSIdentityManager.default()
let identityProvider = identityManager.credentialsProvider.identityProvider.identityProviderName
if identityProvider == "cognito-identity.amazonaws.com" {
print("************LOGGED IN WITH COGNITO************")
let serviceConfiguration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: nil)
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: "YourClientID", clientSecret: "YourSecretKey", poolId: "YourPoolID")
AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: "YourPoolName (typically formatted as YourAppName_userpoool_MOBILEHUB_12345678")
let pool = AWSCognitoIdentityUserPool(forKey: "YourPoolName")
// the following line doesn't seem to be necessary and isn't used so I've commented it out, but it is included in official documentation
// let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USWest2, identityPoolId: "YourPoolID", identityProviderManager:pool)
if let username = pool.currentUser()?.username {
print("Username Retrieved Successfully: \(username)")
} else {
print("Error getting username from current user - attempt to get user")
let user = pool.getUser()
let username = user.username
print("Username: \(username)")
}
}
}
To get your ClientID, Secret Key, and PoolID, check your awsconfiguration.json
To get your PoolName, login to MobileHub, and in your project's backend, go to User Sign in, click Email and Password, then click Edit in Cognito. The following page will have your Pool Name as "YourAppName_userpool_MOBILEHUB_12345678"
Edit: To get all of the attributes as well:
if let userFromPool = pool.currentUser() {
userFromPool.getDetails().continueOnSuccessWith(block: { (task) -> Any? in
DispatchQueue.main.async {
if let error = task.error as NSError? {
print("Error getting user attributes from Cognito: \(error)")
} else {
let response = task.result
if let userAttributes = response?.userAttributes {
print("user attributes found: \(userAttributes)")
for attribute in userAttributes {
if attribute.name == "email" {
if let email = attribute.value {
print("User Email: \(email)")
}
}
}
If you're using Cognito User Pools, you can use this:
import AWSUserPoolsSignIn
AWSCognitoUserPoolsSignInProvider.sharedInstance()
.getUserPool()
.currentUser()?
.username
I'm getting a trouble when trying to connect AWSCognito to AWSLambda to pass an Auth role into it. My application has serverless architecture based on CognitoUserPool's, Lambda and IAM. So I have one configuration for all these things like the following:
let credentialsProvider = AWSCognitoCredentialsProvider(
regionType: CognitoIdentityUserPoolRegion,
identityPoolId: CognitoIdentityUserPoolIdentityId,
identityProviderManager: nil
)
// setup service configuration
let serviceConfiguration = AWSServiceConfiguration(
region: CognitoIdentityUserPoolRegion,
credentialsProvider: credentialsProvider
)
// create pool configuration
let poolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: CognitoIdentityUserPoolAppClientId,
clientSecret: nil,
poolId: CognitoIdentityUserPoolId)
// initialize user pool client
AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: poolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
// fetch the user pool client we initialized in above step
let pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey)
pool.delegate = self
AWSLambdaInvoker.register(with: serviceConfiguration!, forKey: AWSCognitoUserPoolsSignInProviderKey)
Then I do log in using the following snippet:
func signIn(username: String, password: String) -> Promise<Bool> {
let user = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey).getUser()
return Promise(resolvers: { resolve, reject in
user.getSession(username, password: password, validationData: nil)
.continueWith(block: { task -> Any? in
if let error = task.error {
let message = (error as NSError).userInfo["message"] as? String
return reject(AWSError.SignIn.sessionError(message))
}
guard let idToken = task.result?.idToken?.tokenString else {
return reject(AWSError.SignIn.noTokenProvided)
}
guard let identityId = user.username else {
return reject(AWSError.SignIn.noIdentityIdProvided)
}
return resolve(true)
})
})
}
The issue is that I'm always getting an error saying that:
User:
arn:aws:sts:{identity}:assumed-role/Cognito_myUnauth_Role/CognitoIdentityCredentials
is not authorized to perform: InvokeLambda
I tested an official example, I wrote my own implementations, and also I tried all the solutions mentioned in this thread: https://github.com/aws/aws-sdk-ios/issues/357 , but there was no luck with it.
I also tried implementing my own AWSCognitoCredentialsProviderHelper but the error is still presented. Do you have any ideas or maybe you also have faced with this issue so you can help me.
Thanks
I am trying to download a JSON file which is in my bucket in my S3 on my AWS account. I created an Unauthenticated cognito pool and copied this into my app delegate from the sample code:
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USWest2,
identityPoolId:"us-west-2:59a31a8f-ee6a-45fe-adaa-fa3eff871c80")
let configuration = AWSServiceConfiguration(region:.USWest2, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
In my view controller I have this code:
let transferManager = AWSS3TransferManager.default()
let downloadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("db_storage/costdb_latest.json ")
if let downloadRequest = AWSS3TransferManagerDownloadRequest(){
downloadRequest.bucket = "coast-s3-bucket"
downloadRequest.key = "db_storage/costdb_latest.json "
downloadRequest.downloadingFileURL = downloadingFileURL
transferManager.download(downloadRequest).continueWith(executor: AWSExecutor.default(), block: { (task: AWSTask<AnyObject>) -> Any? in
if( task.error != nil){
print(task.error!.localizedDescription)
return nil
}
print(task.result!)
if let data = NSData(contentsOf: downloadingFileURL){
DispatchQueue.main.async(execute: { () -> Void in
print(data)
})
}
return nil
})
}
Both the bucket and the pool are in the same region. USWest2 (Oregon). My bucket is public, and I've added AmazonS3FullAccess and AmazonS3ReadOnlyAccess to my policies. And I'm getting this error:
The operation couldn’t be completed. (com.amazonaws.AWSS3ErrorDomain error 4.)
Its not an authentication/authorization error (I think). From the looks of it, there is some issue with the configuration (region,endpoint etc.). Generally, these errors contain a full description of what's wrong. Try logging the full error message.
Also, see this example app for S3 TransferManager. Use your S3 & Cognito details. If this works, there is some code issue and you can find out by comparing both of these. If this does not work, then this could be a service issue.