0

I've spent some time over the last few days trying to implement a feature for my web application. The feature should add new events to a users google calendar while they are offline. I read the Google OAuth2 documentation for web server applications and seem to understand the basics of it. I created a link to authorize the application for offline access:

    <a target='_blank' href='https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ftasks&response_type=code&client_id=<MY CLIENT ID>&access_type=offline&redirect_uri=http%3A%2F%2Flocalhost:49949%2Foauth2callback.aspx'>Grant Tasks Permission</a>

If the user accepts then I capture the refresh token at the redirect uri like this:

    private static OAuth2Authenticator<WebServerClient> _authenticator;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (HttpContext.Current.Request["code"] != null)
        {
            _authenticator = CreateAuthenticator();
            _authenticator.LoadAccessToken();
        }
        Response.Write("Refresh Token: " + _authenticator.State.RefreshToken);

    }

    private OAuth2Authenticator<WebServerClient> CreateAuthenticator()
    {
        var provider = new WebServerClient(GoogleAuthenticationServer.Description);
        provider.ClientIdentifier = "<MY CLIENT ID>";
        provider.ClientSecret = "<MY CLIENT SECRET>";
        return new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization);
    }

    private IAuthorizationState GetAuthorization(WebServerClient client)
    {
        return client.ProcessUserAuthorization(new HttpRequestInfo(HttpContext.Current.Request));
    }

For testing purposes I have been copying the refresh token to a text file for further use.

My problem is using this refresh token for offine access. I have been using this code to refresh the token:

    protected void btnGetTasks_Click(object sender, EventArgs e)
    {
        if (_service == null)
        {
            _authenticator = CreateAuthenticator();
            _service = new TasksService(new BaseClientService.Initializer() { Authenticator = _authenticator });
        }

        var cl = _service.Tasklists.List().Fetch();
    }

    private OAuth2Authenticator<WebServerClient> CreateAuthenticator()
    {
        // Register the authenticator.
        var provider = new WebServerClient(GoogleAuthenticationServer.Description);
        provider.ClientIdentifier = "<MY CLIENT ID>";
        provider.ClientSecret = "<MY CLIENT SECRET>";
        var authenticator = new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization);
        return authenticator;
    }

    private IAuthorizationState GetAuthorization(WebServerClient client)
    {                      
        string scope = "https://www.googleapis.com/auth/tasks";
        IAuthorizationState state = new AuthorizationState(new[] { scope });
        state.RefreshToken = "<REFRESH TOKEN FROM FIRST STEP>";
        var result = client.RefreshToken(state);
        return client.ProcessUserAuthorization();
    }

Everything seems fine at this point. When I step through the code I can see the result from client.RefreshToken(state) is true. The issue is when I call this line of code:

_service.Tasklists.List().Fetch();

It returns a (401) unauthorized error from google. I'm looking into the cause but I am not sure how to proceed and I am running short on time with this feature. Any advice would be greatly appreciated. Thanks!

sdowd
  • 78
  • 11

1 Answers1

0

Seems just the act of putting code on here always helps me figure it out a little sooner :)

It now appears this line is unnecessary:

return client.ProcessUserAuthorization();

removing that from the GetAuthorization method and just returning the state passed to RefreshToken has resolved the unauthorized error. I'll leave the question in case it stumps anyone else.

sdowd
  • 78
  • 11