Retrieving JWT from Google+ will not validate - c#

I'm currently struggling with the a JWT I'm receiving from google+ log in service. I'm trying to make several authentication services compatible with my solution, but the JWT I'm getting from google doesn't seem to work the same way as the one I retrieve from Auth0.
Made a test to simulate the behavior:
public void TestMethod1()
{
var handler = new JwtTokensConfig.MyJwtSecurityTokenHandler();
const string encodedToken = <JWT>;
const string issuer = "accounts.google.com";
IIssuerSecurityTokenProvider provider = new SymmetricKeyIssuerSecurityTokenProvider(issuer,
new FederationConfig.SymetricKey {Base64Url = <SECRET>}.Bytes);
var securityToken = provider.SecurityTokens.First();
var validationParameters = new TokenValidationParameters()
{
ValidIssuer = issuer,
AllowedAudience = "<CLIENTID>,
SigningToken = securityToken
};
handler.ValidateToken(encodedToken, validationParameters);
}
Removed the sensitive data and replaced it with <>.
When I'm running this test, I receive the following error:
Test method UnitTestProject1.UnitTest1.TestMethod1 threw exception:
System.IdentityModel.Tokens.SecurityTokenValidationException: Jwt10316: Signature validation failed. Keys tried: 'System.IdentityModel.Tokens.InMemorySymmetricSecurityKey'.
Exceptions caught:
'System.InvalidOperationException: Jwt10532: SymmetricSecurityKey.GetKeyedHashAlgorithm( 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' ) threw and exception.
SymmetricSecurityKey: 'System.IdentityModel.Tokens.InMemorySymmetricSecurityKey'
SignatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', check to make sure the SignatureAlgorithm is supported.
Exception: 'System.InvalidOperationException: Crypto algorithm 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' not supported in this context.
at System.IdentityModel.CryptoHelper.CreateKeyedHashAlgorithm(Byte[] key, String algorithm)
at System.IdentityModel.Tokens.InMemorySymmetricSecurityKey.GetKeyedHashAlgorithm(String algorithm)
at System.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SymmetricSecurityKey key, String algorithm)'. ---> System.InvalidOperationException: Crypto algorithm 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' not supported in this context.
at System.IdentityModel.CryptoHelper.CreateKeyedHashAlgorithm(Byte[] key, String algorithm)
at System.IdentityModel.Tokens.InMemorySymmetricSecurityKey.GetKeyedHashAlgorithm(String algorithm)
at System.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SymmetricSecurityKey key, String algorithm)
--- End of inner exception stack trace ---
at System.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SymmetricSecurityKey key, String algorithm)
at System.IdentityModel.Tokens.SignatureProviderFactory.CreateProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at System.IdentityModel.Tokens.SignatureProviderFactory.CreateForVerifying(SecurityKey key, String algorithm)
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(SecurityKey key, String algorithm, Byte[] encodedBytes, Byte[] signature)
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(JwtSecurityToken jwt, Byte[] encodedBytes, Byte[] signatureBytes, IEnumerable`1 signingTokens)
I'm suspecting that this might be related to the fact that the Google JWT returns with the decoding algorithm of "alg": "RS256", but I can't say for sure. The one I get from Auth0 works just fine.
The way I'm getting the token is by using the google+ sign in method (https://developers.google.com/+/web/signin/javascript-flow) then passing the JWT to a different callback site. This page has been added to my REDIRECT URIS on the google project.
If you see anything that is missing, let me know! Any feedback is greatly appreciated.

Related

Youtube Pubsub Validate signature

I am creating an open Source Project which uses the youtube pubsub api to get notifications on video uploads. I want to verify that the request does come from youtube and not from a 3rd Party by checking the HMAC SHA1 Signature as described.
So, every time 1 Run my Program, I will generate a Secret later, to debug the problem, i use "test" as my secret string.
I use the following method to check if the provided signature is valid
public static bool Check(string body, string signature)
{
using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(Secret)))
{
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
var hash = Encoding.UTF8.GetString(hashBytes);
Console.WriteLine("Computed Hash " + hash);
return signature.Equals(hash);
}
}
Where body is the request body and signature is a value provided in the request header.
According to https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html#rfc.section.7
If the subscriber supplied a value for hub.secret in their subscription request, the hub MUST generate an HMAC signature of the payload and include that signature in the request headers of the content distribution request. The X-Hub-Signature header's value MUST be in the form sha1=signature where signature is a 40-byte, hexadecimal representation of a SHA1 signature [RFC3174]. The signature MUST be computed using the HMAC algorithm [RFC2104] with the request body as the data and the hub.secret as the key.
I supply my Secret as hub.secret in my subscription request.
So if I understand it correctly, the hub SHOULD use that secret to generate a HMACSHA1 of the payload -> the body.
I want to regenerate the HMAC and should get the same value, right?
It does not work. Also the computed hash value logged by console.WriteLine is something completely different, not alphabetic characters at all, so I guess it might be a problem with the encoding, but I can't figure it out. Thanks for all the help!
The documentation says "where signature is a 40-byte, hexadecimal representation" so instead of converting hashBytes to an UTF8 string you should convert it to a hexadecimal string.
public static bool Check(string body, string signature)
{
using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(Secret)))
{
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
var hash = Convert.ToHexString(hashBytes).ToLowerInvariant();
Console.WriteLine("Computed Hash " + hash);
return signature.Equals(hash);
}
}

Google Cloud Endpoints Invalid JWT signature (.NET Core) [duplicate]

I am using the following code, which I borrowed originally from the jwt-dotnet github page
private static string CreateToken(UserPrincipal principal)
{
/*
* https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
* http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
*/
var key = ConfigurationManager.AppSettings["jwt-key"];
var claims = new Dictionary<string, string>()
{
{ClaimTypes.Name, "Rainbow Dash" },
{ClaimTypes.WindowsAccountName, "RDash"}
};
var algorithm = new HMACSHA256Algorithm();
var serializer = new JsonNetSerializer();
var urlEncoder = new JwtBase64UrlEncoder();
var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(claims, key);
return token;
}
The above code generates the following token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiUmFpbmJvdyBEYXNoIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy93aW5kb3dzYWNjb3VudG5hbWUiOiJSRGFzaCJ9.5WZWDJ0pvTe6QLjVNUeTfZicX_wSsk1dtYvXUbpiOiw
So, I hopped over to jwt.io to test my token. I'm told I have an invalid signature.
How do I give it a valid 'signature'? I don't understand what my JWT is missing.
The tool over JWT.io can verify the digital signature of your token if you give it the secret signing key you used while creating a token:
And from looking at your code it's the value contained in your:
ConfigurationManager.AppSettings["jwt-key"];
Just input the value inside the "secret" text box and if the signature of the token matches the one calculated by JWT.io then you'll get a message saying that the signature is valid.

Validate Google idToken - certificate verification fails using RSACryptoServiceProvider

I am building login workflow using Google for user. Once user is authenticated, I call GetAuthResponse to get idToken.
https://developers.google.com/identity/sign-in/web/backend-auth
Now, I need to verify certificate against Google certificate. I am using JwtSecurityToken(C#) for the same.
I am referencing for verification - http://blogs.msdn.com/b/alejacma/archive/2008/06/25/how-to-sign-and-verify-the-signature-with-net-and-a-certificate-c.aspx
Issue is - I always gets false from VerifyHash. As, VerifyHash returns just false without any reason, I am not able to find way to verify whether idToken is
valid or not. My code is given below
String strID = ""; // idToken received from Google AuthResponse
JwtSecurityToken token = new JwtSecurityToken(strID);
byte[] text = GetHash(token.RawData);
SHA256Cng sha1 = new SHA256Cng();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);
byte[] signature = Encoding.Unicode.GetBytes(token.RawSignature);
// Modulus and exponent value from https://www.googleapis.com/oauth2/v2/certs - second set of keys
String modulus = "uHzGq7cMlx21nydbz9VsW1PItetb9mqvnpLp_8E3Knyk-mjv9DlaPhKGHYlJfHYGzKa2190C5vfsLLb1MIeGfdAv7ftpFsanIWawl8Zo0g-l0m7T2yG_7XerqcVK91lFifeJtgxKI86cPdZkgRy6DaYxMuAwAlhvpi3_UhPvsIwi7M6mxE8nUNpUWodh_YjJNu3wOxKDwbBZuRV2itjY6Z7RjFgJt1CsKF-QjqSVvWjAl0LaCaeMS_8yae0ln5YNeS8rAb6xkmcOuYeyhYsiBzwLRvgpXzEVLjLr631Z99oUHTpP9vWJDpGhfkrClkbmdtZ-ZCwX-eFW6ndd54BJEQ==";
String exponent = "AQAB";
modulus = modulus.Replace('-', '+').Replace('_', '/'); // Else it gives Base64 error
StringBuilder sb = new StringBuilder();
sb.Append("<RSAKeyValue>");
sb.Append("<Modulus>");
sb.Append(modulus);
sb.Append("</Modulus>");
sb.Append("<Exponent>");
sb.Append(exponent);
sb.Append("</Exponent>");
sb.Append("</RSAKeyValue>");
RSACryptoServiceProvider RSAVerifier = new RSACryptoServiceProvider();
RSAVerifier.FromXmlString(sb.ToString());
// Verify the signature with the hash
return RSAVerifier.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature);
You might want to try as done in the Google+ Token Verification project - this fork includes a few minor updates that are still in review.
An alternative approach is to just verify the tokens using Google's token verification endpoints:
curl https://www.googleapis.com/oauth2/v2/tokeninfo?id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjkyNGE0NjA2NDgxM2I5YTA5ZmFjZGJiNzYwZGI5OTMwMWU0ZjBkZjAifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTEwNTcwOTc3MjI2ODMwNTc3MjMwIiwiYXpwIjoiMzY0MzgxNDQxMzEwLXRuOGw2ZnY2OWdnOGY3a3VjanJhYTFyZWpmaXRxbGpuLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXRfaGFzaCI6IlAzLU1HZTdocWZhUkZ5Si1qcWRidHciLCJhdWQiOiIzNjQzODE0NDEzMTAtdG44bDZmdjY5Z2c4ZjdrdWNqcmFhMXJlamZpdHFsam4uYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJjX2hhc2giOiJjd3hsdXBUSkc4N2FnbU1pb0tSYUV3IiwiaWF0IjoxNDM0NDcyODc2LCJleHAiOjE0MzQ0NzY0NzZ9.Gz_WljZOV9NphDdClakLstutEKk65PNpEof7mxM2j-AOfVwh-SS0L5uxIaknFOk4-nDGmip42vrPYgNvbQWKZY63XuCs94YQgVVmTNCTJnao1IavtrhYvpDqGuGKdEB3Wemg5sS81pEthdvHwyxfwLPYukIhT8-u4ESfbFacsRtR77QRIOk-iLJAVYWTROJ05Gpa-EkTunEBVmZyYetbMfSoYkbwFKxYOlHLY-ENz_XfHTGhYhb-GyGrrw0r4FyHb81IWJ6Jf-7w6y3RiUJik7kYRkvnFouXUFSm8GBwxsioi9AAkavUWUk27s15Kcv-_hkPXzVrW5SvR1zoTI_IMw

JwtHeader.SigningKeyIdentifier creates incorrect X509ThumbprintKeyIdentifierClause

I am trying to validate a JWT token. The code is within an OWIN OAuth handler, however I have taken the various pieces out into a small console application and it would appear to be a problem with how the JwtHeader method SigningKeyIdentifier creates a X509ThumbprintKeyIdentifierClause object.
My JWT has a header value of x5t = [base64urlencodedvalue], and I have confirmed that when this string is decoded it is indeed the thumbprint for my certificate. However, in the SigningKeyIdentifier class the following code seems to create a incorrect clause, e.g. the hash of the clause doesnt match the certificate.
identifier.Add(new X509ThumbprintKeyIdentifierClause(Base64UrlEncoder.DecodeBytes(this.GetStandardClaim("x5t"))));
Below is a snippet of the console app that tries to demostrate the issue:
// http://kjur.github.io/jsjws/tool_b64udec.html
const string X5T = "NmJmOGUxMzZlYjM2ZDRhNTZlYTA1YzdhZTRiOWE0NWI2M2JmOTc1ZA"; // value inside the JWT (x5t)
const string thumbPrint = "6bf8e136eb36d4a56ea05c7ae4b9a45b63bf975d"; // correct thumbprint of certificate
string thumbPrintBase64 = Base64UrlEncoder.Encode(thumbPrint); // <--- value in x5t of JWT
// finds correct certificate
var cert1 = X509CertificateHelper.FindByThumbprint(StoreName.My, StoreLocation.LocalMachine, thumbPrint).First();
var certHash = cert1.GetCertHash();
string hexa = BitConverter.ToString(certHash).Replace("-", string.Empty);
Console.WriteLine(hexa.ToLowerInvariant());
// TokenValidationParameters.IssuerSigningKey
var clause1 = new X509ThumbprintKeyIdentifierClause(cert1);
string hex1 = BitConverter.ToString(clause1.GetX509Thumbprint()).Replace("-", string.Empty);
Console.WriteLine(clause1.ToString());
Console.WriteLine(hex1.ToLowerInvariant());
// this is how JwtHeader.SigningKeyIdentifier method creates SecurityKeyIdentifier
var hash = Base64UrlEncoder.DecodeBytes(thumbPrintBase64);
var clause2 = new X509ThumbprintKeyIdentifierClause(hash); // <----- broken
string hexb = BitConverter.ToString(hash).Replace("-", string.Empty);
Console.WriteLine(hexb.ToLowerInvariant());
Console.WriteLine(clause2.ToString());
string hex2 = BitConverter.ToString(clause2.GetX509Thumbprint()).Replace("-", string.Empty);
Console.WriteLine(hex2.ToLowerInvariant());
// clause1 and clause2 should be the same, but they arent!?
The problem seems to be that the various consructors for X509ThumbprintKeyIdentifierClause end up with different hash values which when compared later dont match.
In my OWIN project one piece creates a X509ThumbprintKeyIdentifierClause from a certificate (TokenValidationParameters.IssuerSigningKey). e.g.
IssuerSigningKey = new X509SecurityKey(X509CertificateHelper.FindByThumbprint(StoreName.My, StoreLocation.LocalMachine, thumbPrint).First()),
and the IssuerSigningKeyResolver method called to match the JWT with the issue certificate using the thumbnail from the x5t field.
identifier.Add(new X509ThumbprintKeyIdentifierClause(Base64UrlEncoder.DecodeBytes(this.GetStandardClaim("x5t"))));
but they dont match.
What am I missing? Something feels wrong with the encoding/decoding of the thumbnail.
We had a great discussion about this in GitHub, should have posted here before.
https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/100
The input that is encoded and creates the x5t is not the 'thumbprint', which are encoded octets. but the octets from the certhash.
The JwtHeader creates the clause as:
ski.Add(new X509ThumbprintKeyIdentifierClause(Base64UrlEncoder.DecodeBytes(GetStandardClaim(JwtHeaderParameterNames.X5t))));
Not:
var hash = Base64UrlEncoder.DecodeBytes(thumbPrintBase64);

Nonce Code or Nonce Timeout

My Client has a Java webservice and I am trying to consumem it using wcf .
It uses a usernametoken with nonce, createddate.. This is the link I am using
http://weblog.west-wind.com/posts/2012/Nov/24/WCF-WSSecurity-and-WSE-Nonce-Authentication,
Following code generates nonce. This simply appends to the string.
string phrase = Guid.NewGuid().ToString();
var nonce = GetSHA1String(phrase);
protected string GetSHA1String(string phrase)
{
SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
return Convert.ToBase64String(hashedDataBytes);
}
Error: The Nonce which is a randomly generated value has expired. Is the code generating a nonce or checksum?
Soap UI does not give me this error. It is successful.This is obvious becuase Interoperability is always an issue
SOAP Error, The nonce, which is a randomly generated value, has expired. ocurred while running action:
Thank you

Categories

Resources