I'm trying to get dual authentication schemes working with Azure Ad and regular jwt tokens, the issue i'm having is, I can access both controller functions with just the JWT token, regardless of scheme. I tried setting up my configuration from this post but it didn't work (neither does my current configuration obviously):
Authenticating tokens from multiple sources (e.g Cognito and Azure)
[HttpGet]
[Authorize(AuthenticationSchemes = "TestBearer")]
[Route("Test1")]
public async Task Test()
{
}
[HttpGet]
[Authorize(AuthenticationSchemes = "AzureAd")]
[Route("Test2")]
public async Task Test2()
{
}
Startup config
services.AddAuthentication(options =>
{
options.DefaultScheme = "AzureAd";
})
.AddJwtBearer("TestBearer", x =>
{
x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Guid.Parse(jwtConfig.SecretKey).ToByteArray())
};
})
.AddMicrosoftIdentityWebApi(x =>
{
x.Audience = config.Audience;
x.Authority = config.Authority;
x.RequireHttpsMetadata = false;
},
x =>
{
x.Instance = config.Instance;
x.ClientId = config.ClientId;
x.TenantId = config.TenantId;
x.Authority = config.Authority;
x.RequireHttpsMetadata = false;
}, "AzureAd");
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
"TestBearer", "AzureAd");
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
var scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(config.ClientId)
.WithTenantId(config.TenantId)
.WithClientSecret(config.ClientSecret)
.Build();
//Build the Microsoft Graph client.As the authentication provider, set an async lambda
// which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
// and inserts this access token in the Authorization header of each API request.
var authenticationProvider = (new DelegateAuthenticationProvider(async (requestMessage) =>
{
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await confidentialClientApplication
.AcquireTokenForClient(scopes)
.ExecuteAsync();
//// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
}));
services.AddScoped(_ => new GraphServiceClient(authenticationProvider));
my jwt token generation
private string GenerateToken(TestEntity entity)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Guid.Parse(_jwtSettings.SecretKey).ToByteArray();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]{
new Claim(ClaimTypes.NameIdentifier, entity.Id.ToString()),
new Claim(ClaimTypes.MobilePhone, entity.Phone.ToString()),
new Claim(ClaimTypes.Email, entity.Email)
}),
Expires = DateTime.UtcNow.AddHours(_jwtSettings.ExpiryTimeInHours),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Audience = "https://localhost:5001",
Issuer = _jwtSettings.Issuer,
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}