I have a customer that is trying to access their calendars from our web application. Everything works for all of our other customers, so I am not sure what is different here except this customer is in Australia and using a non gmail.com email address.
The customer is able to authorize our application and we do get a oauth token for the user. We request calendar access and the customer granted it. When we request a list of all of the calendars, we get the invalid grant message.
Below is the code that we use to access their calendars. The method being called is GetAllWritableCalendars.
public class GoogleCalendarAdapter : ICalendarAdapter {
#region attributes
private readonly ISiteAuthTokenQueryRepository _tokenRepo;
private readonly GoogleCalendarSettings _settings;
private const string APPNAME = "SomeAppName";
private const string ACL_OWNER = "owner";
private const string ACL_WRITER = "writer";
#endregion
#region ctor
public GoogleCalendarAdapter(ISiteAuthTokenQueryRepository tokenRepo,
GoogleCalendarSettings settings) {
_tokenRepo = tokenRepo;
_settings = settings;
}
#endregion
#region methods
private GoogleAuthorizationCodeFlow BuildAuthorizationCodeFlow() {
return new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer() {
ClientSecrets = BuildClientSecrets(),
Scopes = BuildScopeList()
});
}
private CalendarService BuildCalendarService(SiteAuthToken token) {
return new CalendarService(new BaseClientService.Initializer() {
ApplicationName = APPNAME,
HttpClientInitializer = BuildUserCredential(token)
});
}
private ClientSecrets BuildClientSecrets() {
return new ClientSecrets() {
ClientId = _settings.ClientId,
ClientSecret = _settings.ClientSecret
};
}
private string[] BuildScopeList() {
return new [] { CalendarService.Scope.Calendar };
}
private UserCredential BuildUserCredential(SiteAuthToken token) {
TokenResponse responseToken = new TokenResponse() {
AccessToken = token.AccessToken,
RefreshToken = token.RefreshToken
};
return new UserCredential(BuildAuthorizationCodeFlow(), APPNAME, responseToken);
}
public async Task<List<Cal>> GetAllWritableCalendars(Guid siteGuid) {
SiteAuthToken token = await GetToken(siteGuid);
CalendarService svc = BuildCalendarService(token);
IList<CalendarListEntry> calendars = svc.CalendarList
.List()
.Execute()
.Items;
return calendars.Where(c => c.AccessRole.Equals(ACL_OWNER, StringComparison.CurrentCultureIgnoreCase) ||
c.AccessRole.Equals(ACL_WRITER, StringComparison.CurrentCultureIgnoreCase))
.Select(c => new Cal() {
Id = c.Id,
Name = c.Summary
})
.OrderBy(o => o.Name)
.ToList();
}
private async Task<SiteAuthToken> GetToken(Guid siteGuid) {
SiteAuthToken retVal = await _tokenRepo.GetSiteAuthToken(siteGuid);
if (retVal == null) {
throw new ApplicationException($"Could not find a SiteAuthToken for specified site (SiteGuid: {siteGuid})");
}
return retVal;
}
#endregion