private bool ValidateToken(string identityToken) { if (AppController.keys != null) { //IdentityToken if (identityToken != null) { //Split the identityToken to get Header and Payload string[] splitValues = identityToken.Split('.'); if (splitValues[0] != null) { //Decode header var headerJson = Encoding.UTF8.GetString(Base64Url.Decode(splitValues[0].ToString())); //Deserilaize headerData IdTokenHeader headerData = JsonConvert.DeserializeObject <IdTokenHeader>(headerJson); //Verify if the key id of the key used to sign the payload is not null if (headerData.Kid == null) { return(false); } //Verify if the hashing alg used to sign the payload is not null if (headerData.Alg == null) { return(false); } } if (splitValues[1] != null) { //Decode payload var payloadJson = Encoding.UTF8.GetString(Base64Url.Decode(splitValues[1].ToString())); payloadData = JsonConvert.DeserializeObject <IdTokenJWTClaimTypes>(payloadJson); //Verify Aud matches ClientId if (payloadData.Aud != null) { if (payloadData.Aud[0].ToString() != AppController.clientid) { return(false); } } else { return(false); } //Verify Authtime matches the time the ID token was authorized. if (payloadData.Auth_time == null) { return(false); } //Verify exp matches the time the ID token expires, represented in Unix time (integer seconds). if (payloadData.Exp != null) { long expiration = Convert.ToInt64(payloadData.Exp); long currentEpochTime = EpochTimeExtensions.ToEpochTime(DateTime.UtcNow); //Verify the ID expiration time with what expiry time you have calculated and saved in your application //If they are equal then it means IdToken has expired if ((expiration - currentEpochTime) <= 0) { return(false); } } //Verify Iat matches the time the ID token was issued, represented in Unix time (integer seconds). if (payloadData.Iat == null) { return(false); } //verify Iss matches the issuer identifier for the issuer of the response. if (payloadData.Iss != null) { if (payloadData.Iss.ToString() != AppController.issuerEndpoint) { return(false); } } else { return(false); } //Verify sub. Sub is an identifier for the user, unique among all Intuit accounts and never reused. //An Intuit account can have multiple emails at different points in time, but the sub value is never changed. //Use sub within your application as the unique-identifier key for the user. if (payloadData.Sub == null) { return(false); } } //Use external lib to decode mod and expo value and generte hashes RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //Read values of n and e from discovery document. rsa.ImportParameters( new RSAParameters() { //Read values from discovery document Modulus = Base64Url.Decode(AppController.mod), Exponent = Base64Url.Decode(AppController.expo) }); //Verify Siganture hash matches the signed concatenation of the encoded header and the encoded payload with the specified algorithm SHA256 sha256 = SHA256.Create(); byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(splitValues[0] + '.' + splitValues[1])); RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa); rsaDeformatter.SetHashAlgorithm("SHA256"); if (rsaDeformatter.VerifySignature(hash, Base64Url.Decode(splitValues[2]))) { //identityToken is valid return(true); } else { //identityToken is not valid return(false); } } else { //identityToken is not valid return(false); } } else { //Missing mod and expo values return(false); } }
/// <summary> /// Determines whether [is identifier token valid] [the specified identifier token]. /// </summary> /// <param name="idToken">The identifier token.</param> /// <returns> /// <c>true</c> if [is identifier token valid] [the specified identifier token]; otherwise, <c>false</c>. /// </returns> /// <exception cref="System.ArgumentNullException">idToken</exception> /// <exception cref="System.Exception">Error validating identity token:</exception> public bool IsValidIdToken(string idToken) { if (string.IsNullOrEmpty(idToken)) { throw new ArgumentNullException("idToken"); } try { string[] splitValues = idToken.Split('.'); if (splitValues[0] != null) { //decode header var headerJson = Encoding.UTF8.GetString(FromBase64Url(splitValues[0].ToString())); IdTokenHeader headerData = JsonConvert.DeserializeObject <IdTokenHeader>(headerJson); //Verify if the key id of the key used to sign the payload is not null if (headerData.Kid == null) { return(false); } //Verify if the hashing alg used to sign the payload is not null if (headerData.Alg == null) { return(false); } } if (splitValues[1] != null) { //decode payload var payloadJson = Encoding.UTF8.GetString(FromBase64Url(splitValues[1].ToString())); IdTokenPayload payloadData = JsonConvert.DeserializeObject <IdTokenPayload>(payloadJson); //verify aud matches clientId if (payloadData.Aud != null) { if (payloadData.Aud[0].ToString() != ClientId) { return(false); } } else { return(false); } //verify authtime matches the time the ID token was authorized. if (payloadData.Auth_time == null) { return(false); } //verify exp matches the time the ID token expires, represented in Unix time (integer seconds). if (payloadData.Exp != null) { ulong expiration = Convert.ToUInt64(payloadData.Exp); TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks); TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks; ulong unixTime = Convert.ToUInt64(unixTicks.Milliseconds); //Verify the expiration time with what you expiry time have calculated and saved in your application if ((expiration - unixTime) <= 0) { return(false); } } else { return(false); } //Verify iat matches the time the ID token was issued, represented in Unix time (integer seconds). if (payloadData.Iat == null) { return(false); } //verify iss matches the issuer identifier for the issuer of the response. if (payloadData.Iss != null) { if (payloadData.Iss.ToString() != issuerUrl) { return(false); } } else { return(false); } //verify sub. sub is an identifier for the user, unique among all Intuit accounts and never reused. //An Intuit account can have multiple emails at different points in time, but the sub value is never changed. //Use sub within your application as the unique-identifier key for the user. if (payloadData.Sub == null) { return(false); } } //verify Siganture matches the sigend concatenation of the encoded header and the encoded payload with the specified algorithm RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //Read values of n and e from discovery document. rsa.ImportParameters( new RSAParameters() { //Read values from discovery document Modulus = FromBase64Url(mod), Exponent = FromBase64Url(expo) }); //verify using RSA signature SHA256 sha256 = SHA256.Create(); byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(splitValues[0] + '.' + splitValues[1])); RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa); rsaDeformatter.SetHashAlgorithm("SHA256"); if (rsaDeformatter.VerifySignature(hash, FromBase64Url(splitValues[2]))) { return(true); } else { return(false); } } catch (Exception exception) { throw new Exception("Error validating identity token: ", exception); } }