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
}
});
Related
The documentation states: API Gateway validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication.
My question is how?
To authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to the backend API.
So for API Gateway to authenticate the user it needs to know the secret key to calculate signature of a header and payload of JWT to compare it with the signature from JWT.
How does it do that?
My code to verify token is like below and I imagine the API gateway would be using something similar to that - so the _appSettings.Secret is needed:
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
Assuming you're talking about AWS API Gateway; It does require the secret key used for signing the original JWT token but mostly for custom authorization schemes as the documentation states.
A Lambda authorizer is useful if you want to implement a custom authorization scheme that uses a bearer token authentication strategy such as OAuth or SAML, or that uses request parameters to determine the caller's identity.
To achieve this the API Gateway takes a Lambda authorizer to use in the authorization process. You provide the Lambda authorizer with the required details such as the secret key used to sign your JWT token and it can then verify the token based on that. See this AWS example for more details on the implementation.
The API Gateway will then use the provided detail to verify your JWT tokens and authorize a request.
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.
I start building new application with JWT authorization. Our team already have OAuth 2 server written in java, so my target is: check key with public key.
But I don't know how to do it. If I use .net identity I have to use entity framework but I use only Cassandra as a database.
How I can implement it without using EF? Do you know any tutorials?
You don't need any ASP.NET Core stuff. A simple approach would be:
Nu-get the Packages
System.IdentityModel.Tokens.Jwt,
Microsoft.IdentityModel.Tokens
Set up some validation parameters:
var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = true,
ValidateLifetime = true,
IssuerSigningKeys = keys, // Your public keys.
ValidAudience = "my valid audience",
ValidIssuer = "my valid issuer"
}
Call ValidateToken to get a ClaimsPrincipal with claims and stuff.
token is your JWT string, e.g. parsed from Authorization HTTP header.
var handler = new JwtSecurityTokenHandler();
handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
Using JsonWebKeySet from the above IdentityModel.Tokens package, you can automagically obtain keys from an OpenID Connect configuration:
https://github.com/IdentityModel/IdentityModel/blob/master/source/IdentityModel.Shared/Jwt/JsonWebKeySet.cs
There are quite a few Microsoft (and other) documents available (make sure you are looking at documents relevant to the version that you are working with!) - googling will find them pretty easily, but EF is certainly not required as seen below.
No identity or user information is managed by the app directly. Instead, it will get all the user information it needs directly from the JWT token that authenticates a caller.
https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/
Here is a simple example for version 1.1
https://github.com/williamhallatt/aspnet-core-webapi-jwt-auth-example
and the same example for 2.0
https://github.com/williamhallatt/aspnet-core-webapi-jwt-auth-example/tree/dotnecore2.0
My Jwt Token looks like below:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxMzU2OTk5NTI0LCJuYmYiOjEzNTcwMDAwMDAsImV4cCI6MTQwNzAxOTYyOSwianRpIjoiaWQxMjM0NTYiLCJ0eXAiOiJodHRwczpcL1wvZXhhbXBsZS5jb21cL3JlZ2lzdGVyIiwidGVzdC10eXBlIjoiZm9vIn0.UGLFIRACaHpGGIDEEv-4IIdLfCGXT62X1vYx7keNMyc
If I Copy the above JWT token and paste it in https://jwt.io/ then the actual information is showing like this
Image
I want to encrypt the JWT token with no one can access my information in Web Api. So, I want to use any encryption algorithm, If so please provide me proper solution
Here is my Startup.cs file to authorize JWT Token.
// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
}
});
}
Why exactly do you think that it is a problem that someone can see this information? If you are using JWT for authentication, then it's only the user who was just authenticated will get this token and it probably contains the information about this user. So it does not hurt for a user to be able to see information about himself.
Most importantly the token is mac'ed so that no one can forge it and pretend to be another user and that should be sufficient.
And as mentioned in the comments you should be using TLS anyway, so it's encrypted in the transition.
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"]