I have a task to authenticate the APIs using ADFS Token which is from an external application, so I have created two applications one is MVC application lets say A which authenticates using with SSO credentials and another one is WEB API application lets say B, So here FROM A, I am calling B's API using A's ADFS Token but, I am getting error. Does anyone help me how to resolve this?
Below is code in WEB API in application B
ConfigurationManager<OpenIdConnectConfiguration> configManager =
new ConfigurationManager<OpenIdConnectConfiguration>(openIdConfig, new
OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration config =
configManager.GetConfigurationAsync().GetAwaiter().GetResult();
result.EmailId = Claims.FirstOrDefault(claim => claim.Type == "upn").Value;
result.WindowsNTId = Claims.FirstOrDefault(claim => claim.Type == "unique_name").Value;
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
result.TokenCreatedOn = utc0.AddSeconds(Convert.ToInt64((Claims.FirstOrDefault(claim =>
claim.Type == "iat").Value)));
result.TokenExpiresOn = utc0.AddSeconds(Convert.ToInt64((Claims.FirstOrDefault(claim =>
claim.Type == "exp").Value)));
// Use System.IdentityModel.Tokens.Jwt library to validate the token
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = config.Issuer,
IssuerSigningKeys = config.SigningKeys,
ValidateAudience = true,
ValidAudience = expectedAudience
};
SecurityToken validatedToken;
try
{
var claimsPrincipal = tokenHandler.ValidateToken(RawData, tokenValidationParameters,
out validatedToken);
}
catch (Exception ex)
{
}
Below is the Exception Message.
IDX10501: Signature validation failed. Unable to match key:
kid: 'System.String'.
Exceptions caught:System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
It happens when the decoded key (kid) is not a valid one (perhaps it is an old one, as the certificate keys usually change).
From https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs
if (kidExists)
{
if (kidMatched)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10511, keysAttempted, jwtToken.Kid, exceptionStrings, jwtToken)));
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10501, jwtToken.Kid, exceptionStrings, jwtToken)));
}
In my case, the cause of the issue was the null first byte present in the key modulus. The solution was to remove the first null byte.
https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1122
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(configFileUrl, new OpenIdConnectConfigurationRetriever());
var openIdConfig = configManager.GetConfigurationAsync().Result; #region workaround for "Error validating identity token : IDX10511"
//The issue you are facing is caused by the null first byte.
//This is contrary to the JWA (https://tools.ietf.org/html/rfc7518#section-6.3.1.1).
//.NET Core will account for the null byte and .NET framework, apparently, won't.
List<SecurityKey> keys = new List<SecurityKey>();
foreach (var key in openIdConfig.SigningKeys)
{
if (key.CryptoProviderFactory.IsSupportedAlgorithm("SHA256"))
{
var modulus = ((RsaSecurityKey)key).Parameters.Modulus;
var exponent = ((RsaSecurityKey)key).Parameters.Exponent;
if (modulus.Length == 257 && modulus[0] == 0)
{
var newModulus = new byte[256];
Array.Copy(modulus, 1, newModulus, 0, 256);
modulus = newModulus;
}
RSAParameters rsaParams = new RSAParameters();
rsaParams.Modulus = modulus;
rsaParams.Exponent = exponent;
keys.Add(new RsaSecurityKey(rsaParams));
}
else
{
keys.Add(key);
}
}
#endregion
TokenValidationParameters validationParameters =
new TokenValidationParameters
{
// Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = issuer,
//// Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = audience,
ValidateIssuerSigningKey = true,
IssuerSigningKeys = keys,
RequireExpirationTime = true,
ValidateLifetime = true,
RequireSignedTokens = true,
};
// Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method
SecurityToken validatedToken;
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
var claimsPrincipal = handler.ValidateToken(idToken, validationParameters, out validatedToken);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With