I'm trying to validate a token that was provided by Azure AD inside of an AWS Lambda Function. At the moment I have a MVC Website that you can authenticate to Azure AD with, which returns a JWT Token. This JWT will be passed up to an AWS API Gateway where a Lambda Authorizer will verify it.
At first I thought the correct method was to pass the JWT back to Azure AD to verify the token. However after reading this, it appears I need to decrypt the token, and validate the issuer and audience. This lead me to this, which does successfully validate the token. However, if i change mySecret
to not match the one configured in Azure AD, it still successfully validates?
var authToken = "JWTToken";
string key = "I thought this needed to be the client secret in Azure AD but any string will still pass verification";
string myTenant = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var myAudience = "api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var myIssuer = string.Format(CultureInfo.InvariantCulture, "https://sts.windows.net/{0}/", myTenant);
var mySecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
var stsDiscoveryEndpoint = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", myTenant);
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
var config = await configManager.GetConfigurationAsync();
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidAudience = myAudience,
ValidIssuer = myIssuer,
IssuerSigningKeys = config.SigningKeys,
ValidateLifetime = false,
IssuerSigningKey = mySecurityKey,
ValidateAudience = true,
ValidateIssuer = true,
};
var validatedToken = (SecurityToken)new JwtSecurityToken();
// Throws an Exception as the token is invalid (expired, invalid-formatted, etc.)
tokenHandler.ValidateToken(authToken, validationParameters, out validatedToken);
I have Azure AD configured to this, where the Client is the MVC website and the Service is the Lambda Auhorizer. TLDR: This is basically two client registrations, where the Lambda Authoizer has an exposed API and the MVC website has a client secret.
Have a taken the right approach? If so, how do I fix the issue i am facing?
Any help would be appreciated
CodePudding user response:
I've used something like this:
string authority = "https://login.microsoftonline.com/<your-tenant-id>/";
string clientId = "<your-client-id>";
IConfigurationManager<OpenIdConnectConfiguration> configurationManager =
new ConfigurationManager<OpenIdConnectConfiguration>($"{authority}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
var validationParams = new TokenValidationParameters
{
ValidAudience = clientId,
IssuerSigningKeys = openIdConfig.SigningKeys
};
It uses the authority to download the valid issuer, signing keys etc.