Inserting accounts into the Mirror API using a service account returns an "invalid_grant" error
I am using the Mirror API .NET Library with a google service account to do third party authentication through the MyGlass app. I am following the Authentication for GDK Glassware documentation to authenticate my users on the server side and then insert the account.
When I try to insert a new account using the Mirror API, I get an OAuth: "invalid_grant" error:
Stack trace:
Google.Apis.Auth.OAuth2.Responses.TokenResponseException was unhandled by user ID HResult = -2146233088 Message = Error: "invalid_grant", Description: ", Uri:" "Source = Google.Apis
at Google.Apis.Requests.ClientServiceRequest`1.Execute () at C: \ code \ google.com \ google-api-DotNet-client \ default_182 \ Tools \ Google.Apis.Release \ bin \ Debug \ output \ default \ Src \ GoogleApis \ Apis \ requests \ ClientServiceRequest.cs: line 96 \ r \ n
It is expanded and called by the Execute () function in ClientServiceRequest.cs . Line 96.
Source:
const string password = "notasecret";
X509Certificate2 certificateToExport = new X509Certificate2(HostingEnvironment.MapPath("/Path/To/Certificate.p12"), password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var rsa = (RSACryptoServiceProvider)certificateToExport.PrivateKey;
// Have to export the provider or you get an "Invalid Algorithm" error when
// trying to sign the request.
RSACryptoServiceProvider cryptoProvider = new RSACryptoServiceProvider();
cryptoProvider.ImportParameters(rsa.ExportParameters(true));
var serviceAccountCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(id: "MYCLIENTID.apps.googleusercontent.com")
{
Key = cryptoProvider,
Scopes = new List<string>() { "https://www.googleapis.com/auth/glass.thirdpartyauth" },
User = "MYCLIENTID@developer.gserviceaccount.com"
});
var mirrorService = new MirrorService(new BaseClientService.Initializer() { HttpClientInitializer = serviceAccountCredential });
Account account = new Account() { AuthTokens = new AuthToken[] { new AuthToken() { AuthTokenValue = sessionKey, Type = "sessionKey" } } };
// Exception thrown here
Account insertedAccount = mirrorService.Accounts.Insert(account, userToken: userToken, accountType: "example.com", accountName: accountName).Execute();
Some things I've checked twice and three times:
- I have the correct customer ID and email address.
- I have provided scope: https://www.googleapis.com/auth/glass.thirdpartyauth .
- The UserToken that was passed to me as a request parameter using the MyGlass webview is returned back to the MirrorAPI.
- I sign the request with a certificate provided to me by Google.
- MyGlass is using correct URL redirect url
- Google Analytics documentation says "invalid_grant" error:
- Your server clock is out of sync with NTP.
- Refresh token limit exceeded.
Server sync is in sync. This happens on multiple machines. Will examine if the token has been exceeded. I was under the impression that the API library would handle updates for me.
I feel like I have completely misunderstood something (probably). I would appreciate it if someone pointed out that I am wrong here.
source to share
From the chat thread, the problem was caused by a service account validation error due to invalid data passed in the class ServiceAccountCredential
.
The code snippet used in the original question should be corrected with:
var serviceAccountCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(id: "MYCLIENTID@developer.gserviceaccount.com")
{
Key = cryptoProvider,
Scopes = new List<string>() { "https://www.googleapis.com/auth/glass.thirdpartyauth" }
});
source to share
Make sure you submit your utensils to https://developers.google.com/glass/distribute/form . Be sure to indicate that you also want to add accounts and tell them the account type for your app. I remember having to do this in my application before I could add accounts. You think it will be in their documentation, but I don't believe it is.
source to share