Google OAuth 2.0 in .NET4 fails to create ServiceAccount on medium trust level server

222 views Asked by At

I would like to read some calendar events inside a .NET4.0 web service. Because no user is involved I used a service account authorization method. It works perfectly on my local machine. But when I want to install it on the hosting server I get permission exceptions during creating the certificate. The cause is the medium trust level of the web service. But that level is common on hosting servers. Are there other ways to access the api that would work on a medium trust level server?

Here is my internal service code:

public static List<CalendarEventObject> GetEvents( string calendarName, int maxToGet, out string error )
    {
        string done = "";
        error = "";

        try
        {
            // access google api with service account
            String serviceAccountEmail = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com";

            var p12File = System.Web.HttpContext.Current.Server.MapPath( "./bin/MyAppsServiceAccountFileFromGoogleDeveoperConsole.p12" );

            done += "maped certificate: " + p12File;

            // this needs System.Security.Permissions.KeyContainerPermission permission, 
            // that is not inside medium trust (nor inside high trust)
            var certificate = new X509Certificate2( p12File
                , "notasecret"
                , X509KeyStorageFlags.MachineKeySet |
                  X509KeyStorageFlags.PersistKeySet |
                  X509KeyStorageFlags.Exportable );         // tried several storage flags with no success            

            ServiceAccountCredential credential = new ServiceAccountCredential(
            new ServiceAccountCredential.Initializer( serviceAccountEmail )
            {
                Scopes = new[] { CalendarService.Scope.Calendar }
            }.FromCertificate( certificate ) );

            // Create the service.
            var service = new CalendarService( new BaseClientService.Initializer( )
            {
                HttpClientInitializer = credential,
                ApplicationName = "MyCalendarReader",
            } );

            done += "service created ";

            // Fetch the list of calendar list
            var list = service.CalendarList.List( ).Execute( ).Items;

            done += "CalendarList loaded ";

            if ( list.Count == 0 ) throw new Exception( "CalendarList returned none" );

            bool found = false;
            List<string> calendars = new List<string>( );
            foreach ( var calendarListEntry in list )
            {
                calendars.Add( calendarListEntry.Summary );
                if ( calendarListEntry.Summary == calendarName )
                {
                    found = true;
                    return ExtractEvents( service, calendarListEntry, maxToGet );
                }
            }

            if ( !found )
            {
                throw new Exception( "No matching calendar: " + String.Join( ";", calendars ) );
            }
        }
        catch ( Exception ex )
        {
            error = String.Format( "\nDone:{0}\n msg:{1}\n inner:{2}\n stack:{3}", done, ex.Message, ex.InnerException != null ? ex.InnerException.Message : "none", ex.StackTrace );
        }

        return new List<CalendarEventObject>( );
    }
1

There are 1 answers

1
Mihai Dinculescu On

I don't think that there's a solution to your problem other than changing the trust level.

The "medium trust level is common on hosting servers" statement, while it used to be true - it's not anymore.

Medium Trust has been made obsolete by the ASP.NET team. The main reason is that reflection started to be used a lot more in the last couple of years. To do reflection in Medium Trust is almost impossible.

Your best solution, especially for the long run, is to tell this to your hosting provider and to just find another provider in case they refuse to offer you Full Trust.

PS: ASP.NET Partial Trust does not guarantee application isolation