Secure communication from React Landing Page with Rails Backend? - ruby-on-rails

I'm building a Landing Page in React where a visitor submits some data (including name and phone) and this data is sent over HTTP to a Rails 4.2 Backend.
Now, in order for the Landing Page to be able to POST data to the backend, there needs to be some sort of authentication, as only a registered staff member should have access to the data. The Rails backend currently uses regular Devise user/password login to the backend.
I thought about making a dummy account and hardcode an authorization token on the POST header from the landing page, but this is obviously a big security flaw as anyone can see the hardcoded token when they submit the form.
How can I secure the Landing Page to send / receive data to the backend server in a user-agnostic way (since visitors don't make accounts, they just fill a form with their details)?

I am not rails user. But as for your API, like almost all the RESTful API backend, I would assume that rails has the concept of public/private API. I would make the API for getting data from the user public, so that people can send their information without authentication and the other API routes private.
In java spring framework, I can allow an API route to accessible by everyone, like login and generic(no private info) API routes and every other API routes are private which requires Authentication(like an auth-token).

When, you do the login flow and the user has entered the password and hit send, Once your backend authenticates the details, you would have to create an signed authorization token using maybe JWT** ( Json web token ) and send this authorization token to the front-end.
Then, Whenever the front-end makes a call to the backend, it has to attach this token in the header before making the API call. And the back-end should de-code the token to find out which user is requesting it and if the ttl* is within the limits as the issuing token.
If both the cases pass, the back-end should send the requested data or it should send a HTTP CODE - 403/Forbidden, which should then be handled in the front-end to logout the user and open up the login page again.
*(Time to live calculated based on the hours this token is valid from the time of issuing/login)
** JWTs are basically base-64 encoded data ( and signed with a unique key by your backend ) of the user's data. A decoded JWT token of a user would most likely look like this :
{
userIs : "0000-aa12-bb43-cd18",
userName : "Some name",
ttl : "Time to live of this token"
}

Related

Angular 2 + Rails + Auth0

I'm trying to figure out how to use Auth0 with an Angular/Rails application.
I've set up Auth0 with an Angular-only application and it worked fine. I can see the Auth0 docs for Rails and as far as I can tell it makes sense.
What I don't understand is how to connect the front-end authentication with Rails, since I'm not finding documentation on this anywhere.
Okay, I've figured it out. If I use Auth0 to authenticate on the Angular side and then make an HTTP request to my Rails server, that HTTP request will have an Authorization header with a value like this:
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2JlbmZyYW5rbGlubGFicy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTgzMDZmOTFjMDg4MTRlMDEwMTVmNDM0IiwiYXVkIjoiajNKdHpjYnNpTUkyR0JkRnZGb3FFTjM4cUtTVmI2Q0UiLCJleHAiOjE0Nzk4OTc3OTYsImlhdCI6MTQ3OTg2MTc5Nn0.2cGLY_e7jY0WL-ue4NeT39W4pdxJVSeOT5ZGd_xNmJk
The part after "Bearer", the part starting with "eyJ0", is a JSON Web Token. Henceforth I'll refer to the JSON Web Token simply as the "token".
When Rails receives the HTTP request, it can grab and then decode the token. In my case I'm using Knock.
Knock expects my User model to define a from_token_payload method. Here's what mine looks like:
class User < ApplicationRecord
def self.from_token_payload(payload)
User.find_by(auth0_id_string: payload['sub'])
end
end
My user table has an auth0_id_string column. If I manually create a user whose auth0_id_string matches what I find under sub in the decoded Auth0 token, then my from_token_payload method will find that user and Knock will give me a thumbs up for that token. If no user is found, thumbs down.
So it goes like this, roughly:
Angular asks Auth0 to authenticate a user
Auth0 sends back a JSON Web Token
Angular sends that JSON Web Token to Rails
Rails decodes that token
Rails tries to find a user that matches the data in that token
Rails sends back either a 200 or 401 depending on whether a matching user was found
There are some pieces missing but that's the gist of it. I'll probably end up writing a tutorial on Angular + Rails + Auth0 authentication since, as far as I've been able to tell, none currently exists.
Based on the information you provided I'm assuming that you want to have an application that has the front-end implemented in Angular and uses a Rails based API to provides the services required to the Angular front-end.
In this scenario you can model this as a single (client) application from the Auth0 side of things and do one of the following:
Use the ID token resulting from the authentication for two purposes:
to provide information about the currently authenticated user to the Angular application so that it can meet any applicable user interface requirements
as a way to authenticate calls made by the Angular application to the Rails API, that is, the Rails API uses a token-based authentication system that accepts the ID tokens issued by Auth0.
Expose an endpoint on the Rails API that can be used by Angular to exchange the ID token received upon user authentication by any other credentials that can then be later used to access the API.
The first option is the easiest to implement, but you'll have to include the ID token in every request. The second one increases complexity on your side, but it may allow you more flexibility.
If this does not address all your concerns, can you please update the question with more details about the exact scenario you're trying to accomplish.
A final note, if your intentions are to provide an API that can be later consumed by a different range of applications then the most correct way to secure it would be by using a token-based system where the tokens would be issued by an authorization server compliant with OAuth2.
Having your own OAuth2 authorization server is significantly complex to maintain so Auth0 is in the process of enabling this as an additional service that can already be used in preview mode for accounts in the US region. This would basically allow to obtain as part of the authentication process an ID token used by the client application to know the currently authenticated user and also an access token that would allow to make call into the specified API.

Is my app secure? Token authentication with Rails and Angular

I have a Single Page Application in AngularJS with API in Ruby on Rails (Grape framework).
My authentication system looks like this:
User create an account. Sends information to server.
Server save user in database and generate token with Devise. Token and user information is send to Angular.
Angular save token and user info in storage (angular-storage) and token is added to every request (Authorization header).
When user click log out button, storage is cleared and token is deleted in database.
My question is: it this secure, or do I need to use something like JWT? Can I send a role name (for example 'moderator') to Angular without any encoding this? (of course server will always check, if this user with this token can do something)
I also will implement doorkeeper to my app in near future.

Is this concept of Oauth2 workflow for sinatra + angular.js + custom provider correct?

I want to build three example apps. One will be a sinatra oauth2 provider and second will be rails app with angular.js on frontend and rails on backend and third with sinatra on backend and angular.js on frontend.
Our Rails/Sinatra app will be authenticate users using satelizer and our custom provider.
These is our Oauth2 workflow right now.
Using Satellizer we get the authorization code from provider. We send this code to our backend.
In backend using this authorization code, secret key and other params, we send an request to provider to get an access token.
Using this obtain access token we call '/me' action to get an uid, email and other user attributes from provider.
In the same action we parse the response body and we find or create user based on uid.
We are wondering about this step which should somehow set the user's authentication token.
store the provider access token in user database record.
generate new authentication token and change it on every request
Generate JWToken with user uid and token and send it back to satellizer.
Then on each request Satellizer include Bearer JWToken in header. After recive request our backend verify header token stored in database and call sing_in method in our case devise(sign_in, store: false) maybe in sinatra app we will use warden.
What do you think about this concept? Maybe we are missing something. These is our first oauth2 authentication implementation and we are worried about it.

Passing parameters in callback URL Twitter API

I have used OOB callbacks with desktop and mobile applications for twitter oAuth. But now I am moving onto the web based authentication for my web application consuming twitter api.
I have the following flow of events:
User fills a registration form(with say n fields+) entering his email id and twitter handle.
This generates the(short-lived) twitter request token and the url for obtaining twitter Access Token and secret.
That url is sent to the user's email id, so that it serves the dual purpose of verifying the twitter handle and email id.
Now my question is:
Can I specify the callback URL with parameters so that when the user is redirected back to the application controller, the database receives the entries of the n form fields?
And also once the user is redirected back to the application, is it that the access token is appended to the callback URL (along with the parameters)? If yes, then how do I get the access token (token key and secret)?
To further clarify, consider the callback url:
http://www.someurl.com/controller?param1=val1&param2=val2
and on redirect to this url, I think(is it?) that twitter appends some params to this url, like
http://www.someurl.com/controller?param1=val1&param2=val2&someParamsAppendedByTwitter=someValue
I just want to know what this someParamsAppendedByTwitter is/are.
The biggest issue with this question is that in almost all languages, twitter authentication is being dealt with some sort of plugins/libraries and there are very less resources on the same if you want to do it all by yourself.

Login to mobile app and web app using oAuth

We have a SSO system which is used by our web applications and we are planning to also write some new mobile/desktop applications. I have been reading about using oAuth 2.0 so a user can natively login using the app (using the password grant type), retrieve an access token and access functionality using the REST web services. The problem is all functionality will not be available within the app, in some cases we have to redirect the user to the web application via a browser. I have read we shouldn't pass the access token in a URL so is there anyway to use oAuth to login to the web application automatically without the user having to submit their username and password again?
Any advice would be much appreciated.
In the mobile app, you could create a nonce (a token that should be used no more than once). Then, add this to the URL when opening a link to the Web page. This token should have some sort of identifier in it. The Web app that serves that page should track these IDs to ensure that it's not sent multiple times (thus, making it a nonce). This would be independent of the OAuth-based authentication. So, a request might look like this:
GET /anything?nonce=eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI5N1Y2ZU9WWlo1VGpPR3dWIiwiY2xpZW50X2lkIjoibXktZ29vZC1tb2JpbGUtYXBwLTIyIiwiYXVkIjoiaHR0cHM6Ly9leGFtcGxlLm9yZy9wYWdlLXRoYXQtaXMtbm90LWluLW15LW1vYmlsZS1hcHAiLCJleHAiOjE1OTg3NTI0NDB9.JoDstXRnC23PE8ZCqk-U-IzSNp_cUYa12HbajI1KGlF-OwRR46QRC_V7brcGOVdo5_Aw1RdpssNWCVFiGDeTBc8wi1lIJW-rgEGH5J1qUi8rL1T-yfy3vdLGPYzJMtHvCeyoEjgmoYOtZcpPSQScBJSRvId3Hdu3QgwcelSwljkeNJbZRCnG25HIqJfC1Cjm9vqHhvUGqtzbgVBUPnICiI8EZyGe3SpH2P4SxctLcgzWad8zJeyPFki3yfBHpqQ3mBWy0BbVdjzgD0mj323q1LWHR4kNkrH7cUJgAg4PlWahOW7Q4qcT3CBJYNtlh008ARqK7XagEQKX45vv5TfSlk2q7Zy06RnV2XwZXfLpyh-ZfURpcsxEJ3O-4NY71XxEqUtEyuisjQdZx5m95uzSrzk75F-ruQ3KYIouiAOAUDuMtFwhwjF68VdDeC4Zwt2q3BHzMBBp-8k1bAXq8e4dmHz0Jbuo9R8MJ2zSrVK6is5nNtNoJvYoXgc0WTA8MFqBj316cT_ouu-U1nTL3GR5sJ_lxorhP6xz0CqNxNY_90-JwOUB0UibUryRiXt-SUPJga36pBQ8eO8--Xupx_WU7CDIFdFvnLgJahD-4KmZcga6wCoqd-KKw3H5-jtbit06XMrKkDiWjz2g4eYhPR6xipbnqyZaaCwtYN4mAMz86ug HTTP/1.1
Host: example.org
Accept: */*
When the JWT-encoded nonce is decoded, you can see this header:
{
"alg": RS256
}
and this body:
{
"jti": "97V6eOVZZ5TjOGwV",
"client_id": "my-good-mobile-app-22",
"aud": "https://example.org/page-that-is-not-in-my-mobile-app",
"exp": 1598752440
}
Now, the API could decide if the nonce is acceptable by:
Check that it's URL is the same as the aud (audience) claim
Check that the nonce has never been seen before (using the jti, JWT ID, claim)
Check that this resource should be possible for this client to request (using the client_id claim)
Check that the nonce wasn't created too long ago and is still valid (using the exp or expires claim)
The signature of the JWT is valid. This can be done using the public key of the client.
Doing like this could lead to a spaghetti of trust, however. To avoid this, your OAuth server could instead embed a nonce into the app's ID token, or allow the client to request new ones as needed (by performing token exchange e.g.). Then, the API only has to trust the OAuth server, and doesn't need to keep track of the client's public key. If you only have a handful of clients, this won't be hard to mange though.

Resources