Google Calendar API and shared hosting issue

I'm trying to use a public Google calendar in a webpage that will need editing functionalities. To that effect, I created the calendar and made it public. I then created a Google service account and the related client id. I also enabled the Calendar API and added the v3 dlls to the project. I downloaded the p12 certificate and that's when the problems start.

The call to Google goes with a X509 cert but the way the .NET framework is built is that it uses a user temp folder. Since it's a shared host for the web server (GoDaddy), I cannot have the app pool identity modified. As a result, I'm getting this error:

System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

when calling:

X509Certificate2 certificate = new X509Certificate2(GoogleOAuth2CertificatePath,
                "notasecret", X509KeyStorageFlags.Exportable);

that cerificate var is then to be used in the google call:

ServiceAccountCredential credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(GoogleOAuth2EmailAddress)
                {
                    User = GoogleAccount,
                    Scopes = new[] { CalendarService.Scope.Calendar }
                }.FromCertificate(certificate));

... but I never get that far.

Question: is there a way to make the call differently, i.e. not to use a X509 certificate but JSON instead? Or can I get the x509 function to use a general temp location rather than a user location to which I have no access to since I can't change the identity in the app pool?

Since I'm completely stuck, any help would be appreciated.

Answers


One simple option which avoids needing to worry about file locations is to embed the certificate within your assembly. In Visual Studio, right-click on the file and show its properties. Under Build Action, pick "Embedded resource".

You should then be able to load the data with something like this:

// In a helper class somewhere...
private static byte[] LoadResourceContent(Type type, string resourceName)
{
    string fullName = type.Namespace + "." + resourceName;
    using (var stream = type.Assembly.GetManifestResourceStream(fullName)
    {
        var output = new MemoryStream();
        stream.CopyTo(output);
        return output.ToArray();
    }
}

Then:

byte[] data = ResourceHelper.LoadResourceContent(typeof(MyType), "Certificate.p12");
var certificate = new X509Certificate2(data, "notasecret", X509KeyStorageFlags.Exportable);

Here MyType is some type which is in the same folder as your resource.

Note that there are lots of different "web" project types in .NET... depending on the exact project type you're using, you may need to tweak this.


Need Your Help

Edit the values of the TableView from TextField

java javafx-2

Hi I am trying in the spirit of the example in http://code.makery.ch/java/javafx-2-tutorial-intro/ to make a similar application where the TableView values can be edited by a series of TextFields i...

Choosing which input to store where into an ArrayList? (Read from Scanner)

java arraylist java.util.scanner

I'm trying to read in a list of Integers from a scanner, using user input, and store all input into an ArrayList, except the last integer the user inputs, of which I want to store within an Integer, (