I have two separate SPA web applications, one for AR invoicing and the second is for AP invoicing. Each application has its database that contains the list of users allowed to use the application. Each application has its ASPNET core web API that it uses to interact with its database. Both applications are using the same Identity server to authenticate the users and give authorizations to use the applications’ API resources. My issue is to find the best way to implement user permission on both applications. I should only allow users that are successfully authenticated in the IDP to access AR invoicing application only if they exist in the User table of this application and the same thing for the AP invoicing application. I know I could add a claim at the identity server to distinct users that belong to the AR invoicing application and the users belong to the AP invoicing, but I think this is not the best implementation since adding this kind of info is not part of the user identity. I’m thinking to override the authorize attribute or add a policy to check if the user is authenticated and exist in the requested application, but this approach will require the application to check the application’s user table for each API call. Could you please advise or redirect me to any tutorial that handles this kind of need.
-
Perhaps my answer [here](https://stackoverflow.com/questions/52079466/is-claims-based-authorization-appropriate-for-individual-resources/52100609#52100609) may be useful. – Jul 26 '19 at 21:00
-
In order to solve the problem with authorization the creators of IdentityServer developed [PolicyServer](https://policyserver.io/). This way authorization is outsourced, just like authentication is outsourced. – Jul 26 '19 at 21:11
1 Answers
If you have an Identity Server instance, you can integrate ASP.NET Identity into it easily. Then, in your APIs (resources) you wouldn't need user tables at all - the controllers will automatically have a User
instance available after authorizing against the Identity Server. This User
is a ClaimsPrinciple
that is essentially a collection of claims you can check.
EDIT: Providing more detail on answer.
You mentioned that "Each application has its database that contains the list of users allowed to use the application". My point was that you could have the entire set of users for both applications reside only in the Identity Server's database. This would enforce separation of concerns - the AR/AP apps would only be concerned with AR/AP tasks, while the Identity Server would be concerned with users and authentication/authorization. There is really no need for the AR/AP apps to know any user details - they should just add Authorize
attributes and assume that, if a user is able to enter a given endpoint, that user has been properly authorized.
Now, you will need to appropriately build how each app will be authorized. This can be done using claims, roles, or even policies (a way to combine both, and add more advanced authorization logic). For example, you can add this to the AP app when configuring services:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthorization(options =>
{
options.AddPolicy("CanCreateInvoice", policy =>
{
policy.RequireClaim("CreateInvoice");
policy.RequireRole("Admin");
policy.RequireUserName("user1");
⋮
});
⋮
});
}
Then you can add this to an AP app endpoint:
public class InvoiceController : Controller
{
[Authorize(Policy = "CanCreateInvoice")]
public IActionResult CreateInvoice()
{
// Assume the user meets your policy requirements
// Create the invoice
};
}
This way, the AP app has no need to be concerned with any user details - it only performs AP-related tasks. If you need to add the id of the user to the created invoice, you may do something like:
invoice.CreatedBy = User.FindFirst("sub").Value;

- 4,332
- 1
- 22
- 40
-
I have already ASP.Net Identity that is used by identity server to store users. This table will contain all the users that are allowed to access to the AR or/and AP invoicing. for example in the ASP.Net identity, we have 3 users, user1, user2 and user3. – dalios Jul 27 '19 at 08:40
-
@dalios I added more detail to the original answer. Hopefully that is helpful. – crgolden Jul 27 '19 at 13:18
-
I’d argue you’re mixing concerns with this suggestion - authorisation of users should not be handled in the IDP. – mackie Jul 27 '19 at 14:01
-
@mackie I'm not sure I understand your comment. The authorization of the users is not handled by the IDP - it happens at each API endpoint that's decorated with an `Authorize` attribute. The authentication of users is handled by the IDP. – crgolden Jul 27 '19 at 14:43
-
@crgolden you're bringing permissions into to the IDP - "CanCreateInvoice" is something only the invoice creating service can define and know. If the rules change do you then have to change your IDP service? Give this a read: https://leastprivilege.com/2016/12/16/identity-vs-permissions/ – mackie Jul 27 '19 at 14:59
-
@mackie The "CanCreateInvoice" policy is nowhere in the IDP. As I stated in my answer, you "add this to the AP app" when configuring its services. Then, you decorate "an AP app endpoint" with the `Authorize` attribute and direct it to check the policy. I still don't understand where you think the IDP has anything to do with this - it's all happening on the API resource (the AP app). – crgolden Jul 27 '19 at 17:16
-
@crgolden I miss-typed - I was referring to the claim "CreateInvoice" - this is not something the IDP would or could know. – mackie Jul 27 '19 at 18:15
-
@crgolden The table users will be in the IDP (aspnetuser identity table). I will add another table on each app to add the user claim specific to each app. am I correct? – dalios Jul 28 '19 at 18:34