Rails login with Devise and encrypted cookies - ruby-on-rails

This is my first heavy task as a junior Rails dev so it might be a trivial. All the described applications work as microservices and my application can also be considered so
Rails app explanation
Rails 7
Ruby 3.1.2
Devise (API and web)
I've got Rails 7 app which is a single page dashboard with Devise to register/login users and show data from 3rd party API (let's call it main PHP microservice). User registration takes place outside the user's control via POST request from main PHP microservice to my Rails app. To login to the Rails app user needs to provide received SMS code each time. I need to implement that peace of login flow.
Problem explanation
The logging mechanism must include two factor authentication (2FA) which is handled by the main PHP microservice that sends an SMS (text message) with a code to login.
From a Rails side, when credentials (login/password) are correct a POST request is sent to the main PHP microservice to trigger 2FA. The main PHP microservice sends an SMS code (text message) to the user's phone which he later has to enter inside my Rails application.
So in a bullet points, the login flow inside my Rails app will be:
User provides login/password
If authentication credentials are correct, redirect to new window where the user must enter the SMS code they received on their phone
Login to the app when provided SMS (text message) is correct
3a. Trigger new 2FA process via POST request to the main PHP microservice and allow user to enter new code
What I was trying to use here is gem devise-two-factor but it use database to mark if 2FA is correct or not which I cannot use because one of the requirements of my ticket is not to use a database to determine whether 2FA is correct or not:
the gist is, username / password, and be able to set a cookie or add it to the session with the 2fa status for that session
Because a lack of knowledge, I cannot argue with this requirement and believe me, I tried.
Questions
From what I have read, to meet these requirements the safest way is to use an encrypted cookies. How to inject that to make it work with described devise login flow?

Related

Via the api, can I force the user to login to reddit?

I am writing a Reddit client that uses OAuth to authenticate the user. One of the features I would like to implement is the ability to use multiple accounts simultaneously. This requires the user to authorize my client on each account they want to use. The problem I'm running into is that if the user is already logged into Reddit in their browser, when I pop a browser to perform the auth, it will have them authenticate my client against their currently logged in user.
Is there a way to force the user to re-enter their credentials? I would rather not have to put some kind of disclaimer on my Add Account screen that says "Please log out of Reddit in any open browser windows".
I tried opening the Reddit login page in a WebView so the request is sandboxed, and while that worked, it gives the user access to the entire login page (including all the links that navigate to elsewhere on the site). I don't mind that experience when I'm popping an external browser, but in an embedded WebView I really just want to present a username and password box along with the OAuth validation prompt.
Note: I do kind of prefer the embedded experience because it doesn't interfere with the users existing browser cookies, I just don't like how cluttered the login page is this way and I'm not sure how to prevent the user from navigating away from login. Also, for completeness, this is a UWP app, though this problem is largely technology independent.
The problem I'm running into is that if the user is already logged into Reddit in their browser, when I pop a browser to perform the auth, it will have them authenticate my client against their currently logged in user.
It may be caused by the authorization server. If so, we can not do anything in our client app.
But if it is not the server issue, in UWP, there is a WebAuthenticationBroker class witch can help you to authorize your app to access the user info from Resource server by getting a token. You can try to use the class to implement OAuth authorization. You don't need to use the in a WebView so that you can authorize your app with multiple users if you can manage all the user with the token properly in your code logic.
See the Web authentication broker topic and the sample to learn more details.

Session retention after login on iOS app and Devise with Rails

I'm building an iOS app with Rails on the back-end.
The Rails application uses Devise for authentication and I want to use the same service for the authentication on the iOS app. Is there any way that after authenticating, keeping the session even after the app restarts, so that it goes straight to the content of the app instead of the login screen?
I've looked around, but haven't found a clear answer.
Thanks on advance!
One solution could be to extend the existing devise models and controllers to also handle a token based authentication system. Based on the request type html or json, the app can choose to authenticate a user either by the authentication token and email or a combination of username/email and password.
The authentication token could could be saved on the client side and reset only when the user logs out.
I was recently working on the same problem and found these sources to be extremely useful.
https://gist.github.com/josevalim/fb706b1e933ef01e4fb6
http://www.soryy.com/blog/2014/apis-with-devise/
https://github.com/lynndylanhurley/devise_token_auth

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.

How do I pass "Log In via Twitter" credentials from a Rails back end to an iPhone app?

I'm making the back end for an iOS app in Rails. Users need to be able to log into the app using an app-specific username/password or via Twitter, but I'm not quite sure how to set things up for logging in via Twitter.
If I use OmniAuth, then it seems like the flow goes like this:
The iOS app directs users, in Safari, to the /auth/twitter page OmniAuth sets up for me
The /auth/twitter page sends the user to Twitter for OAuth authentication
Twitter returns the user to /auth/twitter/callback, and OmniAuth gives me an auth hash full of info
????
iOS app now has the credentials it needs to identify the user making requests when it calls my APIs
Authentication complete, app use proceeds as normal
It's step 4, getting the credentials back to the iOS app, that I don't know how to set up. All my APIs the iOS app calls are stateless; if they require an authenticated user, then user credentials are included in the API call. I don't know that much about writing iOS apps, and pretty much nothing about how apps interact with Safari.
What is a safe way of getting the user credentials back to the app? One that can't be snooped? If I have the callback page put information in cookies, or in the session, will that be accessible to the app but not anyone watching the traffic?
Alternately, if the app attaches some identifier for itself to the initial call to /auth/twitter, will Twitter & OmniAuth preserve that identifier so that it gets included in the /auth/twitter/callback, so that the app can then ask my back end for the credentials for an authentication that just finished associated with that identifier?
Alternately, if the app attaches some identifier for itself to the initial call to /auth/twitter, will Twitter & OmniAuth preserve that identifier so that it gets included in the /auth/twitter/callback, so that the app can then ask my back end for the credentials for an authentication that just finished associated with that identifier?
Did you try? Cause that's usually how your step4 goes. You keep a token or something about the user so when you get the callback you can lookup for that user again. No session or cookies, just plain db.

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