Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Analytics OAuth with AccessType = Offline in C#

I want to use Google Analytics API using OAuth.

I am using this library: http://code.google.com/p/google-api-dotnet-client/

The following code is used for authentication:

var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
    new ClientSecrets { ClientId = "...", ClientSecret = "..." },
    new[] {Google.Apis.Analytics.v3.AnalyticsService.Scope.AnalyticsReadonly},
    "user",
    CancellationToken.None,
    new FileDataStore("Analytics.Auth.Store")).Result;

var service = new Google.Apis.Analytics.v3.AnalyticsService(
    new BaseClientService.Initializer
    {
        HttpClientInitializer = credential,
        ApplicationName = "...",
    });

Can I use this with a refresh_token so that I do not have to accept the authorization request every few days?

Something like in the answer of this question: Service Account Google Analytics OAuth AccessType = Offline C#

like image 309
Dennis Avatar asked Feb 28 '14 11:02

Dennis


2 Answers

I know only one way: you need to override GoogleAuthorizationCodeRequestUrl, but I have no idea how to use this with AuthorizationBroker.

internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
    public ForceOfflineGoogleAuthorizationCodeFlow(AuthorizationCodeFlow.Initializer initializer) : base(initializer) { }

    public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
    {
        return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
                {
                    ClientId = ClientSecrets.ClientId,
                    Scope = string.Join(" ", Scopes),
                    RedirectUri = redirectUri,
                    AccessType = "offline",
                    ApprovalPrompt = "force"
                };
    }
};

Looks like they create Flow inside the broker: GoogleWebAuthorizationBroker.cs

And I didn't see any way to pass params or replace AuthorizationCodeFlow

like image 139
Darida Avatar answered Nov 17 '22 04:11

Darida


Apparently I can't comment, but to extend on Darida's answer:

Make your custom CodeFlow

public class CustomAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
    public CustomAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }

    public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(String redirectUri)
    {
        return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
        {
            ClientId = ClientSecrets.ClientId,
            Scope = string.Join(" ", Scopes),
            RedirectUri = redirectUri,
            AccessType = "online",
            ApprovalPrompt = "auto"
        };
    }
}

Then make a custom FlowMetadata

public class AppFlowMetadata : FlowMetadata
{
    private static readonly IAuthorizationCodeFlow flow =
        new CustomAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = new ClientSecrets
            {
                ClientId = "...",
                ClientSecret = "..."
            },
            Scopes = new String[] { AnalyticsService.Scope.AnalyticsReadonly },
            DataStore = new EFDataStore(),
        });

    public override IAuthorizationCodeFlow Flow
    {
        get { return flow; }
    }

    public override String GetUserId(Controller controller)
    {
        // In this sample we use the session to store the user identifiers.
        // That's not the best practice, because you should have a logic to identify
        // a user. You might want to use "OpenID Connect".
        // You can read more about the protocol in the following link:
        // https://developers.google.com/accounts/docs/OAuth2Login.

        return String.Format("user-{0}", WebSecurity.GetUserId(controller.User.Identity.Name));
    }
}

and then in the Controller

public ActionResult Sample()
{
    var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);

    if (result.Credential != null)
    {
        var service = new AnalyticsService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = result.Credential,
            ApplicationName = APPLICATION_NAME
        });
   }
}
like image 38
Peter Dolkens Avatar answered Nov 17 '22 05:11

Peter Dolkens