Can anyone briefly explain what is the use of GenericIdentity and where to use it.
GenericIdentity and GenericPrincipal are the simplest way of describing a user as a "principal". This can be used for implementation-unaware security checking in an application - i.e. if the user logs in as "Fred" with the "User" and "Admin" permissions:
string[] roles = { "User", "Admin" };
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), roles);
You might do this at the point of client login to a winform, or there are specific points to do this in WCF, ASP.NET, etc.
Then later code, without having to know how those permissions are handled, can check that permission - either via IsInRole, or declaratively:
[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
void SomeAdminFunction() { }
Some useful utility code here is null-safe wrappers around principal/identity:
public static string GetUsername() {
IPrincipal principal = Thread.CurrentPrincipal;
IIdentity identity = principal == null ? null : principal.Identity;
return identity == null ? null : identity.Name;
}
public static bool IsInRole(string role) {
IPrincipal principal = Thread.CurrentPrincipal;
return principal == null ? false : principal.IsInRole(role);
}
Then you might have some audit code in your DAL:
row.UpdatedBy = MyUtilityClass.GetUsername();
GenericPrincipal is useful for the simple cases of a plain username and set of known roles.
More sophisticated principal implementations might, for example, do "on demand" access checking - i.e. until you ask for the "Foo" role it doesn't know - it then finds out (by talking to a web-service, database, active-directory, etc) and caches the result for future access. This is useful when the list of potential roles is large, and the number of roles typically queried in reality is small.
You can also use a principal to store extra identity information that is only needed in certain contexts - for example, a security token. Callers might test the principal with as to see if it supports the extra data.
Using "principal" is useful because your logic processing code can talk about identity, without having to know whether this is winforms, ASP.NET, WCF, a windows service, etc - it is abstract. Additionally, some 3rd party code will also talk to the principal.
As another example - I wrote some example code here that shows how to use the principal to control access to winform controls via the designer (via an IExtenderProvider - which puts extra entries into the property grid in VS).
You can use GenericIdentity as a concrete implementation of Identity where you want to supply the details yourself, programmatically, about the current user. Pretty good if you have identified and authenticated the user yourself, through other channels.
GenericIdentity class can be used in conjunction with the GenericPrincipal class to create an authorization scheme that exists independent of a Windows domain.
GenericIdentity myIdentity = new GenericIdentity("MyUser");
Check out
http://msdn.microsoft.com/en-us/library/system.security.principal.genericidentity.aspx
You will find some examples up there. It represents a generic user.
Authentication and profile perissions.
GenericIdentity Class:-
The GenericIdentity class implements the IIdentity interface. It represents the identity of the user based on a custom authentication method defined by the application.
GenericPrincipal class:-
The GenericPrincipal class implements the IPrincipal interface. It represents users and roles that exist independent of Windows users and their roles. Essentially, the generic principal is a simple solution for application authentication and authorization.
Related
I used Identity Server and protected endpoints with policies and roles. Those are reflected in the access token I'm distributing to the client. Today, I got the suggestion that instead of protecting a method like this:
[Authorize(Policy = "Elevated"), HttpGet("metadata")]
public IActionResult GetTenantMetadata() { ... }
we could skip the role section of the JWT and only do the following.
[Authorize, HttpGet("metadata")]
public IActionResult GetTenantMetadata() { ... }
Then, in the Startup.cs, we'd register a custom handler like this.
services.AddHttpContextAccessor();
services.AddTransient<IAuthorizationHandler, HeaderHandler>();
The actual security would be then performed in the handler based on the sub value from the token. No roles, no scopes no nothing. To me, it appears intuitively ill-advised putting a lot of responsibility on me to create the protective logic, instead of relying on IDS and people way smarter than me. All the solutions I've seen deal with security using claims and roles. So my gut feeling says it's a bad idea.
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
CustomRequirement requirement)
{
HttpRequest request = Accessor.HttpContext.Request;
string param = request.Headers.SingleOrDefault(a => a.Key == "param1");
string someAccess = dbContext.GetAccess(param, context.User.GetUserId());
bool authorized = SomeEvaluation(param, someAccess);
if (authorized) context.Succeed(requirement);
else context.Fail();
return Task.CompletedTask;
}
However, I wasn't able to motivate my choice (other than the guts and others' samples), so finally, I got unsure. I'm humble to understand that if I can't explain why, then maybe I'm wrong.
I googled claims based security and roles policies security etc. but I could come up with a name for the suggested alternative. Consequently, I haven't found any material discussing that matter.
What is such a custom authorization method called and what's the advantage/caveat of it?
It's still claims authorization, just not a good / practical one: you're only using the sub claim. There's no reason to throw away/not use perfectly good claims provided by a trusted identity provider.
First, letting clients send the user ID via a header is a security risk. How would you know if it's not tampered with, and the user is not pretending to be an admin? You can't, that's why you ask an ID provider to authenticate the user and sign a token for identification.
Second, cherry-picking the user ID and fetching other user claims at runtime from a database or API could work, but it may not always possible (app doesn't keep user data / delegates authentication to a 3rd party) or feasible (high traffic application, too many db lookups).
To authorize an action, you can declare policies with assertions. But for more advanced or imperative checks, you have the option to implement an AuthorizationHandler and imperatively allow/block an action.
It's useful for resource-based authorization, but an overkill for what would be a single line of code if the claims you need are already provided in the access token.
Further info
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/claims?view=aspnetcore-5.0
I am looking for a solution/suggestion that helps me creating permission based access to web api endpoints/controller actions.
Role based access is not suitable becuase I don't have fixed rules that I could use in code like Role("Admin") oder Role("Controller").
Claim based permissions is also not feasable because each user/client can have different permissions on each business object/entity (e.g. Read/Write-access to own tickets and read access to all ticket of his/her company or if its a technician of my company full access to all tickets of all customers. So each user would have 10s or even hundrets of claims which I would have to evaluate at each access of my API.
It is some kind of multi tenancy in just on database and the tenants are our customers with some kind of "master tenant" that has access to all of the tenant data.
I think that something like Visual Guard would satisfy my needs but it is pretty expensive and they don't support net core for now and their documentation seems pretty outdated.
I don't need a usable solution at once but some hints and tricks how I could achieve that would very much be apprieciated because I am looking and searching for some time now.
Details on "database permissions":
What I mean is in my frontend (Winforms app) I want to establish a security system where I can create and assign roles to users and in those roles is defined which actions a user can execute and which CRUD operations he/she can do on specific business objects. Each role can have n users and each role can have n permissions. Each permission on itself declares for exmaple Create:false, Read:true, Write:true and Delete:false. If a permission for a specific business object is not found CRUDs on that BO is denied totally.
So whenever an action in my API is called I have to check if that user and his/her rule allows him to do that specific action based on rules and permissions in my database.
Details an application structure:
Frontend will be a Winforms app which calls the API in the background by OData. I don't want to rely solely on security in the Winforms app because the API will be accessible from the internet and I can't be sure if a user would not try to access the api with his credentials just to see what is possblie without the "frontend filter". So the permissions lie in the API and if a user tries to access s.t. in the frontend app the app itself "asks" the API if that is possible.
Later on I want to create mobile clients that also use the Odata Web API.
The relevant API in asp.net core are:
IAuthorizationService
AuthorizationPolicy
IAuhtorizationRequirement
IAuthorizationHandler
The authorization pattern you are looking for is called Resource-based authorization
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased?view=aspnetcore-2.2
Basically, you can define AuthorizationPolicy, and apply it to a instance of a resource:
var ticket = _ticketRepository.Find(ticketID);
var authorizationResult = await _authorizationService
.AuthorizeAsync(User, ticket, "EditTicketPolicy");
In the authorization handler, you can check if the user is the owner of the resource.
public class ResourceOwnerRequirement : IAuthorizationRequirement
{
}
public class ResourceOwnerHandler
: AuthorizationHandler<ResourceOwnerRequirement, MyBusinessObject>
//: AuthorizationHandler<ResourceOwnerRequirement> use this overload to handle all types of resources...
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
ResourceOwnerRequirement requirement,
MyBusinessObject resource)
{
int createdByUserId = resource.CreatedBy;
Claim userIdClaim = ((ClaimsIdentity)context.User.Identity).FindFirst("UserId");
if (int.TryParse(userIdClaim.Value, out int userId)
&& createdByUserId == userId)
{
context.Succeed(requirement);
}
}
}
//admin can do anything
public class AdminRequirementHandler : IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
if (context.User.Claims.Any(c => c.Type == "Role" && c.Value == "Administator"))
{
while (context.PendingRequirements.Any())
{
context.Succeed(context.PendingRequirements.First());
}
}
return Task.CompletedTask;
}
}
BTW, this still can be called claims or role based authorization. Users with specific role can edit their own tickets, but users with admin role also other tickets. The difference is that you apply authorization to a resource, not just action
EDIT:
I have a 3 layer application - 1) The UI layer is a ASP .NET MVC application 2) The Business layer is a class library 3) The Data Access layer is a class library. I used role based authorization based on claims. I set the claims in the Application_AuthenticateRequest event handler
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var authenticationCookie =
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
var ticket = FormsAuthentication.Decrypt(authenticationCookie.Value);
FormsIdentity formsIdentity = new FormsIdentity(ticket);
ClaimsIdentity claimsIdentity = new ClaimsIdentity(formsIdentity);
// Get the roles from database
...
var role = GetUserRole();
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role));
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
Thread.CurrentPrincipal = claimsPrincipal;
}
Now I have two ways to access the role in business layer
1) Directly access the role from the Thread principal
var principal = Thread.CurrentPrincipal as ClaimsPrincipal;
var claim = principal.Claims.FirstOrDefault(x => x.Type ==
ClaimTypes.Role);
Pros:
Every method can implicitly access the role.
Cons
Difficult to unit test since it is dependent on a static object
2) Pass the role as a parameter to the method needing it e.g.
public IUserService {
void CreateUser(User user, string role);
}
Pros
Easy to unit test since role is explicitly passed to the method
Cons
Every method needs to have a parameter
If authorization is changed from role based authorization to any form of authorization, it breaks the system
What is the alternative ? What is the standard way of implementing role based authorization in business layer?
There is a standard way of implementing externalized, fine-grained authorization (not just role-based) across multiple layers. The model is called abac and stands for attribute based access control. There is one major framework which implements it and that's called xacml. Another alternative is claims-based authorization in .Net specifically.
ABAC/XACML defines:
a policy language with which to defines authorization rules e.g. a manager can view documents they own.
an architecture which defines on the one hand
a. a Policy Decision Point (PDP) which processes authorization requests and produces decisions (Permit/Deny)
b. a Policy Enforcement Point (PEP) which protects your application, intercepts business requests and sends authorization requests to the PDP. This is the piece of code that would sit in your app either as a filter, interceptor, annotation or more...
The nice approach with externalized authorization is that you can apply the same consistent authorization across multiple layers in one go (from web SSO to business tier and even data tier).
HTH. There are great resources on Wikipedia. You can also check out this blog I try to keep up-to-date.
I am creating an application where I first login with my user account. This user account could be windows or self managed account in my own application database.
Now I want to authorize the logged in user before accessing any business objects of my application. Objects are mapped with database tables so eventually I want to authorize user first, whether to give data back to user or not.
After logging in I store user credentials globally as an object of UserCredential class. But I don't want to pass this credentials to each object when I am creating it.
Is there any way to check/reach the application context (including UserCredential object I stored globally) for each business objects automatically which I am creating further?
I want to achieve this in C#. Code example is much appreciated.
You should take a look at the PrincipalPermissionAttribute class, here is the MSDN documentation:
PrincipalPermissionAttribute class MSDN documentation
The PrincipalPermissionAttribute throws a SecurityException when the Thread.CurrentPrincipal does not match the security assertion.
Examples:
User's name is GDroid:
[PrincipalPermission(SecurityAction.Demand, Name = "GDroid")]
public void YourBusinessMethod()
{
// Do something
}
User belongs to Admin role:
[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
public void YourBusinessMethod()
{
// Do something
}
User is authenticated:
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public void YourBusinessMethod()
{
// Do something
}
I've a SecurityService that has a AutoLogin method, that uses the ServiceSecurityContext to find out which windows identity is calling and then tries to find the related user account in the database. This is working fine when it is called from a web site that uses impersonation and requires integrated security in IIS. The call is using the stock NetPipeBinding.
I'd like to test the service as follows:
[TestMethod]
public void AutoLoginAsAnonymousFails()
{
using (var anonymousContext = WindowsIdentity.Impersonate(WindowsIdentity.GetAnonymous().Token))
{
ISecurityService securityService = ClientChannelManager.CreateSecurityServiceChannel();
var loginResponse = securityService.AutoLogin();
((ICommunicationObject)securityService).Close();
Assert.IsFalse(loginResponse.IsSuccessful);
}
}
On the service side the user in the securitycontext is always me - how to make it an anonymous user? I've already tried to impersonate the IntPtr.Zero but without success.
For reference the relevant part of the service method:
public ResponseMessage AutoLogin()
{
if (ServiceSecurityContext.Current.WindowsIdentity != null
&& !ServiceSecurityContext.Current.WindowsIdentity.IsAnonymous
&& !ServiceSecurityContext.Current.WindowsIdentity.IsGuest
&& ServiceSecurityContext.Current.WindowsIdentity.IsAuthenticated)
{
// find the user based on his windows identity and return success = true message
}
// return success = false message
}
This is a classic example of how separation of concerns could help you. Instead of relying directly on ServiceSecurityContext (something that one should, IMO, never do), make sure to configure your service so that security information is instead encapsulated in Thread.CurrentPrincipal.
IIRC, when you use Windows authentication and impersonation, it may even set this up for you automatically, but otherwise, you can always write a custom ServiceAuthorizationManager, that does this for you.
This will allow you to vary your security concerns independently of your domain logic. If you stick with the IPrincipal interface and resist the temptation of downcasting to WindowsPrincipal, your code will even be ready for the future of identity: Claims-based Identity, as implemented by the Windows Identity Foundation (WIF).
This also helps tremenduously with unit testing, because you can then just assign a GenericPrincipal to Thread.CurrentPrincipal before invoking your System Under Test (SUT).