Search code examples
c#asp.net-mvcazureoauth-2.0google-analytics-api

Google Analytics Api on Azure


I want to use the google analytics api in my MVC website, im authenticating using the api service account and oauth2 with have no issues on my localhost but as soon as I deploy to Azure i get a 502 error:

"502 - Web server received an invalid response while acting as a gateway or proxy server. There is a problem with the page you are looking for, and it cannot be displayed. When the Web server (while acting as a gateway or proxy) contacted the upstream content server, it received an invalid response from the content server."

heres my code:

const string ServiceAccountUser = "xxxxxxxxxx-cpla4j8focrebami0l87mbcto09j9j6k@developer.gserviceaccount.com";
AssertionFlowClient client = new AssertionFlowClient(
        GoogleAuthenticationServer.Description,
            new X509Certificate2(System.Web.Hosting.HostingEnvironment.MapPath("/Areas/Admin/xxxxxxxxxxxxxxxxxx-privatekey.p12"), 
                "notasecret", X509KeyStorageFlags.Exportable))
        {
            Scope = AnalyticsService.Scopes.AnalyticsReadonly.GetStringValue(),
            ServiceAccountId = ServiceAccountUser //Bug, why does ServiceAccountUser have to be assigned to ServiceAccountId
            //,ServiceAccountUser = ServiceAccountUser
        };
        OAuth2Authenticator<AssertionFlowClient> authenticator = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);

I cant figure out whats causing it? Am im missing something within Azure?

Thanks for any help.


Solution

  • After hours of pain on this exact same problem, I found a work around by piecing together various sources of info.

    The problem arises from trying to read the p12 file from the Azure web site, i.e. this line in my code fails

    var key = new X509Certificate2(keyFile, keyPassword, X509KeyStorageFlags.Exportable);
    

    No idea why, but it works if you split the file into a cer and key.xml file?

    Firstly, extract these files, (I just used a console app)

    // load pfx/p12 as "exportable"
    var p12Cert = new X509Certificate2(@"c:\Temp\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable);
    
    // export .cer from .pfx/.p12
    File.WriteAllBytes(@"C:\Temp\MyCert.cer", p12Cert.Export(X509ContentType.Cert));
    
    // export private key XML
    string privateKeyXml = p12Cert.PrivateKey.ToXmlString(true);
    
    File.WriteAllText(@"C:\Temp\PrivateKey.xml", privateKeyXml);
    

    Then copy them to your website then load them in like so

    //Store the authentication description
    AuthorizationServerDescription desc = GoogleAuthenticationServer.Description;
    
    //Create a certificate object to use when authenticating
    
    var rsaCryptoServiceProvider = new RSACryptoServiceProvider();
    rsaCryptoServiceProvider.FromXmlString(File.ReadAllText(keyFile));
    var key = new X509Certificate2(certFile) {PrivateKey = rsaCryptoServiceProvider};
    
    
    //Now, we will log in and authenticate, passing in the description
    //and key from above, then setting the accountId and scope
    var client = new AssertionFlowClient(desc, key)
    {
        //cliendId is your SERVICE ACCOUNT Email Address from Google APIs Console
        //looks something like [email protected]
        //~IMPORTANT~: this email address has to be added to your Google Analytics profile
        // and given Read & Analyze permissions
        ServiceAccountId = clientId,
        Scope = "https://www.googleapis.com/auth/analytics.readonly"
    };
    
    //Finally, complete the authentication process
    //NOTE: This is the first change from the update above
    var auth = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
    
    //First, create a new service object
    //NOTE: this is the second change from the update
    //above. Thanks to James for pointing this out
    var gas = new AnalyticsService(new BaseClientService.Initializer { Authenticator = auth });
    

    This now works for me and I hope it helps you.