Where to implement the user profile page using IdentityServer4? - asp.net-core

I have a solution with 3 projects in ASP.NET Core:
MVC --- no DB (calls the API)
Web API --- MySQL 5.7 own DB
IdentityServer4 + ASP.NET Identity --- MySQL 5.7 own DB
I've managed to get authorization and authentication working between all three apps using in memory clients, users, resources following the great documentation found on https://identityserver4.readthedocs.io/.
Currently I'm using the HybridAndClientCredentials flow which works well with existing users as well as registered users. Newly registered users are saved in IdentityServer DB, using ASP.NET Identity tables.
The problems:
One of my client requirements states that the user should have a profile page inside the MVC app to which the user should be redirected after he is authorized & authenticated successfully.
What I'm doing right now is calling the API in the MVC app, OnTickedReceived event, with the initial claims to create the user in the API DB, but I have doubts that this is the correct implementation.
Since the registration is done and persisted at IdentityServer level and some data about the user is stored there, should I make the profile page there too or should I make a call to the API somewhere in the registration flow to create the user in the API DB too, then redirect the user to the MVC app to input the rest of the details required for a complete profile?
Another requirement states that a user should be able to grant read/write access to another user's details (as in linked accounts or something).

Unfortunately, "it depends".
Let's start by asking "what is the profile page?". What information is on the profile page and is that information specific to your application (MVC/WebApi) or the identity management system.
IdentityServer supports the OIDC UserInfo Endpoint and Profile scope with ASP.NET Identity so that could work well. (http://openid.net/specs/openid-connect-core-1_0.html#UserInfo). You can insert IdentityClaims into the AspNetUserClaims table and get those back when you call the UserInfo endpoint.
But maybe this profile page mentioned in the requirements is information belonging to just the application's domain and therefore has no business being in the identity management system. Then, your current approach is ok- though maybe you could use a Filter Attribute instead of an authentication event (that's just a thought, might not be better).
To me, the decision is about who owns this so-called "profile" information. Is it the identity management system or your business application.
If the profile information can be shared across any client of the identity management system, then put it in the identity management system.

Related

Microsoft Identity Delegated and Application Permissions in same API

I've been working with some of the ASP.NET core examples for APIs secured using Microsoft Identity. One scenario I haven't been able to find an example for is when you have a protected API that needs to make requests to another API (Microsoft Graph, one of my own APIs, etc) with delegated AND application permissions.
For example, say I want to update a user's profile on behalf of the user (delegated), but then I want the application to update their manager's profile using the application permissions (on behalf of the application's identity). Is there an example of this scenario? Would the application that's making the API calls request two tokens?

Add user claims after authentication against IdentityServer 4

I have the following projects:
Identity Server 4, with ASP.NET Identity as a user store for all users of all my apps.
.NET Core 5 Web API
Xamarin app
The flow goes like this:
User logins from the Xamarin app (3) and is authenticated against IdentityServer (1)
User receives an access token from Identity Server, that contains the sub claim
User makes a request to the Web API (2) using the access token
The Web API (2) checks its own database for user permissions
----QUESTION/PROBLEM IS HERE-----
Should the Web API add these user claims (permissions) to the access token, OR should the Web API always check the database for the user permissions on every request made from the client?
Maybe I could add the claims before authenticating with IdentityServer, but this would mean that IdentityServer would have access to the Web API's database. I believe this is not a good practice because of separation of concerns.
Another solution would be to introduce a caching mechanism when the Web API validates the token, so that it doesn't always check the database.
Using claims transformation, it is my understanding that I can add the claims to this 1 request only, meaning that the next time a client makes a request, claims transformation should happen again, since it doesn't return a new access token to the user.
Ideally, I would like the Web API to add the claims to the access token so that the Web API can trust these claims on all subsequent requests. I cannot find a way to do so, though. I've searched for Claims Transformation, IssueJwtAsync (IdentityServerTools), IProfileService, but I think none of these are solutions to this problem.
Is this good architecture? Please do share your opinions on this subject and potential solutions.
Thank you very much!
You need to add these permissions in web api, because users need to access the corresponding resources according to these granted permissions. And permissions are granted when the user logs in for the first time, without the need to access the database in every request.
In this case, you can use Claims Transformation. This link has more detailed steps which can solve this problem.

Authorizing by updating Claim with data from database (Blazor WebAssembly ASP.NET Core hosted)

I have a question regarding authentication in my web-app using Blazor WebAssembly ASP.NET Core hosted. The database used is Azure SQL.
I want to avoid storing passwords in the database and the users are therefore restricted to having a Microsoft-account (relevant to the project).
As of now, the user logs in with Azure AD as the third-party authentication provider. When redirected back to the web-app, a user is created with a claim which only consists of the Email from Azure. The user is directed to a registration page where the Email-input is set to the current user-claim email. When the user clicks the register button, the information provided is now stored in the database.
The problem is that I now have a user in the db, but the claim is still just the Email. I want to be able to use the AuthorizeView role tag on the different pages, and therefore wondered if its possible to update the claim with a role that the user specified in the registration-page? This data is at this point only stored in the database.
If this is a bad practice, is there any other similar way I could make this work?
To use the AuthorizeView role, roles claims should be return by your Identity provider (Azure AD in your case). Your application should ask those claims by asking the corresponding scope.
According to the doc : Permissions and consent in the Microsoft identity platform endpoint, the profile scope should return roles claims.
The doc Secure an ASP.NET Core Blazor WebAssembly standalone app with Azure Active Directory explains how to request scopes from Azure AD

How to manage users in ASP.NET core with AD / LDAP? Do I store the users in a database?

I am writing an internal app where all the users are part of AD. I have the following steps to implement this. Is this correct?
Create Action filter to get all HTTP request to website and check in they are in the specific AD role needed (var isUserInRole = User.IsInRole("M2-ITU-PWApplicationDevelopers"))
If user is not in any of the application roles send user to error page
If user is in application role then Add users to SQL DB and link to Role table in DB so now I have the user/role data ready to use in DB along with other data
When user revisits check the database first before LDAP?
How do I set a cookie or something so that every request does not need through process once authenticated ?
Trying to understand the basics.. Maybe I am going about this all wrong ?
Use Windows Authentication. Your application need to be behind IIS to do it in ASP.NET Core 2.2 and lower, but starting ASP.NET Core 3.0 you can do it with Kestrel alone.
If you do that, you can skip steps 3 and 4. When a person is authenticated via Windows Authentication, the application gets a login token that contains all the security groups that the account is a member of. So User.IsInRole is pretty quick. There is no need to store that information in your own database.
You also don't need to worry about cookies.
The added benefit of Windows Authentication is that it can support seamless login: if your site is in the Trusted Sites in Internet Options, then IE and Chrome will automatically send the credentials of the user currently logged into Windows. The user doesn't have to type in their credentials.
Firefox uses its own network.negotiate-auth.delegation-uris setting for the same purpose.

Web API Security using Individual User Accounts and Custom Storage Provider

I am developing a REST based application using Web Api 2. On the project, I elected to use the individual user accounts option when I created my project. On the frontend, I am using a combination of angularjs and ios interfaces to interact with web api. I would like a user to enter their credentials and upon successful authentication, receive a jwt token(SSL) that they can use as long as the ticket hasn't expired. I read an article outlining how to create a custom storage provider, which I need as my user schema is different from asp.net identity.
What is the recommended approach to this scenario?
Can someone provide an example of how to setup .net individual accounts for authenticating users trying to access web api action methods? As stated above, the user interface is angularjs.