Identity Server 4 Cookie Auth vs Silent renew - reactjs

tldr: question: What is proffered way of authentication cookie or silent renew and why ?
I have a react app with .net core backend and identity server 4 as authentication.
Basically I have two apps
identity server (ef core, asp identity, own database)
web app(react + .net core backend, own database)
And now I need to make authentication. I used cookie auth with long cookie expiration (180 days), so user doesn't need to sign in every time. And it is working well. The only problem is that I can't sign out user when I want. I mean if user changes password (because he changes it in identity server not web app) I should sign out him from web app. But I can't since he has still valid cookie.
And now I'm reading something about silent renew method. I guess that silent renew would solve this problem. But doesn't it overload the server ?
Or what is the correct way of doing authentication in react app and why ?
thank you very much

For AspNet identity, you will want to look at the SecurityStamp. This is a column in the user table and stored in the encrypted cookie, and is validated against the server at regular intervals. It changes when a user updates their password, and you can also trigger the change manually as well (for example, having a “sign out everywhere” link that will effectively invalidate all existing cookies.
Here is a great explanation of what is is and how to overrride the validation interval if needed: What is ASP.NET Identity's IUserSecurityStampStore<TUser> interface?
For initial testing you will probably want to set this interval to a very low time to actually see the change taking effect.

Related

How to communicate securely to an Database with electron?

I am creating an electron application that connects to an Database and do POST and GET requests to retrieve and insert data into it, the problem is that in the code i have defined my database uri ( im using mongodb)
const uri = "mongodb+srv://<myusesrname>:<mypassword>#cluster0.wqbiu.mongodb.net/query?retryWrites=true&w=majority"
like in the example above, but if i pack my electron app the connection to the database as well as the credentials its visible if someone unpacks the app.asar file and look in the server.js file how i can solve this problem? i dont want any security breaches neither for me or the people that will be using my application, thanks in advance for any answer :)
An application that requires a secure connection to something cannot afford to have any username's or password's hardcoded into its code.
Instead, a procedure of authentication and authorisation is utilised.
Authentication is used to verify the user. IE: They are who they say they are, often achieved via the use of some type of login form.
Authorisation is used to verify the logged-in user is allowed to access the requested resource. EG: Is this user allowed to retrieve a list of all users email addresses from the database.
As a rough guide, a user will login with their username and password. You could use OpenID as well here if you wanted. Once the user is 'logged-in' you could set a cookie or session and save the session id in the DB against the user. Of course, all of this is done over HTTPS.
There are various ways to control the validity of the session such as but not limited to refreshing the expiration date / time every time the user hits the server, auto timeout if the user has not interacted with the server for more than X minutes, etc.
In your app, the user could try and interact with the database at any time, but if the user is not logged in, the server could return the appropriate response and prompt the user to login. Some form of API here is really the way to go.
If the user is logged in then then next step is to authorise the users request, ensuring they are allowed to perform what they are asking before sending a response back. If they are not authorised to access the resource (EG: Edit another user’s post) then an appropriate response is returned indicating so.
As you can see, securing your app will take some work but the result of not doing so could be devastating to you and your users.

Allow single session per user IdentityServer4

With IdentityServer4 I need to allow a single user session per time. If the user authenticates with device A and then with B, session and access token must be invalidated for A and, even better, client A could receive a notification that user has logged out in a second step.The main thing is making the server force invalidate session and token. There are similar questions, one of them redirects us to the following link:
https://github.com/IdentityServer/IdentityServer4/issues/736
where it is explained to use backchannel logout and in the login method of the identity server to obtain the previous IdentityServer sessionID that should have been persisted somewhere. Then I should send logout tokens to all clients.
Another solution is given here
How to Logout user from a particular session Identity Server 4, .Net Core?
telling us to use an ITicketStore implementation to be able to invalidate the session.
The configuration used is IdentityServer4 with authorizaton code flow with PKCE. Which approach is best for my case? Is there another approach where I could simply delete the access token in the id server database?
I think in your case probably a combination of both. In our real-world implementation we combine server-side storage of sessions via ITicketStore (stored in a custom database with sessions linked to user accounts and also storing the list of client IDs for each session) with the ability to trigger back-channel logout of any session at any time (i.e. not just via the default user-triggered mechanism).
In our case we do this to be able to invalidate sessions for other reasons (e.g. password or other security setting changes, a "log me out of everything" feature, impersonation rights being revoked etc) but this approach could form the foundation of a "single session per user" feature should you wish.

Is there a way to end all sessions for a subject ID?

What I'd like to do is end all sessions for a user when a user changes/resets their password (using ASP.NET Core Identity). I'm using the oidc-client-js library inside of a SPA. I've figured out how to end the current session for a user and cause any tabs that're in that same session (say, other tabs in the same browser windows) to recognize the session is over via the check session iFrame, but any other sessions (say in an incognito window) still seem to have the session functioning, even if their refresh tokens/all persisted grants for that subject ID have been revoked.
Is there some way to make that iFrame return to the client that the session is over for all sessions, like maybe have the iFrame page be checking the persisted grants for that session or something? I'm okay if a currently issued access_token continues working (they're short-lived), but just want the refresh tokens to be invalidated and the session to end.
Option 1
There is an OpenID Connect Session draft specification which would do what you want - it allows front end clients to check the current session state via an iframe. This is a draft and may not be implemented by ASP.NET Core Identity though.
https://openid.net/specs/openid-connect-session-1_0.html
Option 2
An alternative mechanism for resolving your problem programatically is by putting a check in your token exchange code. Your access tokens will presumably be relatively short lived, and so the front end has to regularly acquire new access tokens (either via refresh token, or by id token on the implicit flow for instance.
In your token exchange you could check for timestamp when the password was last updated.
If it is more recent than the timestamp when the token was issued, then instead of issuing the fresh access token you could return a 401 and manage a redirect to your authentication endpoint by a mechanism of your choice.
This doesn't instantly log the user out of alternative browser windows, because it depends upon the expiry window of your access tokens. If does have the advantage of working cross browser though, because it doesn't depend upon browser specific session information. It can also check for customers who are blacklisted, or who have changed their email address and other checks which might be relevant to a desire to force re-authentication.
For belt and braces you can use both these techniques.

Identity Server 4 - User Authentication - Confidential App - Multiple Client Secret - One Client_ID

I've a scenario for a Third Party Client App (Mobile App - With Client Secret) to connect to the Identity Server for getting access to a Resource Server. During the user login the Client App display multiple store location for the user to sign in.
The Client App is designed to have a unique secret for each store location and one Client_ID.
When a store is selected by the end user for login - the ID Server gets a request from the client app with the Client_ID and the specific secret matching to the store location.
The Question I've over here is, how to make the Identity Server (3 or 4) to perform the User Login based on the Store Location.
I'm thinking of intercepting the Client_Secret to use it during the User Login to map to the correct store id by having a lookup table in place.
Is this a good approach to get this scenario worked out, or can someone shed some light with any possible suggestions to make this scenario work with the Identity Server.
The Expected flow:
Client App Displays the Store Location's in the Login Screen
User Selects the specific store location
User is directed to the Identity Server Authorization Endpoint and Client Validation is taken place.
Authorization Server Displays - User Login Screen
The Authorization Server authenticates the end User based on the store location. (Need to figure out a way to achieve this)
If you intend the login flow to be completed within mobile app itself and not within browser client, then you will need to use resource owner credentials grant type, in which case, it doesn't really matter if you have one or many secrets per store as it authenticates a single client based on your scenario.
On the other hand, if you intend the login flow to be completed within browser client, then it also doesn't matter if you have many secrets or one because in that case I assume the store selection would be done within the login screen like you mentioned which would part of the auth server.
All in all, nowhere in your flow the store location seem to matter unless there is some kind linkage between user credentials and store id. If that is the case, then this is essentially a multitenancy question for Identity Server 4 for which there are discussions already open with suggestions.
https://github.com/IdentityServer/IdentityServer4/issues/2673
How should you secure a multi-tenant API with Identity Server?

Azure AD | Conflict when logged in with another Azure Account

I have a Asp.net MVC application that uses Azure AD and OpenID Connect OWIN middlewares to handle authentication. Everything works fine except for one thing : if a user is already logged-in on another Microsoft Application lets say a Office 365 account or maybe a live mail account, when trying to login it recives a page saying that it is not allowed to log into my app, which is correct, but some how I need to catch that situation in my code to allow the user to sign in with a different account. Is there a way of doing that? This is by design? I mean : the user have to log in only with a live/azure account at the time ? I couldn't find any documentation about this.
As of today there is typically one user at a time, but we will soon support for you a way to select a specific user instead of automatically signing you in with the most recent one.
One way you can work around this today is by injecting the parameter "prompt=login" in your sign in requests. You can do that in the RedirectToIdentityProvider notifications, similarly to what is showin in http://www.cloudidentity.com/blog/2014/11/17/skipping-the-home-realm-discovery-page-in-azure-ad/ for domain_hint. This will cause the sign in experience to always start with a fresh prompt even if the user is already signed in. The draw back is that you'll never get SSO this way. Hopefully our account switiching feature will become available soon, keep an eye on http://blogs.technet.com/b/ad/ for announcements

Resources