Shared authentication with devise - ruby-on-rails

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.

Related

How do I sign in/out into a rails app's user account that use devise from terminal instead of browser?

I'm developing a rails app that use devise to manage users, and I want to prevent user from signing into my app directly. (can I just prevent it by removing all the relevant routes?)
I have removed the front end logic, but I know that browser is not the only way to access a website. People can also use tools like curl to access website, so I want to know how people do that so I can better prevent 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

Spam accounts being created via Facebook login

I've got a Rails App that uses Facebook for user accounts, and as of this evening, someone in Vietname has decided to (for whatever reason) use a bot to create fake accounts on my site using fake Facebook accounts. I'm getting about 2 new fake accounts / minute.
I've temporarily disabled registration, but I don't want to leave it that way, so I'm not sure what to do.
A couple things to note:
All the accounts use #yahoo.com or #ymail.com addresses
A lot of the accounts are registered by the same IP, but not all of them. It seems like he switches up the IP every 15 minutes or so.
I'm really at a loss, and I want to go to bed, but I can't until I find a solution to this. Help!
Make a capcha in registration form. If you already have a capcha in it then change the capcha generation mechanics. Also I think that your oponent made a script which is automaticly adds new user accounts to you web page, so as a temporary desicion you can change the url of registration handler.
You can use some techniques like limiting access to the application using something like a smart algo to block the IP it is requesting numerous account or limiting the account creation no more than a user from an IP.
And as specified if you know the pattern you can filter the request based on the pattern and deny any access.

asp.net mvc application need access to users google drive account from "service"

Im writing a web-app that gives our customers the possibility to SYNC their files on their personal Google Drive onto OUR bushiness application. (only limited file types).
So - what works so far:
Users signup to the app, (using OAuth2 and saves a refreshtoken in my end) the user/and my app, have now access to files on their Drive, and can manually invoke file transfers.
Working fine.
Users can afterwards login again and repeat this without having to authenticate the app again. Fine.
In parallel, I need some kind "service" that loops thru our app's user-base and AUTOMATICALLY syncs files in a designated folder - say every 10 mins.
Now im running into problems because of OAuth2 model, needs to redirect to authenticate every user. But I cannot make multiple redirects out of a single request to, say "/SyncAllUsers".
Also, when testing with one user only, the user still have to be logged in into the browser session, or else google will redirect to the service-login page.
(We use a chron-job to invoke these methods at a specified interval - and it is working well with dropbox-accounts, and these users also use OAuth)
So basically 2 questions:
How can I access my users Drive accounts, with my already authorized app, without having users to "be logged in"
And how should I handle the sync-service to run without having to redirect at every user.
I have spent days searching for answers on https://developers.google.com/drive/ and in here.
I have impl. the OAuth code from here https://developers.google.com/drive/credentials#retrieve_oauth_20_credentials
and I modified it so it is using my own user-database.
For your infomation im using the Client ID for web applications, in Google APIs Console
Once you have the refresh token, you can use it to perform synchronization without user intervention. This is the nature of offline access and the whole purpose of a refresh token.
(Sorry if this doesn't answer your question, I am not exactly sure what you are asking, so please explain more and I will try to give you a different/better answer.)

Auto Authentication

I am using Facebook, GMail and many other services and for each such service I have to enter my login and password. But only first time. After this first time the browser remember a login and a password and an authentication occurs automaticaly every time when I open this site.
How can I make this possibile for my site? Now I have to enter a login/pwd every time after I restart the browser.
Search the web for "cookie login". Things like authlogic and devise (since you mention Rails) have this baked (ahem) in. You most likely should not be rolling your own authentication code.
I'd recommend using Devise for authentication generally.
While you can probably code your own authentication features with no issue, Devise makes rolling out these new features a lot faster. For example, it's not difficult to setup these features:
Making 'Remember Me' optional so users can choose whether or not they stay logged on using a permanent cookie.
Automatic login using a token-based url (unique token per user account)
Integration with facebook, twitter, linkedin, etc via Omniauth
Allowing users to reset their passwords
Changing password security rules
etc, etc, etc.
Moreover, since it's very widely used it's very solid and debugged. There are many, many 'eyes on the code'.

Resources