[Google+ Portable SDK .NET] Obtener Token de acceso (III)

Siguiendo con el flujo OAuth 2.0, en esta ocasión vamos a solicitar el token de acceso y el token refresh, para lo cual necesitaremos el código de autorización obtenido en la entrega anterior. Si guardamos ambos valores, la próxima vez que nos conectemos a la plataforma Google Plus, ya no será necesario volver a realizar el proceso OAuth2. También hay que tener en cuenta  que este token tiene una expiración de 60 minutos. Pasado ese tiempo debemos usar el valor del token refresh para volver a solicitar otro token.

Antes de nada, vamos a recordar la hoja de ruta para esta serie de artículos

1. Crear aplicación Google +

2. Obtener código de autorización

3. Obtener Token de acceso (actual)

4. Obtener información del perfil.

5. Amigos en los círculos

6. Buscar Amigos

7. Obtener las publicaciones del muro

Para solicitar el token de acceso hay que hacer una petición POST a la url

https://accounts.google.com/o/oauth2/token

la cual debe incluir los siguiente parámetros:

grand_type: debe contener el valor “authorization_code”

code: es el código de autorización obtenido en la entrega anterior.

redirect_uri: es la url de redirección usada en el entrega anterior.

client_id: este valor se obtiene al crear una aplicación google +

client_secret: este valor se obtiene al crear una aplicación google +

Si la petición es correcta, la plataforma Google Plus nos retorna un JSON, el cual incluye los siguientes campos:

access_token: este es el valor que debemos usar para las peticiones autentificadas a Google Plus.

token_type: indica el tipo de token. Su valor debe ser Bearer.

– expires_in: tiempo de expiración en segundos. Por defecto 60 minutos.

– refresh_token: cuando el token de acceso expira, este valor permite obtener un token nuevo sin necesidad de volver a solicitar autorización al usuario. El “refresh_token” es válido hasta que el usuario revoque su validez a través del “Access Pane” de nuestra App en “Google Plus Console“.

Todo el proceso para recuperar este token ha sido encapsulado en la función “ObtenerTokenAccesoAsync” de la clase “smpGooglePlusApi

        public async Task<InfoToken> ObtenerTokenAccesoAsync(string appKey, string appSecret, string codigoAutorizacion, string urlCallBack = Declaraciones.URL_CALLBACK_WEBSERVER_LOCAL)
        {
            InfoToken infoToken = new OAuth2.InfoToken();

            if (string.IsNullOrEmpty(appKey))
                throw new ArgumentException("appKey");
            if (string.IsNullOrEmpty(appSecret))
                throw new ArgumentException("appSecret");
            if (string.IsNullOrEmpty(codigoAutorizacion))
                throw new ArgumentException("codigoAutorizacion");
            if (string.IsNullOrEmpty(urlCallBack))
                throw new ArgumentException("urlCallBack");

            HttpClient cliente = new HttpClient();
            List<KeyValuePair<string, string>> listaParametros = new List<KeyValuePair<string, string>>();
            listaParametros.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
            listaParametros.Add(new KeyValuePair<string, string>("code", codigoAutorizacion));
            listaParametros.Add(new KeyValuePair<string, string>("redirect_uri", urlCallBack));
            listaParametros.Add(new KeyValuePair<string, string>("client_id", appKey));
            listaParametros.Add(new KeyValuePair<string, string>("client_secret", appSecret));
            FormUrlEncodedContent contenidoPost = new FormUrlEncodedContent(listaParametros);

            HttpResponseMessage respuestaHttp = await cliente.PostAsync(Declaraciones.URL_OAUTH2_TOKEN_ACCESS, contenidoPost).ConfigureAwait(false);
            RespuestaGooglePlus respuestaGooglePlus = await UtilidadesGenerales.ProcesarRespuestaAsync(respuestaHttp);

            if (respuestaGooglePlus.Estado == EstadoGooglePlus.Correcto)
            {
                infoToken = Newtonsoft.Json.JsonConvert.DeserializeObject<InfoToken>(respuestaGooglePlus.ContenidoRespuesta);
            }
            else
            {
                JObject respuesta = JObject.Parse(respuestaGooglePlus.ContenidoRespuesta);
                string error = (respuesta["error"] != null ? respuesta["error"].ToString() : string.Empty);

                throw new Exception(string.Format("Se ha producido el siguiente error: {0}",error));
            }

            return infoToken;
        }

Como se observar en el código anterior, la petición POST es enviada usando el método PostAsync de la clase HttpClient, al cual le pasamos una instancia del tipo FormUrlEncodedContent, que incluye los parámetros comentados anteriormente.

Si la respuesta de Google Plus es correcta, usamos la librería json.net para deserializar la respuesta JSON

infoToken = Newtonsoft.Json.JsonConvert.DeserializeObject<InfoToken>(respuestaGooglePlus.ContenidoRespuesta);

y convertirla a un objeto .NET (en este caso del tipo InfoToken)

namespace smpClienteGooglePlus.OAuth2
{
    public class InfoToken
    {
        public string access_token { get; set; }
        public string token_type { get; set; }
        public int expires_in { get; set; }
        public string id_token { get; set; }
        public string refresh_token { get; set; }

        public InfoToken()
        {
            access_token = string.Empty;
            token_type=string.Empty;
            expires_in = 0;
            id_token = string.Empty;
            refresh_token = string.Empty;
        }
    }

}

Si el token acceso expira, podemos usar el “refresh token” para volver a solicitar uno nuevo. Este proceso ha sido incluido en el método “RefrescarTokenAccesoAsync

public async Task<InfoToken> RefrescarTokenAccesoAsync(string appKey, string appSecret, string refresToken)
        {
            InfoToken infoToken = new OAuth2.InfoToken();

            if (string.IsNullOrEmpty(appKey))
                throw new ArgumentException("appKey");
            if (string.IsNullOrEmpty(appSecret))
                throw new ArgumentException("appSecret");
            if (string.IsNullOrEmpty(refresToken))
                throw new ArgumentException("refresToken");

            HttpClient cliente = new HttpClient();
            List<KeyValuePair<string, string>> listaParametros = new List<KeyValuePair<string, string>>();
            listaParametros.Add(new KeyValuePair<string, string>("grant_type", "refresh_token"));
            listaParametros.Add(new KeyValuePair<string, string>("refresh_token", refresToken));
            listaParametros.Add(new KeyValuePair<string, string>("client_id", appKey));
            listaParametros.Add(new KeyValuePair<string, string>("client_secret", appSecret));
            FormUrlEncodedContent contenidoPost = new FormUrlEncodedContent(listaParametros);

            HttpResponseMessage respuestaHttp = await cliente.PostAsync(Declaraciones.URL_OAUTH2_TOKEN_ACCESS, contenidoPost).ConfigureAwait(false);
            RespuestaGooglePlus respuestaGooglePlus = await UtilidadesGenerales.ProcesarRespuestaAsync(respuestaHttp);

            if (respuestaGooglePlus.Estado == EstadoGooglePlus.Correcto)
            {
                infoToken = Newtonsoft.Json.JsonConvert.DeserializeObject<InfoToken>(respuestaGooglePlus.ContenidoRespuesta);
            }
            else
            {
                JObject respuesta = JObject.Parse(respuestaGooglePlus.ContenidoRespuesta);
                string error = (respuesta["error"] != null ? respuesta["error"].ToString() : string.Empty);

                throw new Exception(string.Format("Se ha producido el siguiente error: {0}", error));
            }

            return infoToken;
        }

Donde también hay que hacer una petición POST a la url

pero usando los siguientes parámetros

– grand_type: debe contener el valor “refresh_token”

– refresh_token: es el valor del “refresh_token”.

– client_id: este valor se obtiene al crear una aplicación google +

– client_secret: este valor se obtiene al crear una aplicación google +

En este punto nuestra app de ejemplo para WPF tiene el siguiente aspecto

googleplus_client_parte3_token

En el siguiente enlace se puede descargar el código de ejemplo.