I have a rails API and a rails client app that communicate with each other via ActiveResource. This works great until I need to pass a unique token with each ActiveResource request to authenticate the user. From what I understand, the ActiveResource token gets set at the class level and cannot be easily changed, which is obviously a problem if I want people to be passing in their unique session token after they are authenticated.
Here is the flow that I am trying to implement:
User submits credentials on Client app.
Client app transmits credentials to API.
API verifies credentials via Devise and returns an auth token.
Client receives auth token and saves in session.
All subsequent requests from Client include the auth token.
API authenticates all requests with the included auth token.
There are many different posts on SO and Github about this. Some say that it simply cannot be done, others say that you can force it, but there are issues with threading.
How can I accomplish what I'm trying to do without losing the huge benefits that ActiveResource provides?
Active Resource has undergone quite an update over the past year or so and is now working well in the modern web.
Active Resource supports the token based authentication provided by Rails through the ActionController::HttpAuthentication::Token class using custom headers.
class Person < ActiveResource::Base
self.headers['Authorization'] = 'Token token="abcd"'
end
You can also set any specific HTTP header using the same way. As mentioned above, headers are thread-safe, so you can set headers dynamically, even in a multi-threaded environment:
ActiveResource::Base.headers['Authorization'] = current_session_api_token
I've used an OAuth JWT strategy with Active Resource quite successfully using the second method in an API controller:
ActiveResource::Base.headers['Authorization'] = "Bearer #{jwt.token}"
Related
I have a client side React application and a Rails API from which the React app is fetching data.
As you would expect I only want my React application to be able to fetch data from the API and the rest of the world shouldn't be able to receive data from it.
Despite much searching I am yet to find the best way to secure the communication between the two applications.
I have read about JWT tokens and cookie based session authentication but the majority of articles seem to be focused on authentication of users (ie sign in/sign out) rather than communication between just the two applications.
The two apps will share the same domain so is it enough to rely on Cross Origin to secure communication?
Any advice really would be much appreciated.
If I got your question right you want your client(React App) to be the only client who can access your server.
As a solution to that you will have to have a combination of CORS and a JWT authorization, Thus I would suggest having a strict CORS to enable only your react app's domain to make a call to the server. To achieve this, I generally use a CORS npm module and configure the origin on my server or you can do it yourself as well.
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
The above code allows only requests from example.com to be accepted by the server or have a look at this code for more dynamic whitelist & blacklist approach.
Now coming back to JWT, It is just a json encryption and decryption token which can share across API request to Authenticate as well as authorize the user.
For instance, you can store information like email, role, and nickname of the user in JWT and sent this encrypted JWT in each API request, the server authorizes this request and if true forwards to the requested API. This process of authorization and forwarding is generally implemented using an 'Interceptor' pattern wherein a middleware(Passport oAuth) does the check and auth before each API call.
Doing the above 2 things will ensure that only a client which has valid JWT token and domain address which you allowed to talk with the server. And this client will be your react app, as it is the only one with proper JWT and origin address.
So now your react app should just make sure that appropriate JWT token is passed in the API calls (post/get/put), most probably in the header of the API request, you can have an API helper service which does this for you and import that in component where-ever you make an API call. And your node server will implement the passport middleware pattern to authorize this JWT and filter non-authorized requests.
If you react app doesn't have a login, The JWT can be a client ID as well which recognizes your client as being legit. And just like user login, you can have you react app make a call to the server with data like a secret client id. This will return a JWT token. OR you can pre-generate a JWT token and you react app store it when it loads the first time, and by setting TTL and another config you can check if the Client which is making a call to your server is Old or New or some other fake client.
HTH
The case of cross origin domains is when you might need to implement CORS and a security like a blacklist. JWT is a little different, as you say authenticating users who need access to your api.
I believe as long as you don't enable CORS on your server, you'll be fine.
Note that this will not stop people from doing things like:
https://example.com/api/blah to access a part of your api if it is public. This is essentially the same as your front end doing the same because the client is served to the user, and the user then has full control over the client. They could change all instances of api calls in your app to a different endpoint and you couldn't stop them, just as they could just type it in the url bar. Any public endpoints on your api have to not share sensitive info.
I am trying to implement token based authorization in rails, with devise_token_auth (https://github.com/lynndylanhurley/devise_token_auth#conceptual).
When I post uid and password against sign_in method, it returns access-token, client (and uid itself) in header. I understand that token based authorization works like this:
User posts uid(id) and password to api server.
Api server validates the uid and password
Issues Token and returns it, if the uid and password matched.
Client receives the Token.
Client whenever client wants to access the authentication required apis, Client uses the uid and the Token in order to prove that this client is in fact already authenticated.
I can understand that access-token corresponds to the Token described in above explanation. That leads to me a question of what the client header value is, because it seems that, according to the official Wiki (https://github.com/lynndylanhurley/devise_token_auth#usage-tldr), devise_auth_token library not only use requires access-token but also client value.
Question:
In devise_token_auth, what is the purpose of client header value? Why is it also needed for identifying the user? Couldn't that be included in (or, concatenated to) the access-token value?
The client header is generated for every different device accessing the API. Its purpose is to maintain more than one session active for a specific user (web client, mobile client, etc.).
You can test this by signing in with the same user on 2 separate web clients and checking user.tokens, there should be 1 set of tokens for every client.
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.
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.
I'm currently developing my own service with its own app. The service has a backend JSON API that the app uses to communicate.
Now, since an iOS app does not have sessions or cookies, I was wondering how I would go about creating a user authentication/login for my app. Should I simply locally encrypt the password/username and then, for every action (such as posting a new entry), send the user/password with the request (which seems unsafe), use a token-based system (app receives a token from the service when authenticating, saves it locally - encrypted - and then sends it with the request), or something else? Should I try to implement OAuth for my service?
I'm using the CodeIgniter Rest API for the backend.
Thanks!
My preference includes both. I normally use oauth2 with a bearer token setup (if I remember correctly). I ask for a username/email + password, encrypt the password client-side and send it to the server via Basic Auth in return for an access token which I can send on all consecutive calls. That way I can always revoke access to the backend by invalidating the access token. Oauth2 is much easier to implement than Oauth 1.0a and by following the specification, it is easy to open up your api for 3rd party apps later.
The Oauth2 access token can be send as a GET parameter, but lately I start to think sending it as a header might be preferable, to distinguish better the meta parameters like an access token and data parameters like it's or a model's actual data.