Loupe

[Windows 8] Récupérer les informations de l’utilisateur lorsque celui-ci se connecte via son compte Google

Dans mon précédent post, j’ai expliqué comment utiliser les APIs de Google dans vos applications Windows Store, afin de manipuler le calendrier par exemple. Aujourd’hui, nous allons voir comment récupérer les informations d’un utilisateur qui s’est authentifié via son compte Google.

La procédure est simple: elle consiste à appeler l’URL  https://www.googleapis.com/oauth2/v3/userinfo qui va renvoyer un flux JSON contenant les informations de l’utilisateur. Pour que cela fonctionne, il ne faut pas oublier de rajouter https://www.googleapis.com/auth/userinfo.profile au scope de la connexion:

 

var googleUrl = "https://accounts.google.com/o/oauth2/auth?client_id=" +
                Uri.EscapeDataString(GoogleClientId) + "&redirect_uri=" +
                Uri.EscapeDataString(GoogleCallbackUrl) + "&response_type=code&scope=" +
                Uri.EscapeDataString("https://www.googleapis.com/auth/calendar") + "+" +
                Uri.EscapeDataString("https://www.googleapis.com/auth/userinfo.profile");

var startUri = new Uri(googleUrl);
var endUri = new Uri("https://accounts.google.com/o/oauth2/approval");

var result = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.UseTitle, startUri, endUri);
if (result.ResponseStatus == WebAuthenticationStatus.Success)
{
    var successCode = result.ResponseData;

    var code = successCode.Substring(successCode.IndexOf("=", StringComparison.CurrentCultureIgnoreCase) + 1);

    var token = await this.GetTokenAsync(code);
    if (token != null)
    {
        await this.GetUserEmail(token.access_token);
    }
}

Avec, à titre de rappel, les helpers suivants:

private async Task<Token> GetTokenAsync(string code)
{
    var httpClient = new HttpClient();

    string postData = string.Format("client_id={0}&client_secret={1}&code={2}&redirect_uri={3}&grant_type=authorization_code", GoogleClientId, GoogleClientSecret, code, GoogleCallbackUrl);
    var stringContent = new StringContent(postData, Encoding.UTF8, "application/x-www-form-urlencoded");

    var result = await httpClient.PostAsync("https://accounts.google.com/o/oauth2/token", stringContent);
    if (result.IsSuccessStatusCode)
    {
        var deserializer = new DataContractJsonSerializer(typeof(Token));
        var data = (Token)deserializer.ReadObject(await result.Content.ReadAsStreamAsync());

        return data;
    }

    return null;
}

private async Task GetUserEmail(string accessToken)
{
    var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);

    var content = await httpClient.GetAsync(string.Format("https://www.googleapis.com/oauth2/v3/userinfo?key={0}", GoogleApiKey));
    var result = await content.Content.ReadAsStringAsync();
}

Si on exécute ce code, on se rendu bien compte que les informations sont correctement remontées :

image

Cependant, on constate qu’une information (qui peut parfois être importante) manque: l’adresse email. En effet, pour des raisons de sécurité, l’adresse email n’est plus exposée directement et il faut la demander explicitement en rajoutant, dans le scope, l’URL https://www.googleapis.com/auth/userinfo.email. Ce qui donne:

var googleUrl = "https://accounts.google.com/o/oauth2/auth?client_id=" +
Uri.EscapeDataString(GoogleClientId) + "&redirect_uri=" +
Uri.EscapeDataString(GoogleCallbackUrl) + "&response_type=code&scope=" +
Uri.EscapeDataString("https://www.googleapis.com/auth/calendar") + "+" +
Uri.EscapeDataString("https://www.googleapis.com/auth/userinfo.profile") + "+" +
Uri.EscapeDataString("https://www.googleapis.com/auth/userinfo.email");

On peut constater qu’il n’y a aucuns problèmes à demander plusieurs scopes en même temps. Lors de la connexion de l’utilisateur, on voit que l’application demande bien un droit d’accès explicite sur l’adresse email:

image

Et, au niveau de l’application, on récupère bien l’information nécessaire dans le flux JSON:

image

 

Vous n’avez plus d’excuses pour ne plus proposer des interfaces utilisateur personnalisées à l’avenir ! Winking smile

 

Happy coding!

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus