I have a standalone blazor WASM app that needs to send requests to an external app. I need to validate the authentication that I receive from the WASM app in the API.
I can see the Bearer token being sent and I checked it up in jwt.io, the data seems to make sense.
The client configuration looks like so :
"AzureAd": {
"Authority": "https://login.microsoftonline.com/common",
"ClientId": "****",
"ValidateAuthority": true
}
I've tried the following TokenValidationParameters without success:
var stsDiscoveryEndpoint = String.Format(CultureInfo.InvariantCulture, $"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration");
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
var config = await configManager.GetConfigurationAsync();
var validationParameters = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = true,
IssuerSigningKeys = config.SigningKeys,
ValidIssuer = config.Issuer,
ValidateLifetime = false
};
I've loosened up the "Validate", hoping to find what's wrong, but I keep getting "Signature validation failed"
Any idea how I can validate the token?
There're 2 methods to validate the token. The first is writing a custom filter to intercept all the incoming requests and as you know there's a bearer token in the request header, then you can use jwt decode library to decode the token and validate the claims.
But I still recommend following official sample to protect your api via Azure AD directly. And here's a tutorial. You need to expose an API in Azure AD, then configure your app.
By the way, you've had the access token, I think you should have had your exposed api in AAD, so it mostly like that you only need to add authentication in your api project. Then In asp.net core web API project, you need to modify Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
And appsetting.json
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "37xxxxxxxb2d7",
"TenantId": "21xxxxxxd93",
"Audience": "api://37xxxxxb2d7"
},
Then in the controller, add [Authorize] attribute.
Related
i try to do an angular application with MSAL-angular and Azure B2C for authentication.
I am able to authenticate the angular app with Azure B2C (i have create a susi flow) and obtain the token as show in image below
so i have create a .net core web api project and modify the appsetting configuration and the start up with this code :
appsetting.json :
"AzureAdB2C": {
"Instance": "https://{mytenat}.b2clogin.com/tfp",
"ClientId": "8xxxx-xxxx-xxxx-xxxx-xxxxxxxxc",
"Domain": "{mytenat}.onmicrosoft.com",
"SignUpSignInPolicyId": "B2C_1_susi"
}
startup.cs
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.RoleClaimType = "roles";
options.TokenValidationParameters.NameClaimType = "name";
},
options => { Configuration.Bind("AzureAdB2C", options); });
// By default, the claims mapping will map claim names in the old format to accommodate older SAML applications.
//'http://schemas.microsodt.com/ws/2008/06/identity/clains/role' instead of 'roles'
// This flag ensures that the ClaimsIdentity claims collection will be build from the claims in the token
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
//services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
//{
// // The claim in the Jwt token where App roles are available.
// options.TokenValidationParameters.RoleClaimType = "roles";
//});
but if i try to run localy the project and call it with postman i have this error :
**System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token. **
i don't understand where is the error.
can you help me?
thanks
In your question, you have created a web api application and angular app in Azure AD B2C. Next, you need to expose the api of the web api application, and then add permissions to the angular app.
First go to web api.
Then go to angular app>API permissions> add a permission>My APIs>your web api app.
Finally, when you parse the token, you will see the scp:access claim.
Before I explain my problem I want to share some insights about what I am trying to do. I am developing a serverless application in Azure. My azure app service plan contains multiple azure function application and each function app contains multiple azure functions(HTTP triggers/API) in it. Now I want to authenticate all the serverless API. I am using firebase to authenticate my users. How I can achieve it in a minimal and reusable manner.
I already use firebase in asp.net core for authentication in a monolithic manner but for a situation like this, I am not sure How to do.
In a Monolithic manner. In our ConfigureServices method, we need to register the services necessary to handle authentication and to specify the parameters of our Firebase project.
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://securetoken.google.com/my-firebase-project";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://securetoken.google.com/my-firebase-project",
ValidateAudience = true,
ValidAudience = "my-firebase-project",
ValidateLifetime = true
};
});
Then in our Configure method, we have to do one simple call to register the actual middleware that will handle the authentication.
app.UseAuthentication();
I've been looking for an example or tutorial for a few hours and thought I should post something at this point.
I'm trying to validate a bearer token from a custom Auth provider inside my .Net 4.7.2 Web Api 2 project. I have a SPA app that gets a bearer token from this auth provider, and sends the bearer token to my WebApi endpoints. I need to turn around and validate the token in each request. I thought there would be a way to point the classes in the Microsoft.Owin.Security.Jwt namespace to validate the token based on the auth providers well known discovery information url.
Has anyone done this before or point me towards a good library/documentation/tutorial?
I know I can write my own auth request filter and go out and pull down the public certificate from the auth server and parse the token and validate the signature, but it seems like a horrible idea for me to write that myself vs using the appropriate libraries.
Ok turns out I found a good example here
The following code sets up our webapi to validate tokens with our custom auth provider while discovering the public key through the OIDC discovery url.
var issuer = "https://my-auth-provider-here/";
IConfigurationManager<OpenIdConnectConfiguration> configurationManager =
new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result;
appBuilder.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions()
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
AuthenticationType = "Bearer",
ValidIssuer = issuer,
ValidateAudience = false,
IssuerSigningKeys = openIdConfig.SigningKeys
}
});
I downloaded the sample IdentityServer and MVC client project from Github.
My goal is to create a portal environment, in which a user can authenticate and than proceed to request protected resources.
So what I did is move the Views from the MVC client to the IdentityServer project, changed the Client.cs to support a client on the same port and added the following in the startup from the IdentityServer:
var oidcOptions = new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
PostLogoutRedirectUri = "http://localhost:5000/",
ClientId = "mvc",
ClientSecret = "secret",
ResponseType = "code id_token",
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
};
My question is are there any reasons, concerning security, I should not implement this and keep it seperated?
There is nothing wrong with this at all from a security perspective.
However I must warn you that you may run into a problem when dealing with cookies and tokens. Running them in separate projects implicitly separates the concerns of the MVC and IDS projects.
something that you might want to do is to fork your request pipeline by using app.Map(). (eg map IDS to "/identity" and the MVC project to "/ui")
I have a separate angular client that I want to authenticate to using Azure AD. I am using ADAL JS and all of that seems to be working fine. I get redirected to the AD login page, and then sent back to my application. I can see the token getting passed with each subsequent http request.
However, when I try to make a secured request to my Web API I receive a 401 Unauthorized error. I am loosely following the guide here for setup. I say loosely because I'm not using MVC, my client is in a separate codebase entirely.
I am positive that my user has access to this application.
My Auth Configuration stuff looks like:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(new WindowsAzureActiveDirectoryBearerAuthenticationOptions()
{
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["AzureADAudience"],
},
Tenant = ConfigurationManager.AppSettings["AzureADTenant"],
AuthenticationType = "OAuth2Bearer"
});
Audience: https://login.windows.net/xyz.onmicrosoft.com/myappname
Tenant: xyz.onmicrosoft.com
The controller I'm locking down is decorated like this:
[HostAuthentication("OAuth2Bearer")]
[Authorize]
[RoutePrefix("Auth")]
Is your SPA hosted with your backend? If so, then you need to change your audience to the Client ID.
ValidAudience = ConfigurationManager.AppSettings["ida:ClientID"]