Is my app secure? Token authentication with Rails and Angular - ruby-on-rails

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.

Related

Secure communication from React Landing Page with Rails Backend?

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"
}

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

Update devise user using API, security issues

I need to provide a way to update, via API, some user informations in the mobile app like email, name and also the password(is optional; solution for that).
My problem is that because I'm using the API to change those data, how do I keep this secure ? what is the solution for updating the information only if my user is logged on the app. And how my API would know that it really is the user trying to change his informations and not someone trying to hack or something.
I'm using Rails 4 and Devise for authentication.
While signup and login generate a authentication token and send in the response.
Once the token is received by the app it can store it in local storage and will send this authentication token every time it sends a request to the server. This is how you will get to know that the user authentic and when the user logs out of the app delete that token from the app's local storage.

Sharing session between a rails server and a php server

Currently I have two servers set up, each handling there own thing, but I want to have a unified login between them. Right now one portal's login form is simply sending the username/pass through an API to the Rails portal, and it sends back an auth token, which we then store in our session and use for future authentication and API calls.
So the problem becomes that a user visiting our site has to login once in each portal, since the Ruby API doesn't communicate with ours, and the Ruby side doesn't do anything with the session when the API is pinged but send us back and auth token.
My initial idea was to have the Rails side create the session when we send the credentials to the API, but apparently that won't work as they won't be able to set the session id in the users browser, or at least that's what I was told.
If the Ruby side moved over to using the database for session storage, would that alleviate this issue? Basically, I want to keep most of the changes on the Ruby side for this.
I have implemented session sharing using memcache concept between Ruby on rails and PHP. i got success in this. if you are familier with memcache concept then it will be useful for you. and if you need any help for the same then i can share with you.
We wound up going a slightly different route. Basically, each side looks for the auth token in the database, and we pass it around via query strings on each link to the other. For example, if the user logs in on the PHP side, the Ruby side receives the username and password via the API, creates an auth token and updates the database, then sends back the token. The PHP side then stores that token in the session and sends it back via query strings (?authToken=blahblah) to the Ruby side, which is always listening for them. If it sees the auth token, it checks the database to make sure there's a match, and if there is, the user is authenticated in the Rails session.
Conversely, the Ruby side's login form simply updates the auth token in the database, and the links that point to the PHP side also pass the auth token. That side does the same check and will authenticate in the case that there is a match.

Resources