It took a lot of searching, but I think I figured it out. Setting up services and getting a client ID is not too complicated (well documented) compared to code development, so this answer will focus on the code. Google is particularly complex due to changes made to their OAuth implementation, which prevents some forms of authentication from working. For Google IDs to work with Cognito, the API must be updated. Use NuGet to link to 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
- Verification 2.4.15
- Xamarin.Android.Support.Annotations 25.4.0.2
This code is in the main action:
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 is another action 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(); } }
source share