问题
I guess my question, Understanding Cognito Identities, wasn't specific enough. I still can't figure out how to use a federated identity from a Xamarin app. Here's what I'm trying, but it's really quite random because I can't find any sample code for this task out there. I tried putting a breakpoint on the AddLogin
line, and it never gets hit, even though breakpoint two lines up does get hit. There are too many new-to-me technologies in this code for me to know where to begin on tracking down the problem. (I x'd out the Identity pool ID in the code below, but a real one is there.) At this point I'm just trying to get evidence that I can uniquely identify/validate an Amazon account, and maybe add it to my user pool. But I can't even get the code to entirely execute or report an error.
Login().ContinueWith(t => { if (t.Exception != null)
Toast.MakeText(ApplicationContext, t.Exception.ToString(), ToastLength.Long).Show(); });
public async Task Login()
{
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
"us-east-2:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // Identity pool ID
RegionEndpoint.USEast2 // Region
);
var client = new Amazon.SecurityToken.AmazonSecurityTokenServiceClient(credentials);
var request = new Amazon.SecurityToken.Model.GetFederationTokenRequest("myamazonid@gmail.com");
var response = await client.GetFederationTokenAsync(request);
credentials.AddLogin("www.amazon.com", response.Credentials.SessionToken);
}
回答1:
It took a good deal of searching, but I think I figured it out. Setting up the services and getting the client ID is not too hard (is well documented) compared to working out the code, so this answer will focus on the code. Google is particularly tricky because of changes made to their OAuth implementation that prevents some forms of authentication from working. In order for Google identities to work with Cognito, APIs need to be up-to-date. Use NuGet to reference the following API versions or later:
- Xamarin.Auth 1.5.0.3
- Xamarin.Android.Support.v4 25.4.0.2
- Xamarin.Android.Support.CustomTabs 25.4.0.2
- AWSSDK.CognitoIdentity 3.3.2.14
- AWSSDK.Core 3.3.17.8
- Validation 2.4.15
- Xamarin.Android.Support.Annotations 25.4.0.2
This code is in the main activity:
protected override void OnCreate(Bundle savedInstanceState)
{
// (etc)
credentials = new CognitoAWSCredentials(
"us-east-2:00000000-0000-0000-0000-000000000000", // Identity pool ID
RegionEndpoint.USEast2 // Region
);
// (etc)
}
private void ShowMessage(string message)
{
AlertDialog dlgAlert = new AlertDialog.Builder(this).Create();
dlgAlert.SetMessage(message);
dlgAlert.SetButton("Close", (s, args) => { dlgAlert.Dismiss(); });
dlgAlert.Show();
}
public void Logout()
{
credentials.Clear();
}
public void Login()
{
if (!string.IsNullOrEmpty(credentials.GetCachedIdentityId()) || credentials.CurrentLoginProviders.Length > 0)
{
if (!bDidLogin)
ShowMessage(string.Format("I still remember you're {0} ", credentials.GetIdentityId()));
bDidLogin = true;
return;
}
bDidLogin = true;
auth = new Xamarin.Auth.OAuth2Authenticator(
"my-google-client-id.apps.googleusercontent.com",
string.Empty,
"openid",
new System.Uri("https://accounts.google.com/o/oauth2/v2/auth"),
new System.Uri("com.mynamespace.myapp:/oauth2redirect"),
new System.Uri("https://www.googleapis.com/oauth2/v4/token"),
isUsingNativeUI: true);
auth.Completed += Auth_Completed;
StartActivity(auth.GetUI(this));
}
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
var http = new System.Net.Http.HttpClient();
var idToken = e.Account.Properties["id_token"];
credentials.AddLogin("accounts.google.com", idToken);
AmazonCognitoIdentityClient cli = new AmazonCognitoIdentityClient(credentials, RegionEndpoint.USEast2);
var req = new Amazon.CognitoIdentity.Model.GetIdRequest();
req.Logins.Add("accounts.google.com", idToken);
req.IdentityPoolId = "us-east-2:00000000-0000-0000-0000-000000000000";
cli.GetIdAsync(req).ContinueWith((task) =>
{
if ((task.Status == TaskStatus.RanToCompletion) && (task.Result != null))
ShowMessage(string.Format("Identity {0} retrieved", task.Result.IdentityId));
else
ShowMessage(task.Exception.InnerException!=null ? task.Exception.InnerException.Message : task.Exception.Message);
});
}
else
ShowMessage("Login cancelled");
}
Then there's another activity to handle the callback from the redirect URL in the Google authentication process:
[Activity(Label = "GoodleAuthInterceptor")]
[IntentFilter(actions: new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
DataSchemes = new[] { "com.mynamespace.myapp" }, DataPaths = new[] { "/oauth2redirect" })]
public class GoodleAuthInterceptor : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Android.Net.Uri uri_android = Intent.Data;
Uri uri_netfx = new Uri(uri_android.ToString());
MainActivity.auth?.OnPageLoading(uri_netfx);
Finish();
}
}
来源:https://stackoverflow.com/questions/46065300/using-cognito-federated-identities-from-xamarin