简体   繁体   中英

OAuth2 Access and Refresh Token from backend service

I'm a backend web service developer for an Android app. We are offering services to the app as subscription and is looking at using Google Play for subscription purchases. We have a backend licenses server to keep track on what services that are available for the user in the app.

For certain reasons we want to get a subscription status for a purchase from the backend. But I have run into a problem getting the access and refresh token from the Google's OAuth2 web service.

I have followed the instructions from following page: Google Play Android Developer API

I do not have direct access to the Google Account that is used to setup the Client ID and I had the manager that has access to do the step to to perform the web call to get the initial code, that was then given to me. I then use it to call the grant auth with a HTTP POST, but getting a HTTP 400 with Json containing nothing but a "invalid_grant" error. Here is an example of the POST code:

    string postData = String.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",
        oauthCode,
        clientId,
        clientSecret,
        redirectURL
        );
    byte[] data = Encoding.UTF8.GetBytes(postData);

    try
    {

        HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
        wreq.Method = "POST";
        wreq.ContentType = "application/x-www-form-urlencoded";
        wreq.ContentLength = data.Length;
        wreq.Accept = "application/json";

        using (Stream wstream = wreq.GetRequestStream())
        {
            wstream.Write(data, 0, data.Length);
        }

        HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse();
        if (wresp.StatusCode == HttpStatusCode.OK)
        {
            using (Stream rstream = wresp.GetResponseStream())
            {
                StringBuilder jresp = new StringBuilder();
                byte[] buffer = new byte[512];
                int read = 0;

                while ((read = rstream.Read(buffer, 0, buffer.Length)) > 0)
                    jresp.Append(Encoding.UTF8.GetString(buffer, 0, read));

                Console.WriteLine(jresp.ToString());
            }
        }
        else
            Console.WriteLine("damn...");

    }
    catch (WebException wex)
    {
        Console.WriteLine(wex.ToString());
        Console.WriteLine("================================");


        if (wex.Response != null)
        {
            StringBuilder inner = new StringBuilder();
            byte[] buffer = new byte[512];
            int read = 0;

            using (Stream xstream = wex.Response.GetResponseStream())
            {
                while ((read = xstream.Read(buffer, 0, buffer.Length)) > 0)
                    inner.Append(Encoding.UTF8.GetString(buffer, 0, read));
            }

            Console.WriteLine(inner.ToString());
        }

    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

I'm concerned that I won't be able to do it from a different location than the initial code auth web browser call and that the access/refresh token can't be performed from a backend out of web browser experience.

I'm writing this as an answer in case someone else will need it. This is the conclusion I came to:

The initial "grant_type=authorization_code" call seems to have to be done in the same session as the OAuth code request.

I was able to get access to the Google Account credentials and had the redirect code do the initial access token request that also returns the refresh token. It was able to do so. This seems to mean that the initial access and refresh token request can't be done in a backend process and has to be done in a session environment such as a web browser.

I then turned around and from C# did a standard post request to refresh the access token with the received refresh token, and was able to get a new access token.

EDIT: And as a heads up. If you have done the initial authorization_code call for a specific client id and secret. any retries to call it, will not return the refresh_token in the result JSON. Only the current access_token. So make sure you store it somewhere!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM