Linus Nikander
Linus Nikander

Reputation: 81

Creating a ServiceAccountCredential for a user from a Systems account

I use the following code to act on behalf of a user through a System-login (domain-wide authenticated). The only example I found which accomplishes this uses reflection to set the user. I know this isn't the proper way to accomplish this so I was wondering if someone could help me out with an example of how this should be solved

ServiceAccountCredential credential = 
    GoogleCredential.FromJson(GOOGLE_SYSTEM_USER_AUTH_INFORMATION)
        .CreateScoped(Scopes)
        .UnderlyingCredential as ServiceAccountCredential;

var userField = typeof(ServiceAccountCredential).GetField("user", 
BindingFlags.NonPublic | BindingFlags.Instance);
userField?.SetValue(credential, GOOGLE_CALENDAR_USERNAME); //Act in the guise of the normal user GOOGLE_CALENDAR_USERNAME


service = new CalendarService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential,
    ApplicationName = ApplicationName, 
});

Upvotes: 4

Views: 2042

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1503180

The original answer below was brittle due to assuming knowledge of which properties were required. It's significantly simpler now:

var credential = GoogleCredential.FromJson(GOOGLE_SYSTEM_USER_AUTH_INFORMATION)
    .CreateScoped(Scopes)
    .CreateWithUser(GOOGLE_CALENDAR_USERNAME);

Here's how I'd do it, setting both the scopes and the new user at the same time via the ServiceAccountCredential.Initializer:

ServiceAccountCredential original = (ServiceAccountCredential)
    GoogleCredential.FromJson(GOOGLE_SYSTEM_USER_AUTH_INFORMATION).UnderlyingCredential;

var initializer = new ServiceAccountCredential.Initializer(original.Id)
{
    User = GOOGLE_CALENDAR_USERNAME,
    Key = original.Key,
    Scopes = Scopes
};
var credentialForUser = new ServiceAccountCredential(initializer);

Now that gives you a ServiceAccountCredential rather than a GoogleCredential. That's what your current code uses, so it should be okay - but it would be nice if there were a simple way of getting a GoogleCredential for this too. We should make this all simpler - I've filed an issue for that.

Upvotes: 4

Related Questions