amazon-archives / aws-sdk-xamarin

AWS Mobile SDK for Xamarin (Beta)
Apache License 2.0
45 stars 18 forks source link

Cognito Developer authenticated identities #30

Closed TuxNetrunner closed 9 years ago

TuxNetrunner commented 9 years ago

Hello! I cannot seem to find any class related to the Developer authenticated identities for Cognito, is it supported yet in this sdk? As far as I can understand from the "other" sdks docs (iOS and Android) there should be a way to implement an authentication provider to be able to manage this type of auth but I cannot seem to find the classes to override to do this. Am I missing something or is this not yet implemented? Is it going to be in the future? Thanks in advance!

tawalke commented 9 years ago

Hi @TuxNetrunner : What are you looking for specifically that you don't see?

Are you looking at the documentation noted in the Developer Guide here: http://docs.aws.amazon.com/cognito/devguide/identity/developer-authenticated-identities/

TuxNetrunner commented 9 years ago

Hi @tawalke , in the documentation you linked, there is a class to override (CognitoAWSCredentials) to implement an identity provider. In the Xamarin implementation, I cannot find the methods that I should override quoted in the example (which I think uses the unity sdk). The class CognitoAWSCredentials in Xamarin SDK doesn't expose a method to override similar to the method "RefreshIdentity" of the example (or at least I cannot figure out which is it). Basically, I already have my backend login script which returns the identityId and Token to the app, but I don't understand how to use these to create the CognitoAWSCredentials needed to identify my app's user and let him/her access other was services (in this case S3). Thanks in advance for your help.

tawalke commented 9 years ago

@TuxNetrunner You would make a class that inherits from IAmazonCognitoIdentity http://docs.aws.amazon.com/sdkfornet/latest/apidocs/Index.html which is what the CognitoAWSCredentials inherits from. The AWSAbstractCognitoIdentityProvider is just an abstract class which your class has to inherit from in the AWS Mobile Android SdK http://docs.aws.amazon.com/AWSAndroidSDK/latest/javadoc/com/amazonaws/auth/AWSAbstractCognitoIdentityProvider.html. You could create an abstract class that your class inherits from that inherits from that Interface if you wanted to be similar OR simply inherit from IAmazonIdentity as create a similar class or continue to use the CognitoAWSCredentials which will make the same calls needed.

If you read here, the process that Developer Auth goes through, you will see the underlying calls that are made which you could emulate or see that this is what the CognitoAWSCredentials emulates but note the difference would be you would override to make a call to GetOpenIdTokenForDeveloperIdentity. Please read here: http://docs.aws.amazon.com/cognito/devguide/identity/developer-authenticated-identities/ and advise if you have more questions or need more detailed advice.

TuxNetrunner commented 9 years ago

Hello @tawalke and thanks again! Sorry, but this looks a lot harder than I thought, so I will ask for some more help from you :). First of all, CognitoAWSCredentials doesn't seem to inherit from IAmazonCognitoIdentity, but from RefreshingAWSCredentials, which in turn inherits from AWSCredentials. The only class I see in the SDK inheriting from IAmazonCognitoIdentity is AmazonCognitoIdentityClient. Implementing all the methods needed for the interface IAmazonCognitoIdentity would be a lot of work, since there are a ton of different methods (all the methods needed to do about any operation involving cognitoidentity which by the way I don't need). I am just looking for the right class - containing a method to override or similar - to let it use the IdentityId and token provided by my backend's authentication and from that generating a set of AWS credentials to use with S3 client, as from the docs that is what I understood was needed. Thanks for your help again!

TuxNetrunner commented 9 years ago

@tawalke, I will try to put it down another way, to explain better the point I am missing :) Reading the docs the flow for Cognito developer authenticated identities is the following :

  1. Mobile APP issues a request to a custom login system on the developer backend using the custom developer credentials
  2. Developer backend authenticates internally the login data and, if it's ok, requests and gets from Cognito an identityID and a Token (using the getOpenIdTokenForDeveloperIdentity request and passing in it the user login identifier just validated); these are to be sent back to the mobile APP.
  3. Mobile APP receives these and uses them in a AssumeRoleWithWebIdentity request.

I got point one and two down with no problems, and the APP receives IdentityId and Token correctly. Point 3 is very hazy, since there is no method to do the AssumeRoleWithWebIdentity that takes these two parameters in Xamarin SDK. The only one I found, don't care about the IdentityID BUT wants the role ARN... So, looking at the docs that you linked, I assumed there would be a method to which I can pass these two strings (IdentityId and Token) to get the credentials needed by the other APIs in the SDK and therefore access other AWS services. I kinda figured that could have been done by somehow overriding CognitoAWSCredentials, but that doesn't look possible, since the method that ultimately makes the assumerolewithwebidentity call is private and from what I see in sources of the sdk itself, it uses the Role ARN if this is set, otherwise it uses the PoolID to request an identity, and openidtoken (which I don't want, since I already have my identityId). I have been playing around all day, even copy-pasted CognitoAWSCredentials class in my project and renamed it, trying to modify the methods to reflect what I want it to do, but I cannot find a way to use the underlying methods it calls to do the AssumeRoleWithWebIdentity call and get the temporary credentials. Maybe I got this all thing wrong, but at this point I really don't see a way out :) Again, thanks for your time and help.

tawalke commented 9 years ago

@TuxNetrunner Okay no problem. But first let me ask some questions.

You don't see the GetOpenIdTokenForDeveloperIdentity method or the AssumeRoleWithWebIdentity needed for your Developer Identity?

Did you inherit from CognitoAWSCredentials and create a refresh method and use the Client to call GetOpenIDTokenForDeveloperIdentity call? This would ensure you didn't have to do the interface inheritance but perform the steps for Developer authenticated credentials.? Then you could call the The AssumeRoleWithWebIdentityRequest request = new AssumeRoleWithWebIdentityRequest() and set the WebIdentityToken(YOUR token), ProviderId(Your URL), RoleArn(Cognito Auth ARN) RoleSessionName(YOUR developer Auth session string);

then AssumeRoleWithWebIdentityResult result = sts.assumeRoleWithWebIdentity(request);

RefreshingAWSCredentials theCredentials = result.getCredentials();

If this doesn't help, I can put something together for you. Let me know if doing the following works.

TuxNetrunner commented 9 years ago

@tawalke I finally got to the bottom of the problem and have a working cognito developer authentication. As you hinted, it was enough to substitute the method that uses the GetOpenId method in CognitoAWSCredentials, everything else in the class can stay exactly the same. I had tried that already the other day, but I was indicating together with the token received the wrong provider identifier (was using the string i specified in the pool), while I should have used "cognito-identity.amazonaws.com". By the way, after I figured this, it took me quite a lot of research to understand what was the value to be used, and it took quite a bit digging through different examples and docs to find the right one, so I think for future reference and to save other people from headaches, it would be a good idea to state it explicitly in the API documentation and/or on the sdk docs/examples. Also, if I may suggest one more thing, I would make the method GetCredentialsForRoleAsync (which, in its two flavors - sync and async- is the only one that does call the GetOpenId method) public or somehow overridable so that to implement developer authentication it will be enough to override that method instead of having to re-write the whole class. Thanks a ton for your support :)