Devise token authentication and session - ruby-on-rails

I am using devise in my rails app. There is an ipad app that connects to the this rails app and authentication is done using token. (devise token_authenticatable).
For sessions, I using the default cookie store. My session_stor.rb looks like this,
Ap::Application.config.session_store :cookie_store
Now say I need to store minor data for the ipad user in session, where is it stored? Say in my controller I am doing,
session['last_search'] = search_key_word
Where is this data stored? I am asking this because on cookie based session store, usually session data is stored in browser. I couldn't find any resource that explains what happens in case of a non browser client that uses token for authenticatication.

I suggest saving the history locally in the iPad's app itself. You can create a table "search_history" that stores the recent 10 keywords. Or you may cache it if you want (also on the client side).

Related

Dropbox OAuth2 API always prompts user for permission when a refresh token is requested

I'm writing an offline application that uses the Dropbox API. When a user comes to the application, I'm using the https://api.dropbox.com/oauth2/token (docs) to get a refresh_token, which I store for later use.
I am calling the same endpoint every time the user logs in (unless I've already got the user's data in a cookie). I'm not sure that this is the best way to go about it: I at least need to get the user's account_id, so that I can look up their refresh_token in the database if I already have it. But every time I call https://api.dropbox.com/oauth2/token, the user is redirected to the Dropbox app authorization interface, as if they've never approved the app before.
So I would either like to know how to stop Dropbox from forcing the user to re-authorize an app every time. Or, if that is just how https://api.dropbox.com/oauth2/token is supposed to work, I'd instead like to be able to get their account_id somehow when they visit my page.
(In case it's relevant, the app is still in development mode at this point.)
The https://api.dropbox.com/oauth2/token endpoint is an OAuth endpoint that the app can call to get an access token/refresh token. Being an API endpoint, it does not itself redirect the user to the Dropbox app authorization page.
The Dropbox app authorization page is at https://www.dropbox.com/oauth2/authorize (documented here), and the app decides if/when to direct the user there to authorize the app.
You generally only need to send the user through the app authorization flow (sending them to https://www.dropbox.com/oauth2/authorize and then calling https://api.dropbox.com/oauth2/token) once per user for an "offline" application. Once you do so, you should store the resulting refresh token for that user. You'll typically store the refresh token for that user tied to their user account in your own app.
Exactly how you manage the user accounts in your own app will depend on how it's built, but, as it sounds like this is a web app, typically you would use the user's browser cookies to identify the user when they return to your page so that you can look them up in your database and retrieve their details, such as their corresponding refresh token. (Or, if they're not already signed in to your web app, you would have them do so first.)
Greg's answer is very helpful, and very politely addresses my misunderstanding of the auth flow. (I was revisiting old code I'd written years previously—obviously I should have documented it better than I had!)
In the end I believe that Dropbox was forcing me to reauthorize because my application was in development mode, and had a small user base. When I used the identical code in an app set to production mode, it stopped forcing me to reauthorize. So the “problem” is really a Dropbox security feature, and the solution was just to use production mode.

How to detect if a user has another user's session in Rails?

We are experiencing a bizarre, very rarely occurring bug where a user will be logged into another user's account.
We are on Rails 4.2. We use authlogic for authentication and dalli as our memcached client. Use memcache as the session store.
I haven't been able to figure out what is causing the issue, but the worst part is that even if I did have a hypothesis I wouldn't know how to confirm if it worked or not.
I would like to find some way to log if a user has been given the wrong session, both to help debug the problem and to determine if a potential fix works.
I'm just not sure if it's possible. If the user's cookie has the wrong session ID, how can I possibly figure that out?
Try going back to signed, encrypted cookie session store. Use memcached for frequently accessed items, like the user record. Load the user model from memcached instead of the database.
If you really want to log session hijacking, then log the user's IP address. If the IP address suddenly changes, as if they were logged in one place, then all of a sudden are making requests from another place, then maybe another user hijacked their session cookie?
http://guides.rubyonrails.org/v5.0/security.html#session-hijacking
Be aware that using TOR would show that pattern, as it generates a new route every ten minutes, but doesn't mean the session was stolen or mixed up.
If you are not using signed or encrypted cookies, then it allows Javascript or malicious ads to steal the session id, and send it back to the attacker's server.
It could also be your session ids are not secure or random enough. Maybe a new session id overwrites another session id in memcached? Since you are using a different session store, maybe you customized the session identifier?

iOS app with a Rails backend

I've built a Rails app with a simple API. I'm using Devise for authentication. I'm trying to work out how to log a user into the rails app from my iOS app so they can retrieve and post data. I've been searching all day for the best way to do this but most info is outdated (using Devise's deprecated token_authenticable solution.
I've got my rails app. I've got my iOS app. I've written my API. How do I connect the pieces together?
Thanks
Details:
My app allows users to fill in a form and have that data sent to the server. In another section of the app the user can view the data they have previously submitted. When the app first launches the user should login to their account so that the data they post is associated with them and they can only view data they have previously posted. It's quite a simple app. How do I log them in so that I can tell the API to only return their data.
Set your server up to use SSL, then the communication to the server are secure. Post the userID and password to the server in an SSL. You can pass that information on each access to the server.
If you want to pass the UserID/Password only once then you can setup a session with a cookie but you will need server support for the session and timeouts.
What you need to define is how secure you want the authentication to be. That is who are you defending against? A friend, an enemy, a government? Define the value (in $) of a security breach. Defend to this level.

Single logon with different applications approach ruby on rails

What would be the best approach in the following situation:
Main application that handles authentication of users (preferably Devise).
Several different applications that can access user database for single logon.
Synchronisation of user data (Preferences, profile data)
Scenario example:
User registers for application A
User can access application B with same credentials (But has to explicitly confirm a new agreement before it can also use application B)
First of all, all the apps need to have access to the users database, so the users only need to register once. You can have an attribute or relation to check if the user has confirmed agreements for different apps.
For making all the apps accesible with only one login, you can use the same session store for all the apps.
For example you can use memcached for the session store and use the same session store key in all the apps. If the user makes login in one app, when he goes to another app without closing the session, this app can check that the session has been created and the user can enter in the new app whithout login in.
With this solution you need to be careful with the session data, so the data of one app doesn't overlap the data of other app.

keep "session only" cookies, iOS

I'm creating an app that connects to a website, and I don't want the user to need to enter their user credentials every time the app loads. The website returns a session cookie (no expiry date set). Is there any problem with me holding on to that cookie indefinitely? If I just reload it when the app starts, it seems to work.
Thanks!
Each application has its own cookie store. So if there is no expiration on the cookie, and you don't delete it, and the app isn't deleted, then there's no problem with using it for as long as you like.
EDIT Here are some links for more opinions and insight:
Persisting Cookies In An iOS Application?"
iPhone: NSHTTPCookie is not saved across app restarts
My opinion on the matter is that the mobile environment is fundamentally different from the desktop environment. "Quitting" a mobile application is in no way similar to quitting a desktop application. Quitting a mobile application is similar to switching focus on a desktop. You would not expect to re-authenticate every time you pressed Cmd-Tab.
Limiting the life of session tokens is a valuable security precaution, but is correctly implemented on the server side, not the client side. If the server is designed to allow a session to persist indefinitely (because the desktop app is never quit), then there is no reason to not continue the session on a mobile platform in a similar way.
Note that there are other solutions, such as storing the user credentials in keychain so that you can reuse them. This is appropriate in many cases, but it actually is a lower-security solution than persisting the session token indefinitely. If you're going to hold onto an authentication credential forever, it's better that it be a single-purpose token (i.e. a session cookie) rather than a multi-use username and password.
There is no problem in you allowing this cookie to be set, each application has a cookie store from which you can if you need to check the cookies, however I assume that since this is only a session cookie, you will only need to allow it's existence and let the user leverage the web service until such time the user logs out.
I have done this with some of my apps also.
Good luck.

Resources