Single logon with different applications approach ruby on rails - 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.

Related

Track paid content without authentication on iOS

I want to offer some paid content in the app but I don't want the user to go through an Authentication process. I would like him to enter the app and directly be able to buy some of the content and remember that this user has bought it if he comes back later or uninstall/reinstall the app later on. (Like most meditation app on the Store right now)
Is it possible using Firebase Services and if so, what would be the good way to track paid content for anonymous user?
An Anonymous user IS a user without details (Name, email, password, etc). It has a unique UserID
So YES. You can save anything to the database using the User's unique ID. But remember. Every app is capable of performing operations inside their sandbox directory. which also has a unique ID and resets when the app is uninstalled.
In a sentece. Firebase won't remember the Anonymous user ID if the app was deleted intentionally.
The docs does state this very well:
You can use Firebase Authentication to create and use temporary
anonymous accounts to authenticate with Firebase. These temporary
anonymous accounts can be used to allow users who haven't yet signed
up to your app to work with data protected by security rules. If an
anonymous user decides to sign up to your app, you can link their
sign-in credentials to the anonymous account so that they can continue
to work with their protected data in future sessions.
Read more:
Authenticate with Firebase Anonymously on iOS
You could theoretically set it up to where it would redirect the user to a TextField page asking him/her to make a "password" and "PIN" of sorts. This "password" and "PIN" could then be stored into a SQL server database as an anonymous user. When re-downloading the app you could have a page dedicated to purchase recovery where all a user would need to do is input this "password" and "PIN", after they have correctly entered both it would return purchases to their account.
things to be wary of:
-People may use the same password, which is why I recommended a PIN as a way of two-step authentication. Keep in mind also that your app will need to test the password against the server before uploading to make sure that the password doesn't already exist and tells the user that the password cannot be used in such case.
-This is essentially the same thing as an account with a username and password... the only difference is that you aren't going to be collecting other information on them, such as email and birthday, etc., making it more anonymous.
-This is a very rare case of question and I know this is a crappy answer, but honestly this isn't the best idea to implement unless your app heavily relies on it.

Rails inception - how to handle a login session within a login session

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

Devise token authentication and session

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).

OAuth combined with custom users

I have a website where users can create an account and log in. This is stored in a database on the server. I also want users to be able to log in with Facebook etc, and thus skip the account creation. I don't know how to combine this and keep it persistent in the database. Any good examples on this use case?
Let's first see how logins work in general. When a user is logging in for the first time, a session id is generated for the user and is stored in the browser of the user as a cookie (note that there are mechanisms to store session id without a cookie, but let's assume you require a cookie for simplicity).
For subsequent requests to other pages in the same website, the cookie is also sent along. With this cookie (which has the session id), the unique user can be identified.
So, all that you require to know to identify a user in the server side (upon a web request) is the session id.
Having said that, if you want to include facebook etc into the login mechanisms, you need to do two things:
Connect your website with facebook (you will require a facebook developer account and some keys. Look here). When you do this successfully, if the user selects facebook login, your website should redirect to facebook login page and once the user logs in into facebook account, facebook will redirect back to your website with a token. This token is an indication that the user is a 'real' user. If required, you can use the token to get more details (such as facebook id, email address, name, etc.) from APIs facebook.
The second step is the same for any authentication flow. You need to generate a session id for use by your server and then save the session id in cookie.
What I have specified is the general flow on how your requirement could be achieved. The mechanics of how to do this will depend on the server side technology that you are adopting (such as ASP.NET, Ruby, etc.)
Additionally, if your website requires storing information about the user behavior / user activity, you may need to additionally check if the user logged in via FB already exists in your database. If not present, you can store the user's facebook id or something to uniquely identify the user later. With this as the primary key / user id, you can store user activity (such as inserting a record in orders table if the user purchases a product).

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.

Resources