asp.net core identity tracking user open sessions - c#

We have a web application built with asp.net core, .net core 3.1, angular which uses asp.net core identity for user authentication management.
We have a need to implement the below scenario:
"If user A is logged in (this is an open session) and user B logs in with the same credentials (this is the 2nd concurrent session), after user B passes MFA, we will send an email to the email address of this customer to notify them that someone else just logged in. We will NOT end the session for the user A."
Our current implementation uses ASP.Net identity to authenticate users with Authentication Tickets being stored in cookies. Since authentication tickets are stored in cookies, the session is browser based, hence being able to track whether the user is logged in with an ongoing open session is not possible with this implementation.
I was leaning towards using custom store for storing auth tickets on server side with either database / redis, and then tracking token expiration thereby determining an existing ongoing session. Am I thinking along the right direction, or are there other mechanisms ? I would like some thougts and suggestions.

ASP.NET Core Identity use Cookie authentication . That means when user B login in your application , application doesn't know whether user A is active , only next time userA send request with cookie to application , then application could check whether user A is active(authentication ticket is not expire ) and create a email response . If user A doesn't send request to server , server won't know the state of user A since cookie is only sent with HTTP request .
You can use asp.net core signalr which enables server-side code to push content to clients instantly.

Related

ASP.NET WebAPI. Do not persist sessions

I have an ASP.NET 6 WebAPI application.
I've implemented login functionality, which boils down to calling:
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
It sets a cookie with key .AspNetCore.Cookies and value of ID of the user session.
Somehow these sessions are persisted across WebAPI restarts. User agent with this cookie is still logged in when sending HTTP requests to WebAPI after restart. Where these sessions are persisted? Is there a way to disable this behaviour?
For clarity: I'm not using .AspNetCore.Session-related functionality, we're speaking solely on .AspNetCore.Cookies based user authentication.
Thanks in advance.

Is it possible to sign out a User in IdentityServer4 as a different user?

The flow I am trying to figure out is this:
UserA is logs into ClientA
ClientA redirects to Idenitity Server to authenticate user
after authentication ClientA manages User info in its own system
UserA is found to be a "bad actor"
AdminUser goes into IdentityServer AdminTool (a different client application for managing the IdentityServer, including users).
AdminUser performs an action to "revoke" UserA
A call is made to the IdentityServer back-end from the admin tool where UserA has an "Enabled" property that is set to false.
At this point in the flow I want to kick the user out of ClientA from the back-end of the IdentityServer.
More context:
IdentityServer is using cookies in the client browser to keep the "session" (not sure if that is the right word cause there isn't actually any state being managed).
Also using cookies for remember-me.
Is there a way to remove the cookie for the IdentityServer from the back-end? Or notify the client that UserA should no longer have a valid authentication so that it can perform HttpContext.SignOutAsync()?
I was reviewing this link: https://docs.identityserver.io/en/latest/topics/signout.html for guidance but I am stuck on how to do this from the back-end as the AdminUser. Calling HttpContext.SignOutAsync() would sign out the AdminUser that made the request, not UserA that is causing havok in ClientA.
In a typical setup with identity server you have:
A JWT token with a short lifetime
A session cookie
The JWT token needs to be renewed frequently. The session cookie is used when there's no valid JWT. In this case the user will be redirected to the login page and if there's a session cookie the user will be automatically authenticated and redirected back to client app.
So you have some options for your logout:
Ensure the user cannot renew his JWT (= logout after a few minutes)
Ensure the user cannot login again
Really clear everything in the browser (and ensure he cannot login/renew again)
Back to your question
Is there a way to remove the cookie for the IdentityServer from the back-end?
The answer here is WebSockets which allows a two-way communication.
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
A common library for C# is Signal/R
https://dotnet.microsoft.com/apps/aspnet/signalr
You would create a Hob on the server side that allows you to send messages to the "bad user".
https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-6.0
And listen for those messages in your client app:
https://learn.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0
Please note: Whatever you do on the client side, the important part is typically to block the server requests. It's not secure to delete the cookie on the client. You have to delete the session on the server side instead.
Additional notes:
The flows in your setup may be different from what I described above.
I know, this is just a partial answer, but it's too much content for a comment ;-)

How we can enable SSO identity server 4?

Should I Create only one client and all my applications must connect to the identity server using it or there is configuration should I do to make it work?
Identity Server is Web API, grant type is "resource owner password".
Each application is a client. But whether you should use the same client_id is up to you. Personally I use different client_id's for each instance of an application. This helps me to identify the instance and allows me to use different secrets per instance. And I think that the client_id has to be unique when you are using refresh tokens.
SSO is something you get for free when you use OpenId Connect (oidc). It works because of a cookie on the IdentityServer website:
When a user has to log in, the user is redirected to the IdentityServer website where (after succesful authentication) a cookie is set, containing information about the identity of the user.
When the user is returned to the client (after succesful authentication) the client will also set a cookie. As long as this authentication cookie is available, the user will be logged in.
When the user needs to log in again, because the client can't authenticate the user (anymore), IdentityServer will try to identify the user with the information from the cookie on the IdentityServer website and (if succesful) automatically sign in the user, skipping the login form.
But it seems that your setup has nothing to do with oidc. When you say that IdentityServer is a Web Api then this suggests that the user is not redirected to the IdentityServer to login, meaning that there is no opportunity to set a cookie.
And Resource Owner Password Credentials (ROPC) is an OAuth2 grant type. This suggests that the user performs the login on the client.
In order to enable SSO, the user has to login on the IdentityServer website. While ROPC is still possible, you'd better use one of the recommended grant types.

Setting up FormsAuthentication after SSO authentication

My ASP.NET MVC 4 application is protected by SSO (OAM) with an ISAPI filter running on IIS. When a request to my application is received, it is intercepted by ISAPI filter and redirected to SSO. User has to login at SSO and after that he is returned to my application.
The username of authenticated user (via SSO) is shared with my application in HTTP Request Headers.
Request.Headers["username"]
What I am trying to achieve is- after SSO authentication, setting FormsAuthentication within my application for username = Request.Headers["username"]. This way SSO remains transparent to my application and Identity of user is available in HttpContext object, plus, I (developer) could effectively utlize Authorize attribute for specific roles.
To achieve this- I hookup into Session_Start(), read Request.Headers["username"], Set FormsAuthentication cookie. And I get this SSO user Forms-Authenticated for my application.
But my problem is when I logout (FormsAuthentication.Signout), I redirect it to another page inside the application, which triggers a new Session (I can see Session_Start triggering when this happens)
Am I doing the right thing- FormsAuthentication after SSO? And if not, why not and then how do I make my application aware of SSO authenticated user?
It's entirely reasonable to use FormsAuthentication cookies to track the logged in user in your application after they have been authenticated using a Single-Sign-On provider. You don't show it but I'm hoping that you are also getting some ticket that you can use to verify the signed in user out-of-band with the SSO provider and not simply trusting the username header.
What you may be seeing, however, is that the user is not signed out from the SSO provider when you sign them out of your application. Because of that, as long as they have a valid cookie for the SSO provider, they will remain signed in, i.e., the user will get automatically bounced back to your application from the SSO provider without any required authentication.
That's unfortunate, but normal.
If you truly want the user to be signed out, you'll need to make use of the centralized logout functionality. I haven't worked with OAM, but it appears that it does support this: http://docs.oracle.com/cd/E21764_01/doc.1111/e15478/logout.htm
I had to explicitly kill the session inside Session_Start if requested URL is logout URL. And then with next request (like from logout to login page again), it generates a new session and runs smoothly.
protected void Session_Start()
{
if (!Request.IsAuthenticated && !IsSignoutURL)
AcceptSessionRequest(); //process local authentication
else if (IsSignoutURL)
RejectSessionRequest(); //kill the sessions
}
For background on how SSO passes authenticated user's identity to my application, read my comment to tvanfosson's post.
The post remains opened for a better idea.

Authentication with REST on social media website

If I am designing a social media website along the vein of Facebook/Twitter where users will be able to browse other peoples profiles, create public posts that appear on other users activity streams etc, and I want to design this using RESTful WCF services on the server end, with ASP MVC web on the front end, how is authentication managed? As there is no session state, every request the user makes will effectively need to be authenticated to confirm who is logged in and making each request. Eg "Search profiles", "View profile", "Update your own profile", "Upload new photo to your profile", "Post public message", "Reply to public message" are all actions the user will need to be able to do.
I assume something must need to be managed in the clients browser if the server holds no state, but how do you protect against spoofing, multiple user computers etc?
secondly, how is session lifetime managed with REST in this instance, ie if you want a user to be forced to reauthenticate out after 10 minutes of no activity, how would that be achieved?
The best way to do this is using OAuth.
https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization
http://msdn.microsoft.com/en-us/library/dn277356.aspx
Basically once a login call is made you will have an authentication token returned that is used for all subsequent requests. All API calls will call to an authentication API to ensure the token is valid. You can expire this token at the authentication api after a set time if required.
To protect against spoofing, all calls should be made over https.
An advantage of implementing OAuth is then you can move the authentication to another provider, say google or facebook, so you do not even have to store user credentials on your site at all.

Categories

Resources