Phil Jenkins Phil Jenkins - 10 months ago 77
C# Question

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 = "";
AssertionFlowClient client = new AssertionFlowClient(
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.

Answer Source

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();
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
    //~IMPORTANT~: this email address has to be added to your Google Analytics profile
    // and given Read & Analyze permissions
    ServiceAccountId = clientId,
    Scope = ""

//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.