Let's consider a special scenario that an admin (Admin A) logs in and start doing some admin stuff on the system. Suddenly another admin (SuperAdmin) wants to downgrade Admin A to a normal user for some reason. However, even-though now Admin A is just a normal user, his token is still an Admin token. So, he can still do admin stuff until the token automatically expires in one hour.
So, in a scenario like this what's the way to expire that token manually ? Does the system should use a DB query to check user level for each admin route ? Or is there any other way to achieve this ?
Is there any way to config core gateway to check validation of token ?
I think if I check validation of token for each request in coregateway we have a lot of overhead and defeats the entire purpose of using JWTs in my opinion.
I am going with JWTs are not designed for sessions or stateful representations of data.
Therefore either accept this or do some messy hack with an "allow/white list".
Option 2.
Use sessions.
Related
One user can log in through multiple systems with various IP addresses, so is there any way to deactivate one of his sessions? (or all other sessions except the current logged in one) if yes, how?
The thing I want to do is exactly like Telegram which you are able to close any of your activated sessions.
The question is not new here, it appears a couple times a month in different interpretations, and the answer is still: there is no such feature out of the box, but there are a couple approaches:
The first one is to use Reference Token (instead of jwt by default), then look through the persisted grants database and logout all the sessions for the target userId.
The other approach is to implement your custom session store based on a database (instead of the cookie based by default). Then you again have access to all the clients logged in with the given user id. Here is my old (but still valid) example of a hybrid (cookie + IDistributedCache such as REDIS) extension for the DefaultUserSession. Here you have to be careful with access token lifetime (make it reasonably short), as a jwt once issued can not be invalidated before its normal expiration.
Context
We use Identity Server for identity and access control in our solution. Our scope names have the form of URLs so they are 40-60 characters long.
Some time ago we received a request to increase the max length for scopes in the request. The default value is set to 300 in InputLengthRestrictions class and it can be changed very easily. However, after some discussions, it turned out that for now it may be enough to increase the max value to 500 or 1000 but in the future, an even bigger limit may be needed in order to be able to request 10, 20 or more scopes.
Here comes the question. Is it a good practice to request an access token with such a large number of scopes? What are the pros and cons?
My thoughts
From my perspective, the main benefit of having one "super" access token has one main advantage i.e. it is convenient because it allows you to call all APIs.
On the other hand, I see some drawbacks and/or code smells:
The fact that a large number of scopes must be requested may mean
that scopes are too granular.
The fact that a large number of scopes must be requested may also suggest that scopes are used more as permissions. It is especially a problem in the case of long-lived tokens as they cannot be revoked easily.
Requesting a large number of scopes may suggest that you request
more than you actually need. However, it is recommended to "choose the most restrictive scopes possible".
Having a super access tokens expose a higher security risk if such a token is intercepted.
In implicit flow, a token is passed in URL so the large super token can exceed the maximum length of the URL.
Super tokens might be too big to store them in cookies (it is a
different topic if tokens should be stored in cookies).
Super tokens can be quite large so the network performance can be affected.
What do you think? Do you see any other pros/cons of super tokens? I'm not sure but maybe large super tokens can affect Identiy Server performance.
I don't have pros or cons for you, but perhaps this answer can help you.
Looking at IdentityServer you'll see three parts, the resource, the client and the user. IdentityServer has two main responsibilities, authorize the client and authenticate the user. User authorization is actually not the responsibility of IdentityServer. That's why they created PolicyServer.
Consider the following resource:
resource = CalendarApi
scope = Calendar.Read
scope = Calendar.Write
scope = Calendar.Event.Create
The resource is just a logical name. It can consist of one or seperate api's (as in projects), where an api can implement a single or multiple scopes. In the api a scope is an implementation of certain functionality.
Only a client can request a scope, because the client knows how to use the functionality.
Suppose I have two clients: Mvc1 and Mvc2. Mvc1 has a calender view and an admin page, while Mvc2 only shows the calendar.
My configuration:
Mvc1: scope = Calendar.Read Calendar.Write Calendar.Event.Create
Mvc2: scope = Calendar.Read
It has no use for Mvc2 to request all scopes, because it doesn't use the other functionality. It wouldn't make sense to request all scopes. And in case Mvc2 is a third party app, you shouldn't, because they could use it even when this was not the purpose.
Best practice here would be that a client only requests scopes that are allowed (as configured in IdentityServer) and may be implemented by the client.
So far the user was not involved, because there is no relation between scopes and users. However, the client needs the user (as resource owner) to actually access the resource.
It then comes to user authorization to determine whether the user can create events on the calendar. This 'permission' is not the scope.
The scope Calendar.Event.Create doesn't allow the user to create an event. It only allows the client to connect to the resource.
When combining the clients and users, then there is only one situation where a user can create an event: when a user with create permission uses the admin page in Mvc1.
Mvc2 can't access the resource, not even when the user has create permission.
Now getting to your question:
Is it a good practice to request an access token with such a large
number of scopes?
The access token should only contain the scopes that are needed, as described above. Only necessary scopes should be requested by the client.
Agree. The number of scopes should not be too detailed. Don't treat scopes as permissions, e.g. create, edit, read. Though I did as example, a better scope would be Calendar, where the user permissions define what the user is allowed to do (CRUD permissions).
Agree, should be investigated.
I would say yes, as argumented above.
It is still the user that has to be authorized. But you should limit the possibility for clients to use functionality that was not meant for that client.
/ 6. / 7. Hitting limits is a good indication that the architecture may need some redesign. In general you should not expose more than necessary and you should avoid hitting limits.
I suspect the problem is that scopes are used as permissions. Remove the 'CRUD' from the scopes and redesign user authorization. Don't set permissions in claims.
In my design there is no need for a super token, nor will I ever hit a limit. There are only few scopes, the access token only contains the sub claim and policy server tells me what the user is allowed to do.
I hope this helps you in any way. Please let me know if something is not clear.
You can implement Service Account flow for same. Using it you can get token of respective client with all allowed scopes to client.
By this way your token does not have included all scope but has scope allowed to client.
I don't have sample code right now but you can check how service account can be implemented
I am making a mobile app for a site with users, so in the app, users need to be able to sign in. To do this, I am creating a remember token to authenticate users on sign in. At first I was thinking about saving each token to the database and destroying it when the user signs out. When the user signs in, they would have the same token until they sign out. Then I saw somethings saying redis was the best way to store the tokens. My question is that if the only time a new token is created is when a user signs in and the only time it is destroyed is when a user signs out, is redis needed or is just saving it to the database ok performance wise
Redis will enable fast access to token data as it keeps the key value pair in memory.
Also, in case you need to expire token after a particular span of time Redis will allow you to set expiration time along with key .Thus you need not perform any explicit computation to determine its expiry time in order to delete it.
A use case of sessions using Redis is Magento.
That commerce framework relies heavily on caching, storing everything in Mysql until v.1.7
From that on, they embedded a model to store sessions in Redis.
I've used Redis with success. phpredis is the best client for php, since it's a c extension.
I would fiddle in heroku's for verifying performance.
(Now I CAN, because of hack support there hehe =)).
My two cents.
We're developing an application that hosts each user account under their own subdomain. Separate users may access their application through a domain such as usera.myapp.com and userb.myapp.com.
To enhance security between application accounts, the session cookies are scoped to the subdomain of the account (ex. usera.myapp.com instead of .myapp.com). This seems to pose a problem with Google's OAuth2 implementation. Since Google OAuth will only allow you redirect back to the set redirect_uri in their settings, we cannot redirect the user back to their custom subdomain after authorizing our app. We're forced to redirect them back a single generic subdomain such as oauth.myapp.com.
Once they're redirected, we no longer have access to the session (sessions are scoped to a different subdomain now). Since we no longer have access to the session, we cannot check the CSRF token we set to the "state" parameter when requesting the OAuth token. Most other implementations of OAuth2 will allow us to redirect back to a wildcard subdomain, so this isn't an issue.
Now we are left with 2 possible solutions to fix this issue...
Skip checking the CSRF token in the "state" parameter, which opens us up to clikjacking attacks. Or...
Open up our session cookies to use the entire domain, instead of scoping them to the the account subdomain. This opens it's own can of worms and security issues, but it is something that we can deal with.
Option #2 seems like the lesser of the two evils, but I'd like some input before we proceed with doing that.
Thoughts?
Hm, might it be possible to construct the state value by hashing up a bunch of pieces of state so you don't have to retrieve the desired value from a cookie? E.g. hash up the subdomain, the time of day, and some internal system state from your app. Then you can recompute the value you expect when they show up at oauth.myapp.com, no need to fetch it from the session. Should be effective against clickjacking I’d think.
I'm building a simple api with Rails API, and want to make sure I'm on the right track here. I'm using devise to handle logins, and decided to go with Devise's token_authenticatable option, which generates an API key that you need to send with each request.
I'm pairing the API with a backbone/marionette front end and am generally wondering how I should handle sessions. My first thought was to just store the api key in local storage or a cookie, and retrieve it on page load, but something about storing the api key that way bothered me from a security standpoint. Wouldn't be be easy to grab the api key either by looking in local storage/the cookie or sniffing any request that goes through, and use it to impersonate that user indefinitely? I currently am resetting the api key each login, but even that seems frequent - any time you log in on any device, that means you'd be logged out on every other one, which is kind of a pain. If I could drop this reset I feel like it would improve from a usability standpoint.
I may be totally wrong here (and hope I am), can anyone explain whether authenticating this way is reliably secure, and if not what a good alternative would be? Overall, I'm looking for a way I can securely keep users 'signed in' to API access without frequently forcing re-auth.
token_authenticatable is vulnerable to timing attacks, which are very well explained in this blog post. These attacks were the reason token_authenticatable was removed from Devise 3.1. See the plataformatec blog post for more info.
To have the most secure token authentication mechanism, the token:
Must be sent via HTTPS.
Must be random, of cryptographic strength.
Must be securely compared.
Must not be stored directly in the database. Only a hash of the token can be stored there. (Remember, token = password. We don't store passwords in plain text in the db, right?)
Should expire according to some logic.
If you forego some of these points in favour of usability you'll end up with a mechanism that is not as secure as it could be. It's as simple as that. You should be safe enough if you satisfy the first three requirements and restrict access to your database though.
Expanding and explaining my answer:
Use HTTPS. This is definitely the most important point because it deals with sniffers.
If you don't use HTTPS, then a lot can go wrong. For example:
To securely transmit the user's credentials (username/email/password), you would have to use digest authentication but that just doesn't cut it these days since salted hashes can be brute forced.
In Rails 3, cookies are only shrouded by Base64 encoding, so they can be fairly easily revealed. See Decoding Rails Session Cookies for more info.
Since Rails 4 though, the cookie store is encrypted so data is both digitally verified and unreadable to an attacker. Cookies should be secure as long as your secret_key_base is not leaked.
Generate your token with:
SecureRandom.hex only if you are on Ruby 2.5+.
The gem sysrandom if you are on an older Ruby.
For an explanation on why this is necessary, I suggest reading the sysrandom's README and the blog post How to Generate Secure Random Numbers in Various Programming Languages.
Find the user record using the user's ID, email or some other attribute. Then, compare that user's token with the request's token with Devise.secure_compare(user.auth_token, params[:auth_token].
If you are on Rails 4.2.1+ you can also use ActiveSupport::SecurityUtils.secure_compare.
Do not find the user record with a Rails finder like User.find_by(auth_token: params[:auth_token]). This is vulnerable to timing attacks!
If you are going to have several applications/sessions at the same time per user, then you have two options:
Store the unencrypted token in the database so it can be shared among devices. This is a bad practice, but I guess you can do it in the name of UX (and if you trust your employees with DB access).
Store as many encrypted tokens per user as you want to allow current sessions. So if you want to allow 2 sessions on 2 different devices, keep 2 distinct token hashes in the database. This option is a little less straightforward to implement but it's definitely safer. It also has the upside of allowing you to provide your users the option to end current active sessions in specific devices by revoking their tokens (just like GitHub and Facebook do).
There should be some kind of mechanism that causes the token to expire. When implementing this mechanism take into account the trade-off between UX and security.
Google expires a token if it has not been used for six months.
Facebook expires a token if it has not been used for two months:
Native mobile apps using Facebook's SDKs will get long-lived access
tokens, good for about 60 days. These tokens will be refreshed once
per day when the person using your app makes a request to Facebook's
servers. If no requests are made, the token will expire after about 60
days and the person will have to go through the login flow again to
get a new token.
Upgrade to Rails 4 to use its encrypted cookie store. If you can't, then encrypt the cookie store yourself, like suggested here. There would absolutely be no problem in storing an authentication token in an encrypted cookie store.
You should also have a contingency plan, for example, a rake task to reset a subset of tokens or every single token in the database.
To get you started, you could check out this gist (by one of the authors of Devise) on how to implement token authentication with Devise. Finally, the Railscast on securing an API should be helpful.
You can try to use rails4 with your API, it's providing more security and use devise 3.1.0rc
In Rails 4.0, several features have been extracted into gems.
ActiveRecord::SessionStore
Action Caching
Page Caching
Russian Doll-caching through key-based expiration with automatic dependency management of nested templates.
http://blog.envylabs.com/post/41711428227/rails-4-security-for-session-cookies
Devise 3.1.0.rc runs on both Rails 3.2 and Rails 4.0.
http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/
Devise is deprecation of TokenAuthenticatable in 3.1.0rc but you can build your own TokenAuthenticatable method for security issue. It's more reliable and secure.
For token, session store you can go through http://ruby.railstutorial.org/chapters/sign-in-sign-out and http://blog.bigbinary.com/2013/03/19/cookies-on-rails.html for more understable.
At last you should go through these kind of encryption and decryption "Unable to decrypt stored encrypted data" to get the more security.