Ability for users to sign up via SMS (Rails) - ruby-on-rails

I am working on a rails application where the main user model is authenticable by mobile number and a password. This all works fine through the website.
What I would like to do is enable a user to access all the same functions of the web app using solely an old school cell phone - that is purely via SMS. I have already enabled some of the web app functions via SMS using Twilio but I was unsure how to go about handling the creation of a user password via SMS in a secure manner.
What I would like:
User sends the word "LOAN" to our Twilio number.
This creates an account on our system based on their mobile_number. However, a password is required in order to persist a user in the DB so this will need to also be generated here.
An SMS is sent to the user with their password in a secure manner.
I imagine my TwilioController action will look something like this:
def sign_up
if params["Body"] == "LOAN"
user = User.create(mobile_number: params["From"], password: __?__)
user.sms_sign_up # method to send the sms to the user
else
send_failure_sms(params["From"])
end
end
I am already familiar with how to set this up on my Twilio account using TwiML apps - I am only interested in understanding how to manage the password aspect of this problem! Thanks
EDIT: I have seen that Devise provides the method #friendly_token. Is this something that would be useful in this case?

Twilio developer evangelist here.
I think your edit is the answer! I've found other Stack Overflow answers that advocate the use of Devise.friendly_token as well as this How to on generating passwords in Devise.

Related

Rails login with Devise and encrypted cookies

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?

AWS iOS Cognito - How To Check For a User in a Userpool?

I am just starting to work with, and learn AWS. I am using the services in the AWS Mobile Hub and so far have set up the Sign In & Sign Up methods.
Everything works fine, and now I am working on the Forgot Password and Update Password.
Problem:
The problem is, is that the way AWS has set up the Forgot Password is that:
You first enter a username and then after the user enters a username AWS sends a verification code via SMS to the phone number associated
with that username.
That's an issue because it means that anyone can enter any username and a text message will be sent, resulting in my SMS payments increasing and to be honest it just looks sloppy.
What I want to have done is that:
After a user enters a username, they then have to enter the phone number associated with the account
Then if it matches, it sends the SMS.
Question
How do I check if a user exists in a userpool?
And then if it does, how do I get the user attribute associated with the phone number to check if it matches the phone number that the user enters?
Is this even possible? Can I even get the credentials of a user who isn't the one logged in?
Thanks in advance!
Cognito User Pools does not currently allow you to get attributes for a user (such as phone number) without that user having signed in and gotten an access token.
The admin apis can do the lookup you're looking for, but they shouldn't be called from the client as that would mean you have to embed credentials. If this is a must have for you, you could potentially secure those credentials by wrapping it in API Gateway or something along those lines and then call that from your client.
Here is how you should do it:
1) Create a web API using the APIGateway. Ideally you want to restrict access with an API Key, which you should bundle with your application.
2) Connect a POST method to a Lambda function, which will
(a) perform the necessary checks (whether the phone number specified is indeed the correct one, etc), calling the admin_* functions.
(b) issue the client version of the password reset, which will trigger the sending of the SMS code.

devise_token_auth automatic sign_in after sign_up, returning sign_in.json?

Using:
Rails 5
devise_auth_token
Site Info:
Site used strictly for apis
Apis will be consumed by mobile apps; sign up, sign in, other CRUD operations, etc.
All apis will return json
What I want to do:
I want to be able to automatically sign_in a user after they have successfully sign[ed]_up AND return the header and json normally returned from DeviseTokenAuth::SessionsController#create.json - so the auth token, client, uid, etc. can be used in subsequent api calls. I haven't overridden DeviseTokenAuth::SessionsController, but I can if I need to. BTW, although I want to sign_in the user after a successful sign_up, I don't want to disable the confirmation email normally sent after sign_up; I do want the user to have to confirm the email address entered.
Also, any additional advice/gotchas/etc. you can add in addition to your answer would be appreciated.
Thank you in advance for your help.

Send devise confirmation instructions using SMS or email

Hi I have used devise for the authentication purpose and also made few changes in it such I have provided sign in using both email and mobile number. Refereed this link.
Here is my code
def self.find_for_database_authentication(conditions={})
find_by(mobile_number: conditions[:email]) || find_by(email: conditions[:email])
end
I am using confirmable module for sending confirmation instructions and they are working fine for email.
Now if user doesn't enter this email (only enters the mobile number) then he has to send the SMS (Confirmation instruction in SMS).
So I have following doubts
How can I achieve this functionality?
How can I generate the same confirmation link for the same.
EDIT (I tried following solutions for generating confirmation link)
As I have to send the confirmation link in SMS also, so I tried to generate the given link using following
http://localhost:3000/admin_users/confirmation?confirmation_token=#{#user.confirmation_token}"
it generates the follwing type of link
http://localhost:3000/admin_users/confirmation?confirmation_token=00b2880c9662c65dc6d276db08532ea42d4333e6b7d2357d036cb9233eed41e8
when I tired to use this link it gives me Confirmation token is invalid error. After searching I found this. So how can I generate the confirmation link out side the devise scope.
As for sending the instructions via SMS you might want to take a look at tropo service or restcomm if you want to setup your on server.
Tropo is particularly easy to use, you will need a small deposit (like $10) to enable the SMS sending feature.
Regarding the generation of the url, you might have to create a controller that extends Devise::ConfirmationsController and override the create method to add the logic to check for the existence of email or phone number and react properly.

Devise 3.2, Confirmation without Login, and Password Creation for New Accounts

I've upgraded to Devise 3.2.1 and Rails 4.0, and I'm trying to figure out my signup now that one doesn't login on confirmation.
I allow users to create a message and specify the recipient of the message via an email address. Then I send emails notifying the recipient that they've received a message on the service. If the recipient doesn't have an account on the service, I create the account without a password, and the email I send to the recipient acts a confirmation email. With prior versions, the recipient would then click on the link, thus confirming, and then be taken to a password creation stage and then finally, they'd have a confirmed account created with password and can go see the message.
With Devise 3.1, they no longer allow login via confirmation as they consider it a security risk, however I fear it may greatly increase the complexity of my sign up process. I can no longer redirect to a password creation page as they aren't logged in. I'm toying with the idea of taking them to a special signup page or creating the account and then sending a special form of password reset.
I don't want to notify them via email, then send them a second email as a confirmation. That adds unnecessary complexity to my signup.
I wondered if anyone else has dealt with this issue and how they handled it. I'd like to avoid using:
config.allow_insecure_sign_in_after_confirmation = true
as that will go away soon and is really not the right way.
Is there a secure, yet fast way to do this with Devise 3.2?
Thanks!
I'm switching to using sorcery ( https://github.com/NoamB/sorcery ) for greater control over authentication and building my flow with that.
This is precisely the problem that devise invitable gem solves in a secure manner. I would recommend using this tool, rather than trying to hand-roll your own solution which is more likely to contain security flaws.
The gem workflow is basically:
An admin invites a new user.
The new user is created with a random password. (I actually helped write this bit!)
The user is sent an invitation email. (This is fully customisable in how it works, but has some simple default settings.)
The user receives a link, which contains a URL with a unique invitation_token.
After clicking this link, the user must choose their real password.

Resources