Combining two services - Design Pattern MVC - oop

I have a service that locks the user from doing actions on an Id, called "LockingService",
I also have 2 different things that need to be locked:
(MembershipService) Login - if a user tried to login with a membership number more than 3 times - the membership number is locked.
(OtherService) If a user tried to put invalid credentials - their session is locked.
The service doesn't distinguish the two.
Described is one of the flows (for the login) that currently exists on the controller:
if(LockingService.IsLocked(membershipNumber))
return View(dto);
if(MembershipService.login(membershipNumber)) {
... some actions that always
return dto;
}
else {
LockingService.AddToFailedAttempts(membershipNumber);
return dto; // with errors
}
I believe this flow an logic should not reside in the controller.
Suggestions of general comments would be much appreciated.
Thanks.

You are correct - this does not belongs to controller, it belongs to service.
You should have i.e. UserService that has method login with business logic inside.
The service can use other services, just require them and use them. The controller should just handle input/output and call the proper service method.

Related

How to create and persist a custom user object before endpoint execution in webflux?

I am currently developing an OAuth 2.0 resource server (REST API) with Spring Webflux.
I have Spring Security set up and I can successfully authenticate users with Spring's built-in principal class.
The problem:
The application needs to store additional information about the user as per requirement.
Users that access the API for the first time are not stored in the REST API's internal user database. Right now I have to check if the provided principal name (I have access to the respective OAuth UUID - the one stored in the authorization server) already exists in the application database.
I would like to avoid code duplication, where I would have to call a method that does exactly that on every endpoint
Here is what already works:
#GetMapping("/secure")
fun secureEndpoint(principal: Principal): ResponseEntity<Void> {
println(principal.name)
// here I would have to check if the user has already been
// created in the database
return ResponseEntity.ok().build()
}
As I said, the principals correct UUID is already being displayed.
What I am looking for is some kind of webfilter, that runs before every (authenticated) endpoint, and automatically creates the user, so I do not have to do it in the controller layer.
This is my Security configuration:
#Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val cookieServerCsrfTokenRepository = CookieServerCsrfTokenRepository()
cookieServerCsrfTokenRepository.setCookieHttpOnly(false)
http.authorizeExchange()
.pathMatchers("/**").permitAll()
.pathMatchers("/secure/**").authenticated()
.and()
.oauth2ResourceServer()
.jwt()
http.csrf()
.csrfTokenRepository(cookieServerCsrfTokenRepository)
return http.build()
}
I would greatly appreciate any help!

ASP.NET Core Custom Authorization

I need to implement role based authorization on a .NET 5 API but the thing is that we don't want to decorate all the controllers with attributes and a list of roles, because all that configuration will come from either a config file (JSON) or an external service (TBD), in a way that roles will be mapped to controllers and actions and we would want to have something that centralizes all this logic, in a similar way we did before with Authentication Filters and Attributes.
I've been reading that now the idea from MS is that everything is handled with policies and requirements, but I don't know how to fit all that into our desired schema. Most of all because I don't see (or can't see) how can I access the Controller and Action's descriptors to know where I'm standing when I perform the authorization process.
Is there any way to achieve this on this new model?
EDIT: I found a way to get controller and action descriptors in order to do part of what I intended. Based on some other questions and articles I read and some tinkering on my own, I got the following:
public class AuthorizationFilter : IAsyncAuthorizationFilter
{
public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var descriptor = (ControllerActionDescriptor)context.ActionDescriptor; //<<-- this is the key casting :)
var ctrlName = descriptor.ControllerName;
var actionName = descriptor.ActionName;
var userPrincipal = context.HttpContext.User;
//DO STUFF AND DECIDE RESULT TYPE BASED ON USER CLAIMS AND CURRENT CONTROLLER AND ACTION
context.Result = new ForbidResult();
context.Result = new UnauthorizedResult();
return Task.CompletedTask;
}
}
Then I could add this filter the following way:
services.AddControllers(x => x.Filters.Add<AuthorizationFilter>());
This way I could achieve something similar as before with ASP.NET MVC 4/5, but from what I can read, the .NET Core team tried to go away from this path by implementing the IAuthorizationRequirement and AuthorizationHandler<T> mechanism to replace all that, so my doubt remains: is this the correct way to do it in the new .NET Core 3.x / .NET 5 architecture? Or is there some other way I'm overlooking on how to get and process the controller/action being executed and pass it along to an AuthorizationHandler?
What you are looking for is called externalized authorization also referred to as attribute-based access control. In this model:
authorization logic is decoupled from the application
authorization logic is expressed as policies that build on top of attributes
attributes are key-value pairs that describe the subject, the action, the resource, and the context of what's going on (A user wants to execute an action on an object at a given time and place)
authorization is decided based on those policies in a logical central point (logical because you could very well have multiple instances of that central point colocated with your app for performance reasons). That logical central point in abac is known as the Policy Decision Point (PDP)
authorization is enforced based on the response back from the PDP in the place where you want to enforce it. This could be at a method level or at an API level or even a UI level: you choose. The component in charge of enforcing the decision is called a Policy Enforcement Point (PEP).
There's one main standard out there called xacml and its developer-friendly notation called alfa that will let you implement attribute-based access control. It's worth noting this model and approach is applicable to any app (not .NET-specific at all).

How to properly do resource-based authorization in ASP.NET Core 2.2?

I have an ASP.NET Core 2.2 application where I am displaying some documents. Most documents are public, so anonymous access is fine. However, some documents are private (i.e. they require authentication/authorization), and in the future some documents might also require a valid subscription. All documents are retrieved using the same actions, so we only know the required permissions after the documents have been loaded. We also load some resources as static files (IApplicationBuilder.UseStaticFiles), but I guess that shouldn't really be an issue as StaticFileOptions.OnPrepareResponse can be used for custom authorization code.
The logic for who gets access to private documents is currently really simple. And at the moment, we only display documents, we don't allow any other kind of operation on them (editing, deletion etc.). To me, this sounds like a pretty standard case of resource-based authorization.
Anyway, I have found this article and from what I've understood, I need to define a policy (identified by a magic string - what's up with that?!) as well as a requirement and an AuthorizationHandler<MyRequirement, MyResource> which will perform the actual authorization logic. Then, inside my controller action, I will need to call IAuthorizationService.AuthorizeAsync and pass in the user, the resource and the policy name (the magic string) and, based on the result from that method, allow or deny access. That seems more than convoluted for what I'm trying to accomplish. It would probably be easier if I simply defined my own kind of "authorization service" and simply dropped the whole policy and requirement stuff. I also think it's less than ideal that I would have to replicate the if-else logic in all affected controller actions.
Surely I'm not the only one with this issue. Is there something I've missed?
If there are indeed good reasons for using policies and requirements, how would you name them in a case like this? I'm really feeling a little lost.
Maybe it would make sense to use the type of document (public, private, subscribers-only) as the policy name?
In the end, we didn't want to deal with this stuff and just wrote our own AuthorizationService, which is injected into the controller like any other service.
It loads the required permissions for all documents the first time it is used and caches them.
Our controller methods then look something like this:
[HttpGet("[action]")]
public async Task<Document> GetDocument(string documentId)
{
if (_authorizationService.MayAccess(User, documentId))
{
return _documentRepository.GetDocument(documentId);
}
else
{
Response.StatusCode = StatusCodes.Status403Forbidden;
return null;
}
}
I recommend the last approach explained in this article - https://www.red-gate.com/simple-talk/dotnet/c-programming/policy-based-authorization-in-asp-net-core-a-deep-dive/
Allows you to keep you controller clean, by just applying annotation with the name of the policy. In the handler you must implement the logic checking if person can access the resource - it can be based for example on checking a property ownerId in a resource(for example in database table column) or a member of a certain group in AD, or anything else.
EDIT:
Using Requirements and RequirementsHandlers - I have done something similiar.
I don't know how should your logic exactly work, so I am just going to assume some.
lets say you have a get endpoint: documents/documentId
You want to apply logic which will make this document accessible only to the document owner. Obviously, you need somewhere to store who is the owner of the document, so lets keep that in property of a document entity.
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IsDocumentOwner requirement, DocumentRepository documentRepository)
{
if (context.Resource is AuthorizationFilterContext ctx)
{
var documentId = ctx.RouteData.Values["documentId"]?.ToString();
//here load document from repo and check if the property ownerId is equal to current user id
var userId = context.User.Claims.FirstOrDefault(x => x.ToString().Contains(oid))?.Value;
//if yes, make the request pass to the body of a controller with the attribute
context.Succeed(requirement);
}
}
implement IsDocumentOwner:
public class IsDocumentOwner : IAuthorizationRequirement
{
}
in your Startup.cs add:
services.AddAuthorization(options =>
{
options.AddPolicy(
nameof(IsDocumentOwner),
policyBuilder => policyBuilder.AddRequirements(
new IsDocumentOwner()));
});
then, last step, apply attribute on your controller method
[Authorize(Policy = "IsDocumentOwner")]
[HttpGet("{documentId}")]
public YourDocumentObjectResultClass GetDocument([FromRoute]string documentId)
{
//stuff you do when current user is owner of the document, probably just display the doc
}
To your IsDocumentOwner handler you can inject any service by constructor(visualised by repository above), for example, to check if the user is a member of a group on azure ad

Multi-tenant .Net Core Web API

I have a requirement to build a Web API for an existing system. There are various agencies throughout the country, and each agency has its own database. All databases are on one single server. All databases are identical in structure. All databases have their own username and password. An agency has one or more users. A user can belong to one or more agencies. There is also one special database which contains a table of all users, a table of all agencies, and user-agencies bridge table.
Currently they are using a traditional Windows desktop application. When a user sets up this Windows program, they log in with a username and password. The system then displays for them a list of all the agencies that they belong to (normally just one, but some "power users" can belong to a few). They pick an agency, and then the program connects to the correct database. For the remainder of the session, everything that the user does will be done on that database.
The client wants to create a web app to eventually replace the Windows program (and the two will be running side by side for a while). One developer is creating the front end in Angular 5, and I am developing the API in ASP .Net Core 2.1.
So the web app will function in a similar manner to the Windows app. A user logs in to the web app. The web app, which consumes my Web API, tells the API which user just logged in. The API then checks which agency(s) this user belongs to from that database that stores that data. The API returns the list of agencies the user belongs to to the web app. There, the user picks an agency. From this point on, the web app will include this Agency ID in the header of all API calls. The API, when it receives a request from the web app, will know which database to use, based on the Agency ID in the header of the request.
Hope that makes sense...
Obviously this means that I will have to change the connection string of the DbContext on the fly, depending on which database the API must talk to. I've been looking at this, firstly by doing it on the controller itself, which worked but would involve a lot of copy-and-paste anti-patterns in all my controllers. So I am trying to move this to the DbContext's OnConfiguring event. I was thinking it'd be best to create a DbContext Factory to create the DbContexts, using the appropriate connection string. I'm just a bit lost though. You see, when the web app calls an end point on the web api (let's say an HTTP GET request to get a list of accounts), this will fire the HttpGet handler in the Accounts controller. This action method then reads the Agency ID header. But this is all happening on the controller.... If I call the DbContext Factory from the DbContext's OnConfiguring() event, it would have to send the Agency ID (which was read in the controller) to the factory so that the factory knows which connection string to create. I'm trying not to use global variables to keep my classes loosely coupled.
Unless I have some service running in the pipeline that intercepts all requests, reads the Agency ID header, and this somehow gets injected into the DbContext constructor? No idea how I would go about doing this...
In summary, I'm a bit lost. I'm not even sure if this is the correct approach. I've looked at some "multi-tenant" examples, but to be honest, I've found them a bit hard to understand, and I was hoping I could do something a bit simpler for now, and with time, as my knowledge of .Net Core improves, I can look at improving the code correspondingly.
I am working on something similar you describe here. As I am also quite at the start, I have no silver bullet yet. There is one thing where could help you with your approach though:
firstly by doing it on the controller itself, which worked but would involve a lot of copy-and-paste anti-patterns in all my controllers.
I took the approach of having a middleware being in charge of swapping the dbconnection string. Something like this:
public class TenantIdentifier
{
private readonly RequestDelegate _next;
public TenantIdentifier(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, GlobalDbContext dbContext)
{
var tenantGuid = httpContext.Request.Headers["X-Tenant-Guid"].FirstOrDefault();
if (!string.IsNullOrEmpty(tenantGuid))
{
var tenant = dbContext.Tenants.FirstOrDefault(t => t.Guid.ToString() == tenantGuid);
httpContext.Items["TENANT"] = tenant;
}
await _next.Invoke(httpContext);
}
}
public static class TenantIdentifierExtension
{
public static IApplicationBuilder UseTenantIdentifier(this IApplicationBuilder app)
{
app.UseMiddleware<TenantIdentifier>();
return app;
}
}
Here I am using a self-created http-header called X-Tenant-Guid to identify the tenants GUID. Then I make a request to the global Database, where I do get the connection string of this tenants db.
I made the example public here. https://github.com/riscie/ASP.NET-Core-Multi-Tenant-multi-db-Example (it's not yet updated to asp net core 2.1 but it should not be a problem to do so quickly)

Advice on how I should return more than a simple type from my service layer

In my mvc3 application, I have things setup like:
1. repositories for each entity
2. service class for each entity that wraps the bare nhibernate db calls with business logic
Now for example, a class that registers a user, I want the service class to return something more than a boolean or user object if the user can register successfully.
Is this good practise?
Reason being, a person may fail to register correctly for reasons like:
1. duplicate email address in the system
2. duplicate username
3. etc.
So my method may look like:
public User Register(User newUser)
{
// check for a user with the same email
// check for a user with the same username
// validation checks etc.
return user;
}
I am thinking of creating a UserRegistrationResponse object so I can return back a much richer return value.
So something like:
public UserRegistrationResponse Register(User user)
{
..
return userRegistrationResponse;
}
This way I can return back a user frienly response I can propogate to the UI layer, and still get the user object and other information etc.
Comments on this approach?
I guess the only other way would be to throw exceptions, but is that really a good idea? The idea is for me to able to re-use these service classes, like say in a Restful service layer I will need in the future.
This is very common. 10 out of 10 WCF projects I've worked on in the past 3 years used this pattern. This includes legacy projects at three different companies, green field development and mvc/webforms projects.