I'm implementing an asp .net core web API for my company. The authentication should be processed via the built-in jwt bearer authentication.
The problem I'm struggling with is, that I'm working behind a proxy. So for the token validation, I'm facing 407 proxy authentication failed responses.
As far as I know, in .net framework, there was the possibility to define a default proxy in the web.config but for .net core, I couldn't find any similar functionality.
Is it possible to "inject" proxy settings for the jwt authentication or if not, is there any other way to work with this authentication behind a proxy?
The option to define a global proxy in the Web.config is gone for ASP.NET Core.
Most APIs that do anything over HTTP allow you to set a HttpMessageHandler, though. You can set the proxy for that MessageHandler.
For instance, assuming you're using default JwtBearer Authentication you could try this approach:
appsettings.json:
"Proxy": {
"ProxyAddress": "http://MyProxy:8080"
},
In your ConfigureServices method you can then:
services.AddAuthentication()
.AddJwtBearer("Bearer", o =>
{
o.BackchannelHttpHandler = new HttpClientHandler
{
Proxy = new WebProxy(Configuration["Proxy:ProxyAddress"])
};
});
Depending on what flow you use you may need to set the Proxy on other/additional handlers as well.
Additionally, if you require finer grained control over the Proxy, you can always write a class implementing IWebProxy and use that instead of newing a WebProxy with a proxy address.
Related
Normally when we use IdentityServer4 we would use this setup:
Where we would have an
Authorization Server (Identity Server)
A Client (which will request a token)
A Web Api (Protected with authorize)
Say we have this setup, but I need to add Protected Api's on the Authorization Server (identity server), by protected I mean with the authorize attribute. Is this possible? cause I haven't found any samples online, and I have been trying to implement it by adding the JwtBearer code on the IdentityServer (JwtBearer is normally added on the WebApi project that you want protected, with Authority set as your IdentityServer domain).
In short what i'm trying to achieve is have the Protected Resource on the same Authorization Server. Is this possible?
Thanks in advance
It is possible with some additional configuration. There is an argument against doing this, but I've had use cases where it was necessary.
For local API authentication you need the following additional configuration in Startup:
public void ConfigureServices(IServiceCollection services)
{
....
// After services.AddIdentityServer()
services.AddLocalApiAuthentication();
}
For reference see the docs.
You also need to configure the local resource:
public static IEnumerable<ApiResource> Apis =>
new ApiResource[]
{
// your other resources....
new ApiResource(IdentityServerConstants.LocalApi.ScopeName)
};
For the client you need to add the local API scope:
AllowedScopes =
{
// your other scopes....
IdentityServerConstants.LocalApi.ScopeName
}
And then you need to specify the local API policy as part of the Authorize attribute on your API:
[Authorize(LocalApi.PolicyName)]
See a local API example.
You can put IdentityServer and the protected resource on the same machine, but I would advice against it.
My experience is that it gets really hard to know who is doing what and it will be much hard to fully understand and reason about what is going on. I always recommend putting IdentityServer, the client and the API in independent services. Just to get a clean separation of concerns.
I have ASP.NET 4.5 service with OWIN pipeline that issues OAuth access_token in exchange for username/password. This service is called from ng-app and once it gets a token, stores in the browsers local storage. Then it calls resource api that consumes this token, API is also written in asp.net 4.5 and uses owin. This being OAuth token issued with OWIN it's encrypted/signed to machineKey secrets - so far so good and is happily consumed by the resource API. All this made possible by OAuthAuthorizationServerMiddleware.
Now I need to consume these tokens sent from the same ng-app to asp.net core 2.1 services, nothing fancy, just verify/decode it and get claims inside the token.
This OAuthAuthorizationServerMiddleware was never ported to asp.net core so I am stuck. (OAuth Authorization Service in ASP.NET Core does not help it talks about the full-fledged oidc server I just need to consume them w/o changing the issuing code)
In ConfigureServices() tacked on to service.AddAuthentication():
Tried.AddJwtBearer - but this makes no sense - these are not Jwt tokens really
Tried.AddOAuth but this does not make sense either b/c I am not dealing with full OAuth flow with redirects to obtain a token, I also don't deal with ClientId/ClientSecret/etc, I just receive "Bearer token-here" in the HTTP header from ng app so I need something in the pipeline to decode this and set ClaimsIdentity but this "something in the pipeline" also needs to have access to machinery-like data that is the same as it is in asp.net 4.5 OWIN service
Any ideas?
You could set the OAuthValidation AccessTokenFormat to use a MachineKey DataProtectionProvider and DataProtector which will protect and unprotect your bearer tokens. You will need to implement the MachineKey DataProtector. This guy already did it https://github.com/daixinkai/AspNetCore.Owin/blob/master/src/DataProtection/src/AspNetCore.DataProtection.MachineKey/MachineKeyDataProtectionProvider.cs.
public void ConfigureServices(IServiceCollection services){
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
ConfigureAuth(services);
string machineKey = #"<?xml version=""1.0"" encoding=""utf-8"" ?>
<machineKey decryption=""Auto"" decryptionKey =""DEC_KEY"" validation=""HMACSHA256"" validationKey=""VAL_KEY"" />";
var machineKeyConfig = new XmlMachineKeyConfig(machineKey);
MachineKeyDataProtectionOptions machinekeyOptions = new MachineKeyDataProtectionOptions();
machinekeyOptions.MachineKey = new MachineKey(machineKeyConfig);
MachineKeyDataProtectionProvider machineKeyDataProtectionProvider = new MachineKeyDataProtectionProvider(machinekeyOptions);
MachineKeyDataProtector machineKeyDataProtector = new MachineKeyDataProtector(machinekeyOptions.MachineKey);
//purposes from owin middleware
IDataProtector dataProtector =
machineKeyDataProtector.CreateProtector("Microsoft.Owin.Security.OAuth",
"Access_Token", "v1");
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddOAuthValidation(option=> {
option.AccessTokenFormat = new OwinTicketDataFormat(new OwinTicketSerializer(), dataProtector); })
It's important to keep the same DataProtector "purposes" Owin uses in the OAuthAuthorizationServerMiddleware so the data is encrypted/decrypted correctly. Those are "Microsoft.Owin.Security.OAuth", "Access_Token" and "v1". (see https://stackoverflow.com/a/29454816/2734166).
And finally you will have to migrate the Owin TicketSerializer (and maybe the TicketFormat too) since the one in NetCore is slightly different. You can grab it from here:
https://github.com/aspnet/AspNetKatana/blob/e2b18ec84ceab7ffa29d80d89429c9988ab40144/src/Microsoft.Owin.Security/DataHandler/Serializer/TicketSerializer.cs
I got this working recently. Basically authenticating to a .NET 4.5 Owin API and running a resource API in NET Core using the same token. I'll try to share the code in github as soon as I clean it up.
As far as I know it's not recommended to keep the old machine key data protector, but to migrate to the new ones from NET Core. Sometimes this is not possible. In my case I have too many APIs already in production, so I'm trying some new NET Core APIs to work with the legacy ones.
You should try this Owin.Token.AspNetCore nuget package instead. By following the code example provided in the README file I'm able to decode legacy tokens using the machine keys on .NET Core 3.1. Note: there's also an option to specify encryption method and validation method if the defaults are not working for you.
I have a project that hosts the IdentityServer4 and I am attempting to also host in the same project a Web API, which accepts the access-token.
My question is, is possible that a single project contains the IdentityServer and an Web API that consume the same IdentityServer?
EDIT: The API must be secured with the Authorize attribute
I have an identity server 4 project, in the same project there is an API for CIUD of the clients. (Lets call it developer console api).
I then have a side project with is an asp .net core project that contains the actual razor pages for the Developer console it access the API within the Identity server project.
The reason i did it this way is that only one project should be updateing the database. So to update the database owned by the identity server it was decided the the API for accessing it should also be within the same project.
Yes you can have a web api from within your Identity server 4 project.
Configure service
services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = settingsSetup.Settings.Authority;
// name of the API resource
options.ApiName = "testapi";
options.RequireHttpsMetadata = false;
});
Configure
I think it needs to have both of these.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseAuthentication();
app.UseIdentityServer();
Endpoints
Because the requests are sent using the access token as a bearer token then the authorize for each of the API calls needs to include the authencationScheme. I havent exactly figured out why but without this it doesnt work.
[HttpGet("Client/List")]
[Authorize(AuthenticationSchemes = "Bearer")]
public ActionResult ClientList()
{
}
While #DaImTo's answer is correct and working and it's developed by IdentityServer team, it uses Introspection Endpoint which means for every request AddIdentityServerAuthentication will create a http request and send it to your server, which is the same app.
I developed a library called IdentityServer4.Contrib.LocalAccessTokenValidation which do the exact same thing but without using Introspection Endpoint. It will authenticate the token directly from TokenStore which is configured in Services. You can use it if you are interested.
nuget link : https://www.nuget.org/packages/IdentityServer4.Contrib.LocalAccessTokenValidation
github link : https://github.com/Kahbazi/IdentityServer4.Contrib.LocalAccessTokenValidation
Does anyone know if it's possible to configure an Mvc4/WebApi2 application to validate/decrypt ASP.NET Core generated Anti Forgery Tokens?
We want to be able to, from an ASP.NET Core application, make a validated request to the WebApi2 application using the AntiForgeryToken generated by ASP.NET Core which runs on the same domain (subdomain).
I believe (and could be wrong, so please correct me) that this is possible under normal WebApi --> WebApi or ASP.NET Core --> ASP.NET Core scenarios provided both apps run under the same domain (and thus have access to cookies). I can't seem to find instruction on how to do this ASP.NET Core --> WebApi.
Our ASP.NET Core application has data protection services set up via:
services.AddDataProtection().PersistKeysToFileSystem("SomeDirectory");
The ASP.NET Core side has a working AntiforgeryToken implementation:
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
and
app.Use(next => context =>
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions {HttpOnly = false});
return next(context);
});
On the Mvc4/WebApi2 side we have a DataProtectorShim set up to allow it to be able to encrypt/decrypt OWIN cookies which both sides are able to operate on.
We tried to manually validate the anti forgery token/cookie but, unsurprisingly, it's unable to decrypt either (this was a stab in the dark):
AntiForgery.Validate(HttpContext.Current.Request.Cookies["XSRF-TOKEN"].Value, HttpContext.Current.Request.Headers["X-XSRF-TOKEN"]);
As far as I can tell, it looks like the System.Web Antiforgery class doesn't allow an injection point where we can push in a properly configured data protector/shim and always uses a MachineKey serializer to do this decryption. I'm aware of the Microsoft.AspNetCore.Antiforgery library but am unsure as to if/how this may be able to help.
Our failed attempt at this yields:
The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the <machineKey> configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.
Which makes sense in that we're not using the machine key for encryption on the ASP.NET Core side.
Is anyone aware of a way to set this up? Any guidance is much appreciated.
in WSTrustChannelFactory documentation there is a reference to working with proxy:
One common pattern where the OnBehalfOf feature is used is the proxy
pattern where the client cannot access the STS directly but instead
communicates through a proxy gateway
I can't seem to find an example.
In some of my users' computers a proxy is defined for exteral request.
How can I request the token if the STS is behind proxy.
Currently I am getting it as follows:
var rst = new RequestSecurityToken{...}
IWSTrustChannelContract wsTrustChannelContract = factory.CreateChannel();
var token = wsTrustChannelContract.Issue(rst) as GenericXmlSecurityToken;
How can I change it to using the proxy?
Thanks.
OnBehalfOf is for situations where you build the proxy yourself - like the ADFS proxy.
I haven't seen any sample for that either - but it follows the same pattern as ActAs.
It has nothing to do with "regular" web proxies that might be between you and your STS.
But have a look here:
How can I set an HTTP Proxy (WebProxy) on a WCF client-side Service proxy?