I'm trying to set up some simple security rules for my Firebase (essentially, any authorized user can read/write), which I'm using with a Rails application that uses Devise for user-authentication. However, I'm having trouble understanding how the process of generating tokens work.
I found the Ruby gem here:
https://github.com/firebase/firebase-token-generator-ruby
However, I'm not sure where I'm supposed to put this snippet of Ruby code:
require "firebase_token_generator"
arbitraryAuthPayload = {:auth_data => "foo", :other_auth_data => "bar"}
generator = Firebase::FirebaseTokenGenerator.new("<YOUR_FIREBASE_SECRET>")
token = generator.create_token(arbitraryAuthPayload)
Do I just put it in an initializer along with a variable for user_id?
Also, I saw that tokens expire after 24 hours. Does that mean this token generator will automatically generate a new token for each client with an expired token?
Thanks
If the clients need to read/write from Firebase directly they will need to have that token to auth to Firebase before they can, so it would probably be a good idea to generate a token wherever you're handling user authentication / initialization.
As you mentioned, the default session length is 24 hours, so after that they will need a new token. You can specify a different expiry time using a second options parameter with an :expires key to the create_token method as mentioned in the README to any future date. That way you can set it for say 30 days in the future, or whatever your normal session length is, or you could create an endpoint that returns a valid token and handle the expiration gracefully on the frontend.
If the ruby server is the only thing accessing Firebase, things are a little easier - you could just create a server token once and allow it read/write access to the whole Firebase
Related
I use Spring-Lemon library for my spring boot project. I use a web front-end to my application. My question is, how to know if my auth token is about to expire? Documentation said a Get context operation should be used in this case to get a new token. But I did't find the way to find out when I should use this method to get a new token. Is there way to add the expiration date or the time remained to the responses, so my front-end would know that it should renew the token?
Knowing when it'll expire shouldn't be a problem, because you actually control it:
By default, the expiration will be 10 days after you call
/context (See LemonProperties)
You can change it by setting a
property
You override the property be calling get-context with a
parameter: /context?expirationMillis=123456
My Rails app has log in / log out functions working and returning a valid access_token after logging in.
I'm using this gem
https://github.com/lynndylanhurley/devise_token_auth
But how do I use this access_token in subsequent requests? For example:
abc.com/action?access_token=123
I would imagine in my controller, and in the action method, I should be able to find the user from this access_token but I am not sure if it is possible using Devise.
If I also pass in the :client or :uid along with the :access_token, I can validate this token by doing:
user = User.find_by_uid uid
user.valid_token? access_token, client
Is it possible to look up a user by his/her access_token alone?
Thanks.
According to the Docs:
access-token This serves as the user's password for each request. A hashed version of this value is stored in the database for later comparison. This value should be changed on each request.
And it seems to be a tokenization using BCrypt and changes each time for security.
Further they do not allow you to lookup the user in the DB from the Token alone do to security vulnerabilities. You can choose to store the UID in a creative way or in the session for lookups and write a method in your application_controller.rb that then performs some logic on that data.
This is mentioned here:
uid A unique value that is used to identify the user. This is necessary because searching the DB for users by their access token will make the API susceptible to timing attacks.
I am trying to build a service that authenticates users using an oauth 1 signed request. The request includes an oauth token, signature, nonce, and consumer key. The server has access to the corresponding secrets, but it is unclear how to use the oauth gem to validate the token and retrieve the corresponding user. The token was originally generated using the oauth-rails plugin, but the validation needs to take place on a different server from the original rails application (but has access to the same underlying database).
How can I use the oauth gem to accomplish this?
I have looked through the source for the oauth and oauth-plugin gems, but I can't tell where this validation actually happens. Almost all of the documentation I can find refers to using the oauth gem as a consumer, not a provider.
I finally figured out the answer to this, so I'll put it here in the hopes of helping someone in the future.
Once you've retrieved the AccessToken and ClientApplication objects from the underlying database and checked the nonce and timestamp, verifying the signature is as easy as:
signature = OAuth::Signature.verify(request, {}) do |sigblock|
[token.secret, ca.secret]
end
If the signature checks out, signature will be true. Beware - if you're behind an http proxy such as nginx, the SERVER_PORT environment variable may not be correctly set for https requests and you may have to set it manually. If this (or any other seemingly tiny part of the request) is off, it can cause the signature verification to fail even if the request is valid.
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.
I am looking at using Savon to consume a SOAP API. One of the requirements of this particular API is that an authentication token be supplied in each request to the API. That is, apart from the request that returns the authentication token itself. That call just needs a username and password. The token expires after 20mins of inactivity.
My question is, what is the best practice for storing this token? It's surely not advisable to make two requests every time, one for the token and one for the actual request?
I was considering storing it in a session variable but this would mean generating a new token for each visitor, which I presume is not necessary. However, it would mean I could set a 20 minute expiry on it very easily though.
If I store it in the database, how would I know whether or not it will have expired before making the call to the API, without a lot of extra logic?
Or, should I store it in the database and simply make a background call to the API every few minutes to ensure the token never expires?
Or am I barking up completely the wrong tree?!
Thanks for any advice.