/// <summary> /// Token request object initilization to retreive user information /// </summary> /// <param name="accessToken"></param> /// <returns></returns> public object GetTokenInfo(string accessToken) { Oauth2Service.TokeninfoRequest tokeninfoRequest = new Oauth2Service().Tokeninfo(); Google.Apis.Discovery.Parameter accessType = new Google.Apis.Discovery.Parameter { DefaultValue = GoogleReqestParameters.offline.ToString(), Name = GoogleReqestParameters.access_type.ToString() }; tokeninfoRequest.RequestParameters.Add("AccessType", accessType); tokeninfoRequest.AccessToken = accessToken; Tokeninfo tokeninfo = tokeninfoRequest.Execute(); return(tokeninfo); }
/// <summary> /// Is token expired or not /// </summary> /// <param name="accessToken"></param> /// <returns></returns> public bool IsTokenExpired(string accessToken) { Tokeninfo tokeninfo = null; Oauth2Service.TokeninfoRequest tokeninfoRequest = new Oauth2Service().Tokeninfo(); Google.Apis.Discovery.Parameter accessType = new Google.Apis.Discovery.Parameter { DefaultValue = GoogleReqestParameters.offline.ToString(), Name = GoogleReqestParameters.access_type.ToString() }; tokeninfoRequest.RequestParameters.Add("AccessType", accessType); tokeninfoRequest.AccessToken = accessToken; try { tokeninfo = tokeninfoRequest.Execute(); } catch (Exception) { // ignored } return(tokeninfo == 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 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)); }
public User ConnectViaSocialNetwork(User user, string socialNetworkName) { var _socialNetworkClientId = ""; var _socialNetworkUserId = ""; var _issuedTo = ""; if (object.Equals(socialNetworkName, "Google")) { _socialNetworkClientId = ConfigurationManager.AppSettings["GoogleClientKey"]; var tokeninfo_request = new Oauth2Service().Tokeninfo(); tokeninfo_request.IdToken = user.SocialNetworkIdToken; var tokeninfo = tokeninfo_request.Execute(); _socialNetworkUserId = tokeninfo.UserId; _issuedTo = tokeninfo.IssuedTo; } else { //Social network does not exist return(null); } if (object.Equals(user.SocialNetworkUserId, _socialNetworkUserId) && object.Equals(_socialNetworkClientId, _issuedTo)) { // Credentials match. // Check if google user ID already exists in the system. string currentEmail = userJdbc.GetEmailBySocialNetworkUserId(socialNetworkName, user.SocialNetworkUserId); if (String.IsNullOrWhiteSpace(currentEmail)) { // Google user ID does not exist in the system. // If email already exists but has not been confirmed, delete it. userJdbc.RemoveUserIfActivationExpired((string)user.Emails[0]); //Generate random alphanumeric password const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var random = new Random(); string randomPass = new string(Enumerable.Repeat(chars, 8).Select(s => s[random.Next(s.Length)]).ToArray()); user.Password = SecurityUtils.CreatePasswordHash(randomPass); //Make sure username is not null if (String.IsNullOrWhiteSpace(user.Username)) { var mail = new MailAddress((string)user.Emails[0]); user.Username = mail.User; } //Set profile pic if (String.IsNullOrWhiteSpace(user.ProfilePicURL)) { user.ProfilePicURL = Utilities.WS_API_URL + "images/profile_pics/profile_default.jpg"; } //Create New User (or update existing one) int userId = userJdbc.CreateUserViaSocialNetwork(user, socialNetworkName); if (userId <= 0) { return(null); } } else if (!object.Equals(currentEmail, user.Emails[0])) { // Google user ID already exists in the system but email has changed (probably a user changed email on social network). // If new email already exists but has not been confirmed, delete it. userJdbc.RemoveUserIfActivationExpired((string)user.Emails[0]); // Add another email to the user. userJdbc.UpdateSocialNetworkEmail(socialNetworkName, user.SocialNetworkUserId, (string)user.Emails[0]); } // Return user. return(userJdbc.GetUserByEmail((string)user.Emails[0])); } else { // Credentials did not match. return(null); } }