Blazor Server Side Authorization - c#

I have been trying to Implement Authorization in my Server Side Blazor application, currently it seems to be working but the Authorization is limited to the .razor pages and components. Try as I might I cant seem to get the [Authorize] Microsoft.AspNetCore.Authorization attributes to work in my underlying services.
Currently the only means of enforcing this is to read the claims directly from the HttpContextAccessor.HttpContext.User witch can be injected into the underlying services. I can also call the RevalidatingIdentityAuthenticationStateProvider.
I have the following setup correctly Registered in my Startup.cs`
RevalidatingIdentityAuthenticationStateProvider<TUser>
app.UseAuthentication();
app.UseAuthorization();
along with a CascadingAuthenticationState and AuthorizeRouteView in the App.razor
These are functioning and do indeed authorize and restricts access were needed. My biggest issue is that I originally planned on driving the Navigation with the "Front End" Authorization but restrict actions in the services themselves.
As a quick side note, I spun up a new Template with Individual User Account Authentication, it also seems to ignore any [Authorize] tags placed in the WeatherForecastService.cs
[Authorize]
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
** Boiler Plate Code **
}
Any suggestions in overcoming this issue, I also suspect I may be barking up the wrong tree as this is all server side and thus there is no real need to Authorize the underlying services.

Related

Aspnetcore API route Template based on Host

I have a set of APIs in an ASP.NET Core (.NET6) project that are exposed both internally (private) and through an API gateway. When served privately, API urls are of the form service.internal/api/v1/resource which is achieved with a RouteAttribute on the ApiController:
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class ResourceController : ControllerBase
{
// actions
}
When accessed via our api gateway, however, the /api/ component of the url is absent, ie. gateway.com/v1/resource. The gateway performs a transformation on the Url which adds in the extra path segment for the internal/proxied request.
This all works "fine" except in a few circumstances. The primary issue I'm having is with link/url generation for requests coming through the gateway. Location headers added by CreatedAt and link headers generated with IUrlHelper include the /api/ segment of the route with the gateways hostname rendering them invalid. I also have some issues with swagger but I believe they should resolve themselves if I can solve this.
Question: Is there a way to make the route template dynamic based on the host name (which would not be a compile time constant, ie. from config)? For example for requests coming from gateway.com, the route template would be v{version:apiVersion}/[controller] and otherwise would be api/v{version:apiVersion}/[controller]?
It doesn't need to be attribute driven if there's a different way. But my understanding is that the ApiControllerAttribute makes attribute routing required and I wouldn't want to lose the other benefits of that.
If I can get this to work, I'd be able to update the gateway and not have it add the /api/ segment to the proxied urls and it should remove any issues with swagger since the proper paths would be detected by the api explorer.
Unfortunately I have no idea where to start looking. I reviewed some of the routing docs but I didn't see anything that would do the job. I admit I'm out of my league here with minimal aspnetcore experience.
If it matters we are using endpoint routing:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

ASP.NET Core 2 CORS not enabled

I'm developing a web application based on an Angular 6 client and ASP.NET Core WebAPI for web services.
At the moment (initial development phase) i have a simple architecture that consists of two web services, one that manages authentication and identities, the other one that holds the applicative logic (business logic, updating db, ecc.).
I'm using JWT Bearer token for client authentication.
Everything works fine with my authentication service, but when I try to call the application service I obtain this error in the Chrome browser console:
Failed to load http://localhost:59207/api/Files/Upload: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 500.
This error is preceded by another one:
POST http://localhost:59207/api/Files/Upload 500 (Internal Server Error)
Is, in some way, the second error I get related to the Internal Server Error it is preceded by?
I test my POST call from Postman and everything works fine, no server-side errors and the data i want back from my service is returned.
I already put in place everything I know about CORS in ASP.NET Core.
Startup class method named "ConfigureServices" contains, as first row:
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
Then this is called in the "Configure" method:
app.UseCors("AllowAll");
Also I put the EnableCors Attribute on every controller class like this:
[EnableCors("AllowAll")]
Anyone has an idea of how I can get out of this mess?
From what I get, this is how CORS is intended to be used and I already got it running this way on other projects (but never with ASP.NET Core 2).
Thank you in advance
This may not be an answer to your situation, but I've run into this issue quite often in the past. It's a Chrome issue when talking between two localhosts upon POST requests.
Try using another browser and see if it works; if so, you can continue using Chrome by disabling Security
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
hope this helps.

How to customize swagger requests in ASP.NET Core?

I have Swagger setup for an ASP.NET Core 2 MVC API application. I'm using OpenIddict for OAuth but want to customize how the request and responses appear on the documentation.
Since the method in the controller takes an OpenIdConnectRequest, the generated default output looks like so:
... and it just goes on and on.
This is a far cry from the neat JSON required for a client to consume since the middleware does a bunch of work inbetween the client and the controller method.
How do I change how Swagger represents these? I am already using a hack to massage the responses via a custom, private type for token responses, so any help on how to use that would also be appreciated. I have tried to use the SwaggerGenOptions.MapType<> function as the documentation claims that tells Swagger how to map a type to a custom output. Unfortunately, I've not gotten the Swagger output to reflect anything I've done with .MapType<>.
To be clear, these aren't models I control so I can't decorate the members myself.
Note that this is different from How to show WebApi OAuth token endpoint in Swagger. My controller action is discovered fine. Unfortunately, I'm thinking it may be easier to filter it out and use that as another work around to define it manually but I'd rather not if possible.

Unable to access MVC 6 API

I'm currently creating an MVC 6 project (beta 8) which includes some APIs. Along with this is an accompanying Word App which talks to these APIs (just GET methods at present), however all my ajax get JSON requests from the Word app result in an 'Error: Access is denied.' message.
After much searching I believe this may be a CORS issue, so I have enabled this in my startup.cs by adding the following into ConfigureServices:
services.AddCors(options =>
{
options.AddPolicy("AllowAllOrigins", builder => builder.AllowAnyOrigin());
});
and then
app.UseCors("AllowAllOrigins");
into Configure, but this makes no difference, I still just receive the access denied message. I've attempted adjusting my CORS options to allow all methods and tried various other options, including adding
[EnableCors("AllowAllOrigins")]
on the actions, but again it makes no difference.
I am running both projects locally and manually navigating to the api via a browser returns the results without a problem, as does my swashbuckler setup.
Am I missing something obvious here?
In my experience, some browsers don't allow the wildcard response for allow origin when over an SSL connection (which is what you get when you use AllowAllOrigins). If you need your traffic to go over SSL, you need to respond with a list of allowed origins instead of the wildcard.
This answer has a good approach.

C# Web API - Security for some of the GET requests

On an existing host I've added Web API Models & Controllers. I've added the following four:
Products
Orders
Categories
Users
When someone accesses the localhost:port\api\products, it returns all the products in JSON format.
The Create, Update and Delete statements are completely disabled, so we are only able to use GET-requests on the API (so either \api\products for a list of all products or api\products\# for a single products with id #).
Because the other CRUD's aren't used, there isn't a lot of security that should be added to the Web API, except for one thing: The Users
These will also return emails and such, which would be better to keep private and unreadable without the proper authorization (without entire log-in pages, but a way to authenticate yourself when accessing the Web API in for example Android HttpGetRequests).
So, the question: How should I add authorization for only the UsersController accessed by the Web API.
And, how can I encrypt the JSON in C# and decrypt it in Android again. If this second part is too big to answer I'll make a new question later on, my main focus is the low-end [<- without log-in pages, so built in into the GET-request] authorization of the Web API's GET-request for Users.
Edit 1: I did found this link where a new project is made with Authorization Changed to Individual Users. I also see that the user is registered and then logged in with POST and GET requests.
The following questions came into mind when reading through this link:
How to change the Web API's Authorization to Individual Users on an existing project?
Our authorization is done through OAuth (mainly Google-account) with our work e-mail address. I guess it's not possible / easy to authorize in the same way as in the link with a Google-account on Web API GET-requests.
Edit 2: After using the first link provided by Vladimir Gondarev I've added the [Authorize] to both the Get methods in the UsersController. In my project everything else was already used before, like a class that uses the AuthorizeAttribute, so just adding the [Authorize] was already enough for the first step. Now in the browser I get an unauthorized (JSON) back when I'm not logged in, which is good.
The next step would be to add the OAuth-authorization to the Android app, but that is an entire new problem / question that I will look into first before asking a new stackoverflow-question.
The simplest solution would be "Basic Authentification". In order to to implement it you have to derive from AuthorizeAttribute and then apply it to a method or a controller.
Here you find further info:
What is basic Authentification:
http://www.asp.net/web-api/overview/security/basic-authentication
Implementation:
ASP.net Web API RESTful web service + Basic authentication
You don't have to encrypt anything as long as you use HTTPS transport.

Categories

Resources