Best approaches for to create a JWT server Dotnet 6 - .net-core

I am making an authentication server which will provide JWT tokens to the client for the client to communicate with another server.
Server one (Authentication - responsible for delivering JWT)
Server two (Main API)
Client
What is the best and safest approach for server two to validate the JWT token provided by server one.
Should server one have some middleware to send an api request to server two? in Which server two has the functions to verify the token? Or shall Server two have the same secret key as server one to verify the token itself?.

There is a package Microsoft.AspNetCore.Authentication.JwtBearer that allows you to sign JWT tokens.
You create a login end point that does the credentials validation and returns the token with the users roles.
On the client you store that token in a cookie or local storage and send it back to each api request either as a cookie or in the header.
The middleware you create is where you turn the token into a user then you can use validation attributes on you api controllers and actions.
Use the app UseJwtBearerAuthentication helper method
.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["AppSettings:AuthConfig:SecretKey"])),
ValidateIssuer = true,
ValidIssuer = Configuration["AppSettings:AuthConfig:Issuer"],
ValidateAudience = true,
ValidAudience = Configuration["AppSettings:AuthConfig:Audience"],
ValidateLifetime = true,
}
})
As long as both server have the same AuthConfig:SecretKey in app settings it will work between servers.

Related

IdentityModel.AspNetCore problem with proxy credentials for backchannel HttpClient

I'm using IdentityModel.AspNetCore to manage client access tokens in a background service. Access to the internet is only possible through a corporate proxy server which uses windows authentication.
The proxy server is configured in Windows options and the background service detects the settings, however authentication doesn't work and I'm constantly getting The proxy tunnel request to proxy 'http://proxy:8080/' failed with status code '407'. How can I configure the HttpClient to use the windows credentials for authentication against the proxy server?
I've already tried the following, but this doesn't work:
services.AddAccessTokenManagement(options =>
{
options.Client.Clients.Add("sapci", new ClientCredentialsTokenRequest
{
Address = hostContext.Configuration["HttpProxy:TokenEndpoint"],
ClientId = hostContext.Configuration["HttpProxy:ClientId"],
ClientSecret = hostContext.Configuration["HttpProxy:ClientSecret"],
GrantType = OidcConstants.GrantTypes.ClientCredentials,
AuthorizationHeaderStyle = BasicAuthenticationHeaderStyle.Rfc2617,
ClientCredentialStyle = ClientCredentialStyle.AuthorizationHeader
});
})
.ConfigureBackchannelHttpClient(client => new HttpClient(new HttpClientHandler()
{
DefaultProxyCredentials = CredentialCache.DefaultCredentials,
}));
I believe you can do this at app startup, to ensure you capture all client usages:
HttpClient.DefaultProxy = new WebProxy()
{
Credentials = CredentialCache.DefaultCredentials
}:
I would reduce your problem to deploying a minimal console app and running it with the same user account etc as your service. Once that works your main app will also.
Sometimes these things are infrastructure related also: eg in the past, with IIS clustered environments, I've had to use a service account and register a service principal name, eg to prevent use of computer accounts. I doubt that is relevant to .Net Core / Kestrel though, which I assume you are using.

Restricting AddJwtBearer from validating ID Tokens in .net core 3.1

I implemented Token validation in .net core 3.1 application as below :
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.Authority = Configuration["AuthorityUrl"];
options.Audience = Configuration["Audience"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "preferred_username"
};
});
My main issue now which is security threat I believe that if the user passes ID token the authentication passes successfully which is wrong as Resource servers should accept only Access token. Is this behavior is right ? if yes how can limit the validation to Access tokens only.
Your API's job is to verify the attributes of the token - and APIs are typically configured with fixed values for items 2 and 3 below:
Signature
Issuer
Audience
Expiry
Scope
Use of id tokens should naturally fail if you check the audience (and you should) - where typical values are shown below:
Audience of access token = api.mycompany.com
Audience of id token = mywebclientid
APIs should also check for a required scope - and Authorization Servers do not include scopes in id tokens - since scopes are only used by APIs to protect areas of data.
In addition, some providers will provide a claim within the token to tell you its type, though this is vendor specific. As an example, Curity provide a 'purpose' claim - see the example at the end f this document.

Azure mobile app custom authentication and MobileServiceClient

I was following custom authentication for my azure mobile app (https://www.newventuresoftware.com/blog/custom-authentication-with-azure-mobile-apps)
I created AuthControll which accepts username and password and creates token. When i call MobileServiceClient.InvokeApiAsync("Auth", loginInfoDictionary), I receive the user name and token succesfully. I created new MobileServiceUser(username) with received token an set it to MobileSeviceClient.CurrentUser. But When i call MobileServiceClient.InvokeApi over method which requiere authorization, it tells me i am unauthorized.
What i am supposed to do with received token then ? Can i use MobileServiceClient.InvokeApiAsync and MobileServiceClient.GetTable methods with this type of authorization ? If yes what i am missing ?
I found a problem in my solution on server side. I forgot to specify my url site when creating a token. Like this
var signingKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY");
var audience = "https://TheSiteIForgotToSpecify.azurewebsites.net/"; // audience must match the url of the site
var issuer = "https://TheSiteIForgotToSpecify.azurewebsites.net/"; // audience must match the url of the site
JwtSecurityToken token = AppServiceLoginHandler.CreateToken(
claims, signingKey, audience, issuer, TimeSpan.FromHours(24));

Azure AD OAuth 2 validate token .NET Core

I am developing now a Microservices .NET Core project. We have an Azure AD and we want to validate the requests that come to all web Apis microservice.
There are many apps who will call our Web API projects. Each one of these app has his own application (ClientId and client secret). They generate the token using their data and then send it in the header with every request. (No problem till now)
On my side, I have to validate the token with every request, but the validation should work for all the tokes that come from different applications.
So, I am trying to set the JWTBarear to accept any token, but I am a bit lost with the configuration:
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwt =>
{
jwt.Authority = "https://login.microsoftonline.com/[myTenant]";
});
services.AddAuthorization(auth =>
{
auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build());
});
and in the Configure:
app.UseAuthentication();
app.UseMvc();
But, I am getting always and 401. I generated the token using postman and it is valid.
I am not very good with the configurations. Am I missing something?
All the examples that I saw on the internet are using ClientId which I have many, not just one.
P.S. I don't have to sign in or something, I have to only validate the token.
Thanks!
Ooh, I found the answer. I was missing the Audience, which was different in .NET Core:
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Audience = "https://management.core.windows.net";
jwtOptions.Authority = "https://login.microsoftonline.com/[myTenant]";
});

Handling authentification to Firebase Database with Fetch in a Service Worker

I'm trying to query a Firebase database from a Service Worker using the Fetch API. However it doesn't work as expected as I can't get authenticated correctly.
Basically what I'm trying to do is from origin https://myproject.firebaseapp.com inside a Service Worker I do a call like this :
var fetchOptions = {};
fetchOptions.credentials = 'include';
var url = options.messageUrl;
var request = new Request('https://myproject.firebaseio.com/user/foobar.json', fetchOptions);
messagePromise = fetch(request).then(function(response) {
return response.json();
});
I'm getting this error :
Fetch API cannot load https://myproject.firebaseio.com/user/foobar.json. Response to preflight request doesn't pass access control check: Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'https://myproject.firebaseapp.com' is therefore not allowed access.
Any idea of a way to fix it? How one should do to query/update the Firebase database from a SW?
I've read https://jakearchibald.com/2014/using-serviceworker-today/ and one of the gotcha was exactly that problem, the fact that Fetch request do not send authentification.
Ideally it would be great to be able to use the Firebase JS API inside a SW but this doesn't seem to work as well.
Firebase doesn't store authentication info as a cookie or in anything that would be sent along in the credentials, so there's no need to send them in your fetch request. Instead, you'll need to pull the token from Firebase Auth:
firebase.auth().currentUser.getToken(true).then(function(token) {
// token is the value you'll need to remember for later
});
Once you've got the token, you should be able to add it as a query parameter to the REST request e.g. ?auth={THE_TOKEN}. This will allow you to make your authenticated request in the Service Worker.

Resources