Rails inception - how to handle a login session within a login session - ruby-on-rails

I must build a Rails API, which responds to requests from an iPad app. I have, among other things, a Shop model, a User model and a Product model.
The iPad app works like that - once started, first the shop must log in with an ID and a password. This is done by the shop manager (probably in the morning, at the beginning of the working day or even just once, if they never log out). This happens on multiple iPads. Then, an iPad is given to a customer, who, within the “session” of the shop, logs in as a user. The point of this is, that a user can log in with the same credentials in different shops and depending on this, they can see different products in the iPad app.
So, within a Rails session I need to keep a current_user, but also a current_shop. The question is - how do I implement this?
I was thinking of the following - after the shop manager enters id and password, the API returns some token, which is persisted on the iPad. Then - when the user logs in, this token is sent along with their credentials, so that, at the moment of login I know in which shop the user is and know which products to return in the initial response after login. I also save the shop token in the user’s session.
I would first like to know if my general idea is correct. Also, I would like to know how would you implement it. I was thinking of using Devise for the user and hand-rolled authentication for the shop, but I must figure out how to integrate both.

Devise does allow you to use any model and multiple models in parallel. This allows you to use all the nifty helpers like current_user and authenticate_shop!.
What devise doesn't bring out of the box is an API authentication mechanism. That you can (and have to) implement yourself
Using tokens for each of the shop and user accounts seems straight forward. You can even use the same basic mechanism (maybe via HTTP-Header).
before_filter :authenticate_xxx_via_token
def authenticate_xxx_via_token
xxx_id = params[:xxx_id] || request.headers["X-XXX-ID"]
xxx_token = params[:auth_token] || request.headers["X-XXX-AUTH-TOKEN"]
xxx = xxx_id && Xxx.where(id:xxx_id).first
if xxx && Devise.secure_compare(xxx.authentication_token, xxx_token)
sign_in xxx, store: false
end
end
So do this once for each model and you can then protect your controllers/actions via authenticate_xxx! and use current_xxx.
Finally, don't forget to add SSL to your service or all of this is of little use.

I guess, you're integrating an API driven application, using devise will be of limited use to you. You could do it but I have a feeling it will cause more pain than it is worth.
Use Rails built'in has_secure_password - http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html
The simplest possible flow without session tokens would go like this:
store manager's username and password into the iPad app (you can send an api call to the host to verify it's OK) and the app stores those values in its process memory (not on the disk!)
in subsequent API calls you resend the manager's username and password alongside with the customer's username and password and you verify both in before_action of your base controller
A bit more secure solution would be to use a session token which supports multiple ipads:
store manager enters his username and password into the ipad app and ipad app sends a store authentication call, you verify the credentials and return a SecureRandom.base64 digest and you set Rails.cache shop_owner/#{digest} key to value of shop_id for later retrieval, on the app you are free to put the digest on the disk
in every subsequent request the digest is sent alongside the customer credentials, in the before_action you check the cache for shop_owner/#{digest} and retrieve the store ID from there

Related

where to store user info after login to swift ios app

I'm creating simple user login at the beginning of my app. After user submits correct username and password, my script from server should return some parameters which I should store in some sort of local database, and check for these parameters every time when new view appear/loads.
My questions are:
1) which type of local "database" should I use, which one is secure so no one else from "outside" can access it, because if someone could than he could set my logins by himself (keychains, user defaults etc.)?
2) which parameters should I return from server, which one of them are essentially from security when checking if user is logged in - I'm thinking of username and the token - if user is successfully logged in, than server script should create some type of token which will be stored in online database. Every time user makes some request from app to the server than token is checked, if it exists in app and if it exists in server database and if they are equal.
3) How should I check if user is logged in when new view is loading in the app - should I just check if variables exists (for example in Keychains) or should I connect to the server and check every time server database?
for storing sensitive user data(password, api token, email) you should always use Keychain for this purpose.In other hand there is Realm also offer secure way to store your data.Its easy to use, you just need wrap data objects with realm base(Object) class and mark properties with dynamic attribute.For basic login system i think user name, email and api token good enough.But depends on api needs you can include here phone number, birthday etc.For checking user authorization I think validating api token good enough in most case.
There is also most secure techniques to improve data safety like keep database property names in keychain.Hashing sensitive data parts in api calls.Last thing you need use https for api communication.

Shared authentication with devise

I have two Rails 4 sites, auth.example.com and app.example.com. Eventually there are going to be multiple app-type sites, maybe a dozen or two, but let's start with the one. Auth has devise set up so we can do basic user management (user creation and deactivation, password and SSH key management, etc.), with users logging into auth so they can do basic stuff themselves like update their address or phone number.
I want to set up app so that it uses the same authentication as auth. If a user tries to access app without being logged in, I want to redirect them to auth so they can log in, then go back to the page they were trying to access on app. Basically, I want to do devise actions on app, but with devise residing on auth. This, of course, is so that when we have multiple sites running, we can implement devise once instead of having to put it on every one of our sites individually.
I found this but it doesn't look like it's quite what I want:
http://4trabes.com/2012/10/31/remote-authentication-with-devise/
Anybody have a pointer to a resource that can walk me through how to do this?
Thanks.
What I would do is create a small API simply for user management. Then allow your other apps to make calls to that API to log a user in, create a user, etc. So keeping them on whatever site they're on, but in the background you're talking to the auth API.

How to implement 'User' functionality in an app?

This is probably a repeat. However, the other answers haven't helped me out. So, here goes.
I'm working on an application and we with need to add 'users' to it. We'll be giving the option for people to sign in with Facebook, Twitter and LinkedIn. I've worked with these APIs before, however never combined them globally.
How can I maintain and manage these users that will use different services to log in. I'm confused as to how they would be stored in a database, would I need to have a different table for each different social service or is there a way to implement a table that will house all users in one place.
From what I understand, you're asking how to manage, store, verify users that will be logging in your application through different social services.
This is how we've implemented it through the various projects we've worked with. From the list of services you've provided we've worked only with twitter and facebook, so I can only speak about that.
Setup:
We have a web service that our iOS app communicates with such as when the iOS app needs to make a request call for user login the server would take the user details trying to login and gives back a response where the app would then do whats necessary.
We have a database stored on the server with a users table which is used to verify a user.
That being said, you need to understand whats common between most social services, or to at least know what the property is that is used by these social services to uniquely identify its users. In this case they all use email to identify users.
You'll find that when interfacing your app with these different APIs, they like to use a login session key used for unique logged in sessions.
So on your database you would store whatever details you want to save of the user, but know that you need to store atleast the username, password (encrypted), email (for identification, unique column), and login_session_key.
Just double check that linkedIn does have something like a session key that it creates when a user logs in with that method. Facebook and twitter do. Send at least the 4 main data properties needed (username, password, email, session) to the server You then follow this sort of approach:
New user
If the user that is new tries to login, the server first checks the email provided even exists in the database, if it does not then you sent a response back alerting the user that the user does not exist; your app would then take them to the register screen for example.
If the user is in the registry page, save all the details you want to store of theirs including username, password and email.
Members
If the user logs in the email will exist on the server side, its an existing user so just update the session key that was sent from the app on log in if the password matches, (in some apps these session keys are used through the life cycle of the application being used, with each request sending the same session key and if at any point the session key does not match during app interaction, it can be concluded that the user has logged elsewhere on another device perhaps.
if the password does not matches return the appropriate message.
That's about it really. We're able to store all facebook and twitter users in one table.

the user is forced to authorize my app each time

I am using tweepy api for oauth: http://packages.python.org/tweepy/html/auth_tutorial.html#oauth-authentication
The first time, user is ask to authorize my app. But from the second time, I dont want the user to be asked to authorize my app again.
The tutorial says
It is a good idea to save the access token for later use. You do not need to re-fetch it each time. Twitter currently does not expire the tokens, so the only time it would ever go invalid is if the user revokes our application access. To store the access token depends on your application. Basically you need to store 2 string values: key and secret:
auth.access_token.key
auth.access_token.secret
I plan to store access_token key and secret to a session. When user use my app the second time, I will just use the access_token, so user will not be forced to authorize my app again.
However, THE PROBLEM IS that what happen when many twitter users use my app, how can I know which access_token belong to which user.
I hope my question is clear.
Stop twitter to force user to authorize my app from second time.
if I need to store access_token to solve (1), how can I know which access_token belong to which user.
You need to implement session management in your web app and associate session IDs with your user model which stores the auth information. You don't say what language you are using but if you use the Ruby on Rails framework then session management is easily done. I recommend the Devise gem with omniauth-twitter (https://github.com/arunagw/omniauth-twitter).

Flex App Embedded in Rails App w/Authentication

We have a Rails 3 app using session-based authentication (modified acts_as_authenticated), and a Flex app that needs to be embedded in an html.erb template. The Flex app needs to access routes that have a before_filter set to check if the user is logged in. When interacting with the HTML site, this causes the user to be redirected to a login page, then sets a Rails session property (tied to a cookie) to record that the user is logged in when making future requests.
The Flex app needs to access XML that's generated by Rails (behind the before_filter) and I don't want to force the user to log in twice -- what should I be passing as a flash parameter to the Flex app so that it can present as "already logged in" if that session exists (ie, the user has logged in via the HTML interface)? I haven't dealt with this kind of problem before so I'm not sure if I'm even asking the right question. Any advice appreciated!
Integrating flash into your authenticated service can be tricky. You can't rely on normal http sessions or cookies to manage authentication for you. What is generally regarded best practice is to generate a unique token for each logged in user to pass on every request to the server to prove that they are in fact a logged in user. for example:
They log in through an html form.
When you serve up a swf that is going to access authenticated content you give it a flashvar of token=49r03f0239fhduffnkdjfgnas or something like that.
This token is generated server-side and stored somewhere to be checked on requests.
On every request to the server you pass this token and check it's validity.
If it's good you perform the action and return the data.
If it's bad you prompt the user.
notes:
tokens should be long and unguessable like a session variable.
each time they log in you need to generate a new token.
each time they log out you need to destroy the token.

Resources