in ASP.NET Web API, How to de-authorize a user immediately after account lock-out or delete? - security

I'm building a new Web API application using OWIN cookie authentication (ASP.NET Identity 2.2) for security.
I'm new to the whole cookies thing, but I've got a head-scratching problem: How is a logged-in user immediately blocked from using the API if their account has been deactivated (either deleted or locked-out)?
This arises after a startling discovery that if I have a user logged in on a client app, and I delete their user account via a different app, they are still able to access the API (i.e. the [Authorize] filter still succeeds because their cookie is still valid).
Somebody please correct me if I'm wrong, but AFAIK, cookies are not stored on the server, so there is no way to "invalidate" the cookie.
Yes, if the user logs out, they won't be able to log back in again. Also, I understand that setting an expiry on every cookie upon successful login will mitigate the problem.
But what about the following scenario: a system administrator (let's call him JoeAdmin) gets fired or otherwise becomes untrusted and some other administrator locks out his account. If JoeAdmin happened to be logged in when he got fired and became disgruntled, he still has access to the system and can do some real damage.
In this scenario, how could JoeAdmin be blocked immediately?

JoeAdmin happened to be logged in when he got fired and became disgruntled
Also JoeAdmin could have saved the cookie value offline, awaiting for his account to be revoked, and then later restores the cookie value to his browser.
OWIN cookie authentication is not ideal if you ever need to immediately invalidate logins.
This is because all the state information about the user is stored client-side, authenticated with a secret only on the server-side.
That said, you could do something with Oauth2 refresh tokens like here. e.g. have an access token that expires after say a minute, which when expired the application has to use a refresh token in order to gain an access token for another minute.
This way, any revoked accounts are only exposed for a short time. However, you may need to deal with the complexity of out-of-sync clocks on client and server.
Long story short, if you need to secure your system in this way, traditional server-side tokens would be the way to go. They are more secure in this regard.
The risks with using OWIN cookies are very similar to those of using JWT's for authentication. See this comment and the associated question and answer.

Related

Usage of JWT after logout

I have a query, is it possible to use current JWT after the user is logged out?
Scenario: I have a set of private APIs that needs authorization token to access the endpoints. Here I have a web application where I need to log in and get the JWT. I keep the token aside and from the active session I press the logout button and my session is needed to expiry even though I am able to use the JWT to access the endpoints, how will this happening is this the right approach or can I raise this as a bug?
How this is happening?
The session details might be stored in JWT itself and there is no server side state for the same. Every time you are sending the JWT, they are trying to decrypt it, then validating the claims present in it and providing the required access. Since, the JWT itself contains its expiry information, they are unable to invalidate it. It will be expired after specified time decided at the time of token creation. They might be just clearing the cookie at the time of logout.
Is this the right approach?
Depends. It's tradeoff between speed and security. In order to revoke the token access, there should be a server state maintaining the set of access/revoked tokens. If the application is not storing any confidential/sensitive information, its a design call for them to opt for a server state. If the site is on https and free from XSS, the only way to get the token somehow is by gaining physical access to the device. If the expiry time of access token is less than 20 min, the risk is minimal. But it mostly depends on the nature of application. For example, this is not a right approach for a banking application.
Can I raise a bug?
You should to confirm the hypothesis. There can be a possibility that they actually have an infrastructure to revoke the access tokens but its faulty as of now.

Should I reuse OAuth 2.0 access tokens?

I am building an Authorization Server in terms of OAuth 2.0.
There is also a 3rd party web application (Client) which is using my Authorization Server. It's a regular web application, and the user may have several active sessions established with this application (for example, office and home machine, or just several web browsers on the same machine).
My Authorization Server issues an access token #1 (with or without the refresh token, that's not so important here) for Client once. When the user starts a new session with the Client, should the Authorization Server give the Client app the same access token #1 for that new session or should it issue a new #2 token?
My thougts:
From security point of view the new token might sound better, but then if the user wants to manage his authorizations, he will see a separate entry for each Client session, which might be messy.
For example, GitHub returns the same token for previously authorized clients, and on the "applications" page in my GitHub account I see only one entry per application, no matter how many sessions I've started, which is convenient.
However, this approach means that I have to store access tokens in Authorization or Resource server in the reversible way (plain-text or encrypted with some known key) instead of using irreversible hashing (like you usually do with passwords, storing salt and password hash from bcrypt, pbkdf2 or something similar).
Please be advised that I am not a security expert and this explanation
is my general idea of oauth. Reason why I mentioned this in the
beginning is because I see you are CREATING YOUR OWN AUTH SERVER based
on oauth 2.0 protocol, which means down the road some people might be
using your server for authentication, and thus I don't want you to
have the wrong concept.
The session-oauth mismatch
I want to clear this first that don't mix sessions and oauth. These are two separate things usually found working together IMHO.
Oauth protocol simply gives the apps/users with an access token via which the app/user can query your server for data associated with the token.
Session on the other hand depends on the application itself. Once some app received the token, they make a session out of it. When user logs in or logs out, the session is destroyed, not the oauth.
So what is the fate of oauth token?
Well from a server standpoint, each of your token should expire after a certain time period. That is it. Server does not know anything else. It gives you the token, then expires it after 'n' seconds.
However, the app may decide that it wants to revoke the access token. Maybe their website was hacked, or maybe they are done with all api calls. Then they can send a special request to your server telling you to force-expire the token.
So what should I do about user opening multiple sessions?
ABSOLUTELY NOTHING. As an oauth service provider, you are not concerned with sessions at all. All you know is that if the app asks you for a token, you give them one.
However, I will answer you question about sessions as well. Should you spawn different sessions for the same user? I would say yes. If you have same session, then if you log out from one machine, and refresh the page in second machine, since the session has expired, your other browser/machines will also log out naturally.
So how does github manages to not show extra entries?
Well I do not work for them so I don't know. But I guess that they will check each session, and if two or more sessions are associate with the same user, they know the user must be using many devices. Then when one of your devices sends some request to github, they can guess from the IP address your location, and if many of your machines are making requests from same place, you got to be using multiple machines. If not, then maybe some attacker is using your account as well.
This is how AFAIK banks predict malicious users - well not the only way, they sometimes also predict the pattern you are using to access bank records, and if that pattern is different, there are good chances that your account was compromised.
So now you may ask me, are you really sure that I should create as many tokens as the app demands me?
This is the part where I am not so sure. From what I have seen, oauth has two things. Google these two terms for more info:
Refresh Token: This token is not your access token. This token never expires, and once your access token is expired, you can use this token to get a new access token. This token is also to be kept secret.
Offline access type: Many oauth providers such as google and facebook also support this mode. This mode basically allows you to extend the expiry time of your access token. E.g. instead of normal expiry time of access token (e.g. 1 hour), for offline tokens you might have the expiry time of 1 year or so.
Answer to the question "Should I reuse OAuth 2.0 access tokens?"
Yes, the token is supposed to be used as many times as you need within the given expiry time (google sets it to 1 hour).
After it has expired, use the refresh token to get another access token and use it as many times as you need. Keep repeating the process.
If your users won't be online for you to start the oauth process, and you don't have the refresh token, then the app needs to have "offline" tokens.
Should I store my auth tokens?
You can if your app demands it, but it is nowhere recommended because of the potential to be leaked. Tokens are supposed to extract data within the given time limit and reissue the token when needed again. However, you surely can store them if you want.
"Offline" tokens, on the other hand, are expected to be stored. You can encrypt them if you like, but if the scopes are not too broad, I wouldn't bother at all.

Simultaneous login on different machines using oauth provider

As I asked described here:
I am building a service where I have code borrowed from the SocialBootstrapApi. I am specfically using the Linkedin oauth2 provider though.
I have no complaints for a single user - the code works nicely, but if the same user logs in simultaneously from two differen machines (using the same linkedin account) the original logins access token is invalidated. While the user stays logged in (because session cookies are already in place) if the user performs an action that uses the expired access token to perform a task that requires a linkedin api call, the call fails with an invalid access token error. Obviously I understand the reason behinds this, but I am not sure how to rectify it. In this mobile first world, we have so many devices and one device can't logoff a user from another device.
So, should I re-get the access token from the UserAuthDetails table everytime before I perform an api call just in case it has been invalidated? Or, shouldn't this be updated in the cache and next time the access token is accessed, the refreshed one is served because the cache has been updated?
Thanks
The easiest option (and my preferred solution) is to just fetch the access tokens from the IAuthRepository before making the API call. IAuthRepository.GetUserAuthDetails() will return the UserAuthDetails that contains the access tokens.
This can be slightly optimized by first attempting to use the access tokens on the session before hitting the UserAuth backend datastore, although as it's likely the cost of the required simple db call to a internal datastore is going to be a lot less than the call to a remote service (i.e. LinkedIn API's) - the optimization may not be worth it. But if you're going with this approach I'd update the Users Session with the fresh access tokens so next time the fresh tokens from the cache can be used.
Each User Session references a different Session in the Cache
Users authenticating from different browsers, pc's, devices, etc are each given their own session which is just the AuthUserSession POCO's stored in the registered ICacheClient referenced by ServiceStack's Session Cookies, i.e. they don't share the same Cache so changes to one of the users session doesn't affect any other Users Sessions.

Servicestack authentication process on each request

I have been through much of the documentation and examples provided, but Im looking for some inputs for my setup from other users.
I have a some clients (website, iOs/Android apps). These only serves as a shelves and its content will be requested through servicestack, which makes servicestack a central point of my setup.
The client will login through servicestack and get a sessionid.
My question here is, how should i setup servicestack to make sure that the user is validated on each request?
I was thinking after login, i save the user in the cache and make sure this expires after some time (unless persisted). Then on each request based on the session id, i check the cache to see if the user exists. If the user exists, the request i authenticated, and if not the user have to login again.
Am i on the right track here, or is there an easier way in servicestack, to support this?
I was thinking after login, i save the user in the cache and make sure this expires after some time (unless persisted).
It sounds like you can just use the Authentication/Authorization plugin. Once a user is authenticated (using any of the 'Providers') the user's session is stored in the cache using the key 'urn:iauthsession:[sessionId]' and contains a bool property isAuthenticated. For any Service the requires Authentication you can use the Authenticate attribute.

How to forcibly ask authentication for a web resource for every access?

I have some webserver resources protected with Form based Authentication. The requirement is to have some highly secure resources access result in forced authentication of the user even if he/she is authenticated earlier and have a valid cookie (authentication).
The authentication in a session is maintained by a particular cookie. The first idea to solve this problem is to pass that cookie with "expires" value with back date. But for the form login it is not working, I am getting only login page everytime after providing correct credentials. Cookie with expire value with back date is encountered, cookie is deleted by browser. So this cycle of login is encountered.
Please advise me on what to do.
At this point authentication isn't enough. You're going to have to implement multiple levels of authorization, with some levels not having persistent tokens. There's a number of resources on the Internet that explain token-based auth.
Basic authentication (not to be confused with the HTTP scheme of the same name) uses only a single token to determine whether the user is logged in or not. Just split the application into multiple authz token realms and handle it from there.

Resources