/// <summary> /// Processes the request based on the path. /// </summary> /// <param name="context">Contains the request and response.</param> public void ProcessRequest(HttpContext context) { // Get the code from the request POST body. string accessToken = context.Request.Params["access_token"]; string idToken = context.Request.Params["id_token"]; // Validate the ID token if (idToken != null) { JwtSecurityToken token = new JwtSecurityToken(idToken); JwtSecurityTokenHandler jsth = new JwtSecurityTokenHandler(); // Configure validation Byte[][] certBytes = getCertBytes(); Dictionary <String, X509Certificate2> certificates = new Dictionary <String, X509Certificate2>(); for (int i = 0; i < certBytes.Length; i++) { X509Certificate2 certificate = new X509Certificate2(certBytes[i]); certificates.Add(certificate.Thumbprint, certificate); } { // Set up token validation TokenValidationParameters tvp = new TokenValidationParameters() { ValidateActor = false, // check the profile ID ValidateAudience = (CLIENT_ID != "YOUR_VALID_CLIENT_ID"), // check the client ID ValidAudience = CLIENT_ID, ValidateIssuer = true, // check token came from Google ValidIssuer = "accounts.google.com", ValidateIssuerSigningKey = true, RequireSignedTokens = true, CertificateValidator = X509CertificateValidator.None, IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) => { return(identifier.Select(x => { // TODO: Consider returning null here if you have case sensitive JWTs. /*if (!certificates.ContainsKey(x.Id)) * { * return new X509SecurityKey(certificates[x.Id]); * }*/ if (certificates.ContainsKey(x.Id.ToUpper())) { return new X509SecurityKey(certificates[x.Id.ToUpper()]); } return null; }).First(x => x != null)); }, ValidateLifetime = true, RequireExpirationTime = true, ClockSkew = TimeSpan.FromHours(13) }; try { // Validate using the provider SecurityToken validatedToken; ClaimsPrincipal cp = jsth.ValidateToken(idToken, tvp, out validatedToken); if (cp != null) { its.valid = true; its.message = "Valid ID Token."; } } catch (Exception e) { // Multiple certificates are tested. if (its.valid != true) { its.message = "Invalid ID Token."; } if (e.Message.IndexOf("The token is expired") > 0) { // TODO: Check current time in the exception for clock skew. } } } // Get the Google+ id for this user from the "sub" claim. Claim[] claims = token.Claims.ToArray <Claim>(); for (int i = 0; i < claims.Length; i++) { if (claims[i].Type.Equals("sub")) { its.gplus_id = claims[i].Value; } } } // Use Tokeninfo to validate the user and the client. var tokeninfo_request = new Oauth2Service().Tokeninfo(); tokeninfo_request.AccessToken = accessToken; // Use Google as a trusted provider to validate the token. // Invalid values, including expired tokens, return 400 Tokeninfo tokeninfo = null; try { tokeninfo = tokeninfo_request.Execute(); if (tokeninfo.IssuedTo != CLIENT_ID) { ats.message = "Access Token not meant for this app."; } else { ats.valid = true; ats.message = "Valid Access Token."; ats.gplus_id = tokeninfo.UserId; } } catch (Exception stve) { ats.message = "Invalid Access Token: " + stve.Message; } // Use the wrapper to return JSON token_status_wrapper tsr = new token_status_wrapper(); tsr.id_token_status = its; tsr.access_token_status = ats; context.Response.StatusCode = 200; context.Response.ContentType = "text/json"; context.Response.Write(JsonConvert.SerializeObject(tsr)); }
/// <summary> /// Processes the request based on the path. /// </summary> /// <param name="context">Contains the request and response.</param> public async Task <WebApplication.Api.Controllers.AccountController.GoogleUserViewModel> VerifyGoogleAccessToken(string accessToken, string idToken) { // Validate the ID token if (idToken != null) { JWTSecurityToken token = new JWTSecurityToken(idToken); JWTSecurityTokenHandler jwt = new JWTSecurityTokenHandler(); // Configure validation Byte[][] certBytes = getCertBytes(); for (int i = 0; i < certBytes.Length; i++) { X509Certificate2 certificate = new X509Certificate2(certBytes[i]); X509SecurityToken certToken = new X509SecurityToken(certificate); // Set up token validation TokenValidationParameters tvp = new TokenValidationParameters(); tvp.AllowedAudience = CLIENT_ID; tvp.SigningToken = certToken; tvp.ValidIssuer = "accounts.google.com"; // Enable / disable tests tvp.ValidateNotBefore = false; tvp.ValidateExpiration = true; tvp.ValidateSignature = true; tvp.ValidateIssuer = true; // Account for clock skew. Look at current time when getting the message // "The token is expired" in try/catch block. // This is relative to GMT, for example, GMT-8 is: tvp.ClockSkewInSeconds = 3600 * 13; try { // Validate using the provider ClaimsPrincipal cp = jwt.ValidateToken(token, tvp); if (cp != null) { its.valid = true; its.message = "Valid ID Token."; its.aud = cp.FindFirst("aud").Value; its.azp = cp.FindFirst("azp").Value; its.email = cp.FindFirst("email").Value; its.sub = cp.FindFirst("sub").Value; } } catch (Exception e) { // Multiple certificates are tested. if (its.valid != true) { its.message = "Invalid ID Token."; } if (e.Message.IndexOf("The token is expired") > 0) { // TODO: Check current time in the exception for clock skew. } } } // Get the Google+ id for this user from the "gplus_id" claim. Claim[] claims = token.Claims.ToArray <Claim>(); for (int i = 0; i < claims.Length; i++) { if (claims[i].Type.Equals("gplus_id")) { its.gplus_id = claims[i].Value; } } } // Use the wrapper to return JSON token_status_wrapper tsr = new token_status_wrapper(); tsr.id_token_status = its; tsr.access_token_status = ats; if (its.valid) { WebApplication.Api.Controllers.AccountController.GoogleUserViewModel fbUser = new Api.Controllers.AccountController.GoogleUserViewModel(); fbUser.Email = its.email; fbUser.aud = its.aud; fbUser.azp = its.azp; fbUser.gplus_id = its.gplus_id; fbUser.sub = its.sub; return(fbUser); } return(null); }
/// <summary> /// Processes the request based on the path. /// </summary> /// <param name="context">Contains the request and response.</param> public void ProcessRequest(HttpContext context) { // Get the code from the request POST body. string accessToken = context.Request.Params["access_token"]; string idToken = context.Request.Params["id_token"]; // Validate the ID token if (idToken != null) { JwtSecurityToken token = new JwtSecurityToken(idToken); JwtSecurityTokenHandler jsth = new JwtSecurityTokenHandler(); // Configure validation Byte[][] certBytes = getCertBytes(); Dictionary<String, X509Certificate2> certificates = new Dictionary<String, X509Certificate2>(); for (int i = 0; i < certBytes.Length; i++) { X509Certificate2 certificate = new X509Certificate2(certBytes[i]); certificates.Add(certificate.Thumbprint, certificate); } { // Set up token validation TokenValidationParameters tvp = new TokenValidationParameters() { ValidateActor = false, // check the profile ID ValidateAudience = (CLIENT_ID != "YOUR_VALID_CLIENT_ID"), // check the client ID ValidAudience = CLIENT_ID, ValidateIssuer = true, // check token came from Google ValidIssuer = "accounts.google.com", ValidateIssuerSigningKey = true, RequireSignedTokens = true, CertificateValidator = X509CertificateValidator.None, IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) => { return identifier.Select(x => { // TODO: Consider returning null here if you have case sensitive JWTs. /*if (!certificates.ContainsKey(x.Id)) { return new X509SecurityKey(certificates[x.Id]); }*/ if (certificates.ContainsKey(x.Id.ToUpper())) { return new X509SecurityKey(certificates[x.Id.ToUpper()]); } return null; }).First(x => x != null); }, ValidateLifetime = true, RequireExpirationTime = true, ClockSkew = TimeSpan.FromHours(13) }; try { // Validate using the provider SecurityToken validatedToken; ClaimsPrincipal cp = jsth.ValidateToken(idToken, tvp, out validatedToken); if (cp != null) { its.valid = true; its.message = "Valid ID Token."; } } catch (Exception e) { // Multiple certificates are tested. if (its.valid != true) { its.message = "Invalid ID Token."; } if (e.Message.IndexOf("The token is expired") > 0) { // TODO: Check current time in the exception for clock skew. } } } // Get the Google+ id for this user from the "sub" claim. Claim[] claims = token.Claims.ToArray<Claim>(); for (int i = 0; i < claims.Length; i++) { if (claims[i].Type.Equals("sub")) { its.gplus_id = claims[i].Value; } } } // Use Tokeninfo to validate the user and the client. var tokeninfo_request = new Oauth2Service().Tokeninfo(); tokeninfo_request.AccessToken = accessToken; // Use Google as a trusted provider to validate the token. // Invalid values, including expired tokens, return 400 Tokeninfo tokeninfo = null; try { tokeninfo = tokeninfo_request.Execute(); if (tokeninfo.IssuedTo != CLIENT_ID) { ats.message = "Access Token not meant for this app."; } else { ats.valid = true; ats.message = "Valid Access Token."; ats.gplus_id = tokeninfo.UserId; } } catch (Exception stve) { ats.message = "Invalid Access Token: " + stve.Message; } // Use the wrapper to return JSON token_status_wrapper tsr = new token_status_wrapper(); tsr.id_token_status = its; tsr.access_token_status = ats; context.Response.StatusCode = 200; context.Response.ContentType = "text/json"; context.Response.Write(JsonConvert.SerializeObject(tsr)); }
/// <summary> /// Processes the request based on the path. /// </summary> /// <param name="context">Contains the request and response.</param> public void ProcessRequest(HttpContext context) { // Get the code from the request POST body. string accessToken = context.Request.Params["access_token"]; string idToken = context.Request.Params["id_token"]; // Validate the ID token if (idToken != null) { JWTSecurityToken token = new JWTSecurityToken(idToken); JWTSecurityTokenHandler jwt = new JWTSecurityTokenHandler(); // Configure validation Byte[][] certBytes = getCertBytes(); for (int i = 0; i < certBytes.Length; i++) { X509Certificate2 certificate = new X509Certificate2(certBytes[i]); X509SecurityToken certToken = new X509SecurityToken(certificate); // Set up token validation TokenValidationParameters tvp = new TokenValidationParameters(); tvp.AllowedAudience = CLIENT_ID; tvp.SigningToken = certToken; tvp.ValidIssuer = "accounts.google.com"; // Enable / disable tests tvp.ValidateNotBefore = false; tvp.ValidateExpiration = true; tvp.ValidateSignature = true; tvp.ValidateIssuer = true; // Account for clock skew. Look at current time when getting the message // "The token is expired" in try/catch block. // This is relative to GMT, for example, GMT-8 is: tvp.ClockSkewInSeconds = 3600 * 13; try { // Validate using the provider ClaimsPrincipal cp = jwt.ValidateToken(token, tvp); if (cp != null) { its.valid = true; its.message = "Valid ID Token."; } } catch (Exception e) { // Multiple certificates are tested. if (its.valid != true) { its.message = "Invalid ID Token."; } if (e.Message.IndexOf("The token is expired") > 0) { // TODO: Check current time in the exception for clock skew. } } } // Get the Google+ id for this user from the "sub" claim. Claim[] claims = token.Claims.ToArray<Claim>(); for (int i = 0; i < claims.Length; i++) { if (claims[i].Type.Equals("sub")) { its.gplus_id = claims[i].Value; } } } // Use Tokeninfo to validate the user and the client. var tokeninfo_request = new Oauth2Service().Tokeninfo(); tokeninfo_request.Access_token = accessToken; // Use Google as a trusted provider to validate the token. // Invalid values, including expired tokens, return 400 Tokeninfo tokeninfo = null; try { tokeninfo = tokeninfo_request.Fetch(); if (tokeninfo.Issued_to != CLIENT_ID){ ats.message = "Access Token not meant for this app."; }else{ ats.valid = true; ats.message = "Valid Access Token."; ats.gplus_id = tokeninfo.User_id; } } catch (Exception stve) { ats.message = "Invalid Access Token."; } // Use the wrapper to return JSON token_status_wrapper tsr = new token_status_wrapper(); tsr.id_token_status = its; tsr.access_token_status = ats; context.Response.StatusCode = 200; context.Response.ContentType = "text/json"; context.Response.Write(JsonConvert.SerializeObject(tsr)); }