I am trying to implement authorization for a WCF service but I have run into some significant difficulties. I think I need to use a hybrid solution combining custom authentication and claims, but I am not sure if this is correct.
My application uses Windows authentication to connect to the application. Once the user has been authorized, access to functions needs to be granted based on permission information stored in the database.
Users can be assigned permissions via the application interface. One level of the permission heirarchy corresponds to access to individual WCF functions:
Access to module (purely organizational)
Access to function (access to WCF function, checked automatically)
Function-specific permissions (checked dynamically in code)
Sample structure and usage:
Shipping
Can Create Shipment
Can override naming conventions
Can Package Shipment
Must be verified by supervisor
Can generate customs documentation
...
class ShippingService : IShippingService
{
// Access corresponds to "Can create shipment" permission
public bool CreateShipment(string name)
{
...
// Check the function-specific permission dynamically.
if (!ConformsToNamingConvention(name) && !CheckPermission(Permissions.CanOverrideNamingConvention))
return false;
....
return true;
}
}
I think what I need to do is to create a custom Authorization Policy by implementing IAuthorizationPolicy. This will connect to the database, pull the permissions for the user and add a claim for each of the permissions. I will then need to create a custom authorization manager that will compare the requested action with the list of claims to determine if the connecting user is authorized.
Is this the correct way to approach this, or am I:
a) overcomplicating the issue, or
b) using WCF components incorrectly (such as claims, IAuthorizationPolicy, AuthorizationManager...)
Thanks in advance for any help, and best regards.
The problem you'll have with this approach as with just about all the other approaches is the fact you want to allow business users to create and delete roles on the fly. How are you even going to check that in code? Typically, you'd restrict execution of a method or service call to a specific role (or set of roles) - how is this going to work if you want to have roles that get created dynamically at runtime?
If you can live with pre-defined roles, there's a few solutions. Have you checked out the ASP.NET role provider? It's part of the more general ASP.NET membership and role provider set, but it can be used on its own, too.
To activate it, use this snippet in your config (once you've set up the basic infrastructure for the ASP.NET role provider stuff):
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceAuthorization principalPermissionMode ="UseAspNetRoles"
roleProviderName ="SqlRoleProvider" />
</behavior>
</serviceBehaviors>
</behaviors>
The only other idea I have is looking at the Authorization Manager (AzMan): this is a set of tools to allow you to specify fairly granular "atomic" permissions that a business user can then compose into roles and assign users to those. But basically, in the end, at the bottom level of the granular program functions ("Tasks" in AzMan), you're dealing with a static set of rights, again.
Check out this MSDN article on AzMan as an introduction and see this article in the WCF security guidance on how to use it from a WCF service. I don't know the current status of AzMan and I don't know if it will be developed much further anymore - it almost seems a bit like it won't (but I'm not 100% sure on that).
Marc
Related
I'm quite new to the entire auth design and am still trying to understand how to use keycloak for authentication and authorisation.
Currently from what I understand in order to have authorisation enabled for a client you will need to have it in confidential.
After which I am kind of stuck in terms of how to set which policy for which permission.
I have a few types resources but currently placing them all under a single client for simplicity sake.
For my use case I have a workspace for users. So each workspace can have multiple users with different roles of owner,editor,viewer. And within the workspace there are artifacts. So it is some what like designing an authorisation for Google drive.
Would like some advice on how best to design it.
One way I have thought of is using groups and each workspace is a group. Using it to assign users to each group as a way to use the group policy for permission.
The other is really by creating multiple policy and permission for each artifact/resource and adding user to each policy for each workspace.
Would like any advice on authorisation design or even where to begin reading.
After some research I have come to these conclusion.
Yes these can be done by keycloak though most likely shouldn't be done in keycloak itself for its design.
Keycloak itself will most likely be more suitable in terms of authenticating/authorising on services or infra level. So this use case of having user be able to access workspaces or artifacts will be better done in application level having a separated service to handle the permission itself.
That being said if it really needs to be done in keycloak the design that I thought of that is not so scalable is as follow.
Create a policy/user and each workspace/artifact as a single resource. Depending on how many types of access/fine grain control is needed for each type of resource create the scope for each (e.g workspace:view, workspace:edit...). Then create a permission for each resource&scope. This allows fine grain access of basically assigning user to permission of each resource through the user policy.
But of course this design has its flaws of the need of too many policies, permissions and resources so it is better to have keycloak just handle the authentication part and authorisation is just giving users the role to be able to access a service and through the service check if the user is authorised for a certain action.
I'm extremely confused on how to use a centralized IDP with both authentication and authorization. The architecture for my project was to be a single web API and one React client. I wanted to keep things structured out into microservices just to try something more modern, but I'm having major issues with the centralized identity, as many others have.
My goal is fairly simple. User logs in, selects a tenant from a list of tenants that they have access to, and then they are redirected to the client with roles and a "tid" or tenant id claim which is just the GUID of the selected company.
The Microsoft prescribed way to add identity in my scenario is IdentityServer, so I started with that. Everything was smooth sailing until I discovered the inner workings of the tokens. While some others have issues adding permissions, the authorization logic in my application is very simple and roles would suffice. While I would initially be fine with roles refreshing naturally via expiration, they must immediately update whenever my users select a different tenant to "log in" to. However, the problem is that I cannot refresh these claims when the user changes tenants without logging out. Essentially, I tried mixing authorization with authentication and hit a wall.
It seems like I have two options:
Obtain the authorization information from a separate provider, or even an endpoint on the identity server itself, like /user-info but for authorization information. This ends up adding a huge overhead, but the actual boilerplate for the server and for the client is minimal. This is similar to how the OSS version of PolicyServer does it, although I do not know how their paid implementation is. My main problem here is that both the client and resource (API) will need this information. How could I avoid N requests per interaction (where N is the number of resources/clients)?
Implement some sort of custom state and keep a store of users who need their JWTs refreshed. Check these and return some custom response to the caller, which then uses custom js client code to refresh the token on this response. This is a huge theory and, even if it is plausible, still introduces state and kind of invalidates the point of JWTs while requiring a large amount of custom code.
So, I apologize for the long post but this is really irking me. I do not NEED to use IdentityServer or JWTs, but I would like to at least have a React front-end. What options do I have for up-to-date tenancy selection and roles? Right when I was willing to give in and implement an authorization endpoint that returns fresh data, I realized I'd be calling it both at the API and client every request. Even with cached data, that's a lot of overhead just in pure http calls. Is there some alternative solution that would work here? Could I honestly just use a cookie with authorization information that is secure and updated only when necessary?
It becomes confusing when you want to use IdentityServer as-is for user authorization. Keep concerns seperated.
As commented by Dominick Baier:
Yes – we recommend to use IdentityServer for end-user authentication,
federation and API access control.
PolicyServer is our recommendation for user authorization.
Option 1 seems the recommended option. So if you decide to go for option 1:
The OSS version of the PolicyServer will suffice for handling the requests. But instead of using a json config file:
// this sets up the PolicyServer client library and policy provider
// - configuration is loaded from appsettings.json
services.AddPolicyServerClient(Configuration.GetSection("Policy"))
.AddAuthorizationPermissionPolicies();
get the information from an endpoint. Add caching to improve performance.
In order to allow centralized access, you can either create a seperate policy server or extend IdentityServer with user authorization endpoints. Use extension grants to access the user authorization endpoints, because you may want to distinguish between client and api.
The json configuration is local. The new endpoint will need it's own data store where it can read the user claims. In order to allow centralized information, add information about where the permissions can be used. Personally I use the scope to model the permissions, because both client and api know the scope.
Final step is to add admin UI or endpoints to maintain the user authorization.
I ended up using remote gRPC calls for the authorization. You can see more at https://github.com/Perustaja/PermissionServerDemo
I don't like to accept my own answer here but I think my solution and thoughts on it in the repository will be good for anyone thinking about possible solutions to handing stale JWT authorization information.
When creating an Angular web application that also has a backend API, I feel like there are a few different options when it comes to getting User Info such as roles/permissions/display name/email/etc.
We can use an ID Token to store user claims like this. That token can be put into local storage or a cookie and the Angular app can read it and render the UI/guard against unauthorized route navigation/etc as soon as the app spins up (since the ID token is available right then and there).
We can NOT use an ID Token for this information at all and instead have an API endpoint that we have to call every page re-load to fetch this data. The server would decode our access token/ID token and return the data in JSON format.
Lastly, there could be some hybrid solution where basic User Info like names/emails are stored int he ID token and available right away, but user permissions (which could be a larger payload and maybe not wanted in a token that should be small) could be fetched via an API
Is there maybe a 4th option I didn't think about?
I haven't been able to find many conventions around which of these options is the best. I like the ID token option as it requires no "blocking" of the UI until the API request is done making the page load that much faster, but I'm not sure if that goes against other conventions.
All your approaches rely on a permissions-based system where you would have been granted permissions upon login. These are sometimes referred to as birth rights since they are typically given when the user is created or whenever their permission sets change. The typical way to carry birth rights around is to have them as scopes / assertions inside an identity token (e.g. OAUth 2.0) that you pass along from service to service.
You can also have your applications retrieve additional permissions / roles / entitlements from a backend store (a database for instance) based on the user ID so that you know what your user can or cannot do.
So far this is essentially role-based access control / permissions-based access control.
The main challenge with that approach is role explosion / permissions explosion as well as token bloat (too many permissions in the token) and administration pains - you have to assign roles and permissions to users all the time. You have to deprovision. It becomes a management nightmare and a risk you may have the wrong permissions set for users. You then need to think about identity and access governance as well as recertification. Heavy.
What's the alternative?
You definitely need some roles - yes - but they should be kept to a minimum - essentially the business roles you need in your apps e.g. a doctor, a nurse, a non-medical staff rather than doctor_hospital1_unitA.
You should then express your authorization as plain-old English policies using any number of attributes - not just user attributes but also contextual information (time, location), resource information (what type of object, who owns it, where is it? How sensitive is it?), and action information (view, edit, delete...).
Sample Policies
A doctor can view a medical record if they are assigned to the patient the medical record belongs to
A nurse can view a medical record if the medical record is in the same unit as the nurse
A non-medical staff can view the financial section of a medical record but not the medical section.
Attribute-Based Access Control
Following this approach is called attribute-based access control (abac). In ABAC, you clearly decouple your app from the authorization process. Authorization is expressed as policies rather than code which makes it easier to:
update
audit
review
How to implement?
You have several options to implement ABAC (from open-source to commercial). You can go down the XACML (xacml) path, the ALFA alfa path, or others. They all have similar architectures with:
the notion of a policy decision point (PDP): a service that evaluates the authorization requests against the set of policies you defined and produce decisions (Permit / Deny) that can be enriched with additional information e.g. order to do two-factor Authentication.
the notion of a policy enforcement point (PEP): an interceptor that sits in front of or inside your API that will send an authorization request to the PDP.
I've written about the architecture more in detail in this SO post.
ALFA Example
In ALFA, a sample policy would look like:
policyset viewMedicalRecord{
target clause object == "medical record" and action == "view"
apply firstApplicable
policy allowDoctors{
target clause role == "doctor"
apply firstApplicable
rule allowAssignedPatient{
permit
condition patient.assignedDoctor == user.name
}
}
}
Suppose that I have a web application. Consider it like a Black-Box for now. I want to use a backend system to limit what a user can view/do on the app.
i.e. Sample users can only do three functions, Premium users can do 10 functions and see more pictures.
What is the best way to do it?
I'm trying to using WSO2 Identity Server, but it doesn't offer this functionality. So I've thought that maybe I can integrate it with the WSO2 API Manager and make an API that limits users' access to a certain resource. But really I cannot find if it's possible do it. Anyone know it?
Please refer to : https://docs.wso2.com/display/IS530/Access+Control+Concepts
1) WSO2IS can act as a coarse grained access manager. Your application will act as a fine grained access mnager.
It means that roles can be defined in WSO2IS, managed and assigned to user. From there Roles assigned to one user can be provided as clains with the identity token generated by WSO2IS and sent to the application.
The application, on the other side, will manage roles to permissions links.
Access control is then done at each request by the application, based on the roles presented in the Identity Token by the user and the Permissions grid based on roles in the application.
2) The access control at the application is a business logic you must implement (or at least configure if it a COTS). It is possible to outsource this logic to WSO2IS as policies on attribute (with Workflows).
Please look at : https://docs.wso2.com/display/IS530/XACML+Architecture
Jeff
I'm new to WCF and REST so please excuse any obvious questions.
I'm trying to create a RESTful API that will be used by clients. The API needs to be available only to authenticated users so I believe the best way to do this (from what I've read over the last couple of days) is using Basic Auth over SSL which is fine.
I have a basic WCF REST Service Application in VS2010 targeting .NET 3.5. - the bare bones of this have been directly taken from http://www.codeproject.com/KB/WCF/BasicAuthWCFRest.aspx
What I'm struggling to understand and to differentiate on is how to authenticate suers while also restricting the calls that clients can make based on who they are.
So the call that the clients will need to make will pass some basic information from their system to ours, each client will be able to make the same call however I don't want client A being able to post info into client B's area on our side and vice versa.
I was planning on having both clients POSTing something like the following url:-
api.mydomain.com/sale/
however, I wonder if it would make more sense to make it clearer to do this:-
api.mydomain.com/clientA/sale/
api.mydomain.com/clientB/sale/
...as you can see, I'm quite lost!
Also, the example code I have is using a custom MembershipProvider - I understand the basics of Membership but again, don't know if I should be using this in some way to restrict the clients posting data to eachothers areas?
Sorry for the waffling - sooo many questions :(
Regarding authorization (granting an authenticated use access to specific resources) there's a couple of ways.
You can restrict access to certain areas (directories / URL paths) via the <location> element in the web.config, and then using the <authorization> element only allow certain users or roles (groups) to access those locations. This is OK if the number of locations / users / roles is manageable and doesn't change too much. For example:
<location path="ProtectedPlaces/Foo">
<system.web>
<authorization>
<allow roles="FooGroup"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
Alternatively, under the covers you can use an API based approach that essentially does the same thing. There are a number of libraries out there that can help, including AzMan; an authorization library that's in the same 'family' as the role membership provider; there is also one in the Enterprise Libraries.
This article might be of some help (see: "Step 2: Limiting Functionality Based On the Currently Logged In User’s Roles").
Here is how I did this. I used a standard membership provider (but you can also do the same with a custom membership provider) to authenticate the user, but I do not let IIS do this. I authenticate the user myself (as part of the REST API) and generate a token for that user, which I store in the membership database and send back to the client.
For each request the client makes it needs to send a valid token as well. As the token is stored together with a user id, I can then determine if the token is valid and what user is making the request. Because of this I can then determine if the request is allowed based on my own security rules.
If a user is only allowed to do a certain request on it's own data, then you don't need to send any identifying information except for the token.
HTH.