public string getAuthenticationToken(GoogleOAuth2Config config)
        {
            var logger = new Logger("GoogleService.Authenticator");
            var registry = new Windows.Registry.Helper(config.ApiAccessKey);

            var expiryTime = registry.getExpireTime();
            if (String.IsNullOrEmpty(expiryTime) || expiryTime.Length < 4)
            {
                expiryTime = FALLBACK_EXPIRY_DATE;
            }
            var ExpireDateTime = Convert.ToDateTime(expiryTime);
            var ExpireTimeNow = DateTime.UtcNow;
            TimeSpan span = ExpireDateTime - ExpireTimeNow;
            double iExpireLeft = span.TotalSeconds;

            logger.Write(0, "Expire time left (sec): " + iExpireLeft);

            if (iExpireLeft < 60) {
                logger.Write(0, "Requesting authentication token from server...");
                var tokenObject = requestAuthenticationToken(config);

                if (tokenObject.access_token == null)
                    throw new NullReferenceException("access_token is null");

                registry.putValue(Helper.SubKey.TokenName, tokenObject.access_token);
                registry.putInterval(Helper.SubKey.ExpireTime, tokenObject.expires_in);
                logger.Write(0, "Token Received successfully");
            }

            string accessToken = registry.getAccessToken();
            return accessToken;
        }
        public Token requestAuthenticationToken(GoogleOAuth2Config config)
        {
            var certificate = new X509Certificate2(
               config.DirectoryName + "\\" + config.PrivateKeyFilename,
               config.CertificatePassword);

            var header = new { typ = HEADER_TYPE, alg = HEADER_ALGO };
            // claimset
            var times = GetExpiryAndIssueDate();
            var claimset = new
            {
                iss = config.ServiceAccountEmail,
                scope = SCOPE,
                aud = AUDIENCE,
                iat = times[0],
                exp = times[1],
            };

            // encoded header
            var headerSerialized = JsonConvert.SerializeObject(header);
            var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
            var headerEncoded = Base64UrlEncode(headerBytes);

            // encoded claimset
            var claimsetSerialized = JsonConvert.SerializeObject(claimset);
            var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
            var claimsetEncoded = Base64UrlEncode(claimsetBytes);

            // input
            var input = headerEncoded + "." + claimsetEncoded;
            var inputBytes = Encoding.UTF8.GetBytes(input);

            // signature
            var rsa = certificate.PrivateKey as RSACryptoServiceProvider;
            var cspParam = new CspParameters
            {
                KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
                KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2
            };
            var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false };
            var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
            var signatureEncoded = Base64UrlEncode(signatureBytes);

            // jwt
            var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;

            var client = new HttpClient();
            var uri = "https://accounts.google.com/o/oauth2/token";
            var post = new Dictionary<string, string>
                    {
                        {"assertion", jwt},
                        {"grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"}
                    };
            var content = new FormUrlEncodedContent(post);
            //Console.WriteLine(content.ReadAsStringAsync().Result);
            var result = client.PostAsync(uri, content).Result;

            Token tokenObject = JsonConvert.DeserializeObject<Token>
                (result.Content.ReadAsStringAsync().Result);

            return tokenObject;
        }