dimanche 1 janvier 2017

Using .NET WebAuthenticationBroker for Google Login in your Windows 10 application [UWP,C#,GOOGLE]

I was fighting with my Google login on my UWP app and thus thought that it would be great if I just copied and pasted my code here so that it might help others.

Long story short, I did not want to use the google SDK to log into my app so I ended up using WebAuthenticationBroker.AuthenticateAsync.   For the WebAuthenticationBroker you need a startUrl and a endUrl which you can find here:
var googleUrl = new System.Text.StringBuilder();
            googleUrl.Append("https://accounts.google.com/o/oauth2/auth?client_id=");
            googleUrl.Append(Uri.EscapeDataString(ClientID));
            googleUrl.Append("&scope=");
            googleUrl.Append(Uri.EscapeDataString("https://www.googleapis.com/auth/plus.profile.emails.read"));
            googleUrl.Append("&redirect_uri=");
            googleUrl.Append(Uri.EscapeDataString("urn:ietf:wg:oauth:2.0:oob"));
            googleUrl.Append("&response_type=code");


string endURL = "https://accounts.google.com/o/oauth2/approval?";


One small problem, was that when using WebAuthenticationBroker on UWP you don't get an access token but a authorization code which doesn't really help you,  because you cant authenticate with an authorization code, I needed an access token.

What we need to do next is a POST call on  https://accounts.google.com/o/oauth2/token
with my client id, client secret and authorization code and a few other parameters, here is the full list:
 var pairs = new Dictionary<string, string>();
                    pairs.Add("code", authorizationCode);
                    pairs.Add("client_id", ClientID);
                    pairs.Add("client_secret", ClientSecret);
                    pairs.Add("grant_type", "authorization_code");
                    pairs.Add("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");

We encode the content:
var formContent = new HttpFormUrlEncodedContent(pairs);

Next we do our POST call:
await client.PostAsync(new Uri("https://accounts.google.com/o/oauth2/token"), formContent);

And Voila you have your auth token =)
string response = await httpResponseMessage.Content.ReadAsStringAsync();

Full code here:
Warning to people that like sexy code this will hurt you eyes:

 public async Task<string> LogIntoGoogleClean()
 {
            var googleUrl = new System.Text.StringBuilder();
            googleUrl.Append("https://accounts.google.com/o/oauth2/auth?client_id=");
            googleUrl.Append(Uri.EscapeDataString(ClientID));
            googleUrl.Append("&scope=");
            googleUrl.Append(Uri.EscapeDataString("https://www.googleapis.com/auth/plus.profile.emails.read"));
            googleUrl.Append("&redirect_uri=");
            googleUrl.Append(Uri.EscapeDataString("urn:ietf:wg:oauth:2.0:oob"));
            googleUrl.Append("&response_type=code");

            //approval
            string endURL = "https://accounts.google.com/o/oauth2/approval?";

            Uri startUri = new Uri(googleUrl.ToString());
            Uri endUri = new Uri(endURL);

            try
            {
                // Using WebAuthenticationBroker
                WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.UseTitle, startUri, endUri);

                //Checking to see if we haev succeded
                if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
                {
                    Debug.WriteLine("ResponseData: " + webAuthenticationResult.ResponseData);

                    //getting just the autorizationCode to continue and get the token 
                    var authorizationCode = webAuthenticationResult.ResponseData.Substring(13);

                    //lets get crazy and get the access token so that i can really login
                    var pairs = new Dictionary<string, string>();
                    pairs.Add("code", authorizationCode);
                    pairs.Add("client_id", ClientID);
                    pairs.Add("client_secret", ClientSecret);
                    pairs.Add("grant_type", "authorization_code");
                    pairs.Add("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");


                    var formContent = new HttpFormUrlEncodedContent(pairs);

                    //please dont hate me but this is dirty
                    var client = new HttpClient();
                    var httpResponseMessage =
                        await client.PostAsync(new Uri("https://accounts.google.com/o/oauth2/token"), formContent);
                    string response = await httpResponseMessage.Content.ReadAsStringAsync();

                    //but at least I got it to work :P
                    GoogleAccessToken token = JsonConvert.DeserializeObject<GoogleAccessToken>(response);

                    //return access token
                    return token.access_token;
                }
                else
                    return webAuthenticationResult.ResponseStatus.ToString();
            }
            catch (Exception Error)
            {
                //report the issue
App.RepportError(Error); } return "error"; }

Happy Coding!