Backbone & REST API : Session Handling - api

I am in the midst of planning a saas app and have been stuck trying to figure out how I want to handle my session management. Here's the scenario:
Server 1: REST API, Rails 4 w/ rails-api gem
Server 2: Front-end, Rails 4, BackboneJS/MarionetteJS
These servers, eventually, will be part of a cluster of similar servers.
The applications are separate because there will also be a mobile app using the REST API and we plan on having 3rd party applications tie into our database via the API.
I've boiled it down to 2 scenarios:
1) Use access_tokens only for authentication on the front-end:
User logs in and sends over email and password over https
They are authenticated via the api and it returns an access_token
All future requests made on the front-end use this access token
2) User database sessions on the front-end and then access_tokens for api calls
User logs in and is authenticated via devise on the frontend server (storing session info in the DB)
An access_token is generated for them and added to the Backbone app initialization for future api requests
I favor #2 simply because every time the user changes the page, I can easily see if they are still authenticated and if not, boot them back to the login page.
But #1 keeps things easy in the sense that the frontend server deals with just that: the frontend stuff.
Does any suggest one method over another? Why?
Does anyone have any other alternatives?
Thanks all!

You're reinventing the wheel by doing using an access_token. Devise already generates a cookie and sends it back when signing in. Just parse this cookie out when the client logs in:
User logs in with backbone app (post request is sent to API server)
Devise does it's thing and authenticates the user, generates the session_id and sends it back in an HTTP Set-cookie header.
backbone app parses the cookie out and caches the session_id value (think of this as your access_token)
each subsequent api call sends the cookie value in an HTTP Cookies header as session_id=cookie-value-here
Note your session cookie name is custom to your app and can be configured in an initializer via:
# /config/initializers/session_store.rb
YourRailsApp:Application.config.session_store :cookie_store, :key => '_your_rails_app_session'

Related

Using JWT authentication across multiple microservices

I have search the web for an answer about this issue, but nothing is quite similar to the setup I have.
So I have a single page application and 3 services:
Backend service - service A
Service for serving static files of the SPA - service B
Authentication service - service C
The flow is as follows:
A user visits the site by going to the / of service B gets redirected to the /login of service B.
The user enters the credentials and they are sent to service C to perform the authentication process and to get the permissions for the user, this data is sent in a JWT.
Service B then puts it in a cookie and returns it to the user's browser.
Then the user performs a task which requires that JWT, so I have to send that cookie to service A, but there is a problem, I can't do it, the cookie is only for service A.
https://auth0.com/docs/security/store-tokens - this link is an example of a source I found that is talking about the issue of where to store the tokens for SPA.
It says there that I should use a cookie to store the JWT if :
If have my own backend
If the backend is in the same domain as the site itself.
The problem is that my backend has a different URL, it is a completely different service, so using cookies wont be the solution, or at least that is what it seems to me.
Then it says:
If your single-page app has a backend server at all, then tokens should be handled server-side using the Authorization Code Flow, Authorization Code Flow with Proof Key for Code Exchange (PKCE), or Hybrid Flow.
The problem here is that they don't even mention how and where to store the JWT so I can access it from multiple domains.
I have not found a clean way to save that JWT on the user's browser and send it in every request that I am doing to the backend.
The solution I need is to save the JWT in a secure way in the browser of the user, allowing me to send it to any backend service I need to.
Thanks for reading thus far and for helping!
One solution is to send the requests to the backend service with JWT in a query param.
You can then have a middleware in the backend service that converts it to an Authorization header so that libraries that look at it continue to work.
So that is the way I chose to implement the solution, but first, few clarifications.
When a browser tries to visit the site, as stated in the question, will be redirected to the /login route to verify the user.
But if the user is nonexistent, then I will let the user to see the site but with minimum permissions.
So if the user is authenticated, the cookie with contain the jwt with the needed data.
If the user is some sort of a guest, service B will still return a cookie, but will indicate that the user is a guest.
The way I chose to implement it is:
Because of the explanation above, we always get the cookie from service B, meaning we can always tell our site save it in the LocalStorage of the browser, so I decided to save the JWT in it.
For each fetch request that I make to service A, I will set a header named Authorization that the value of it will be Bearer <the jwt token> (insert the jwt inside <the jwt token>) as stated in this MDN article about authorization.
About security:
So because saving the JWT in a cookie that is related to service A is not possible (service B and A are from different domains), we are left with the LocalStorage option.
LocalStorage is not the most secure way, it is by default vulnerable to XSS attacks,
but, as stated in this answer, by mikejones1477, modern browsers have strong defense against XSS, and the LocalStorage is not vulnerable to CSRF.
So, essentially, there should be extra care about XSS attacks, but that is the way its made possible to pass the token between services from different domains.

Implementing identity server behind web api owin authentication

I have two different client apps written in javascript connecting to two different web api. I am trying to implement identity server 3.
Is it possible to have identity server behind my web api owin
authentication api end point. In other words, is it possible to
route /token endpoint from owin in web api to call /authenticate
endpoint in identity server?
Is it possible to audit log to db in identity server including
failed request along with user's ip and browser agent. Also is it
possible to log user's ip even if i am calling from web api as my
web api is being called by a user using browser?
In my case should i keep two different user base for two different
projects or move all my users to identityserver. If i move all the
user info to identityserver, how am i going to handle all the joins
with other tables in different applications or should i keep a copy
of user with minimum info such as id, email and name?
It makes little sense to first call a web api and deal with authentication during that call.
Your client apps should first redirect the browser to IdentityServer where user would log in and be redirected back to your client app along with either access token (implicit flow) or authorization code (AuthorizationCode flow), depending on the client app having a back-end or not. Then, your client app would make requests to the webapi, passing the access token in the Authorization header.
As for different user bases, one approach might be to implement specific IUserService for each user base and either send a hint about which one to use in the acr_values or tie it to specific clients registered in IdentityService. Again, depending on the requirements.
Is it possible to have identity server behind my web api owin authentication api end point. In other words, is it possible to route /token endpoint from owin in web api to call /authenticate endpoint in identity server?
Yes and no - you cannot reroute those requests, but you can host identityserver in the same application as a web api. In Startup.cs, map a folder to identityserver.
It's not a good idea to do this, first of all, which api of the two will host idsrv? What if that api goes down and takes idsrv with, then the other api does not work anymore.
-> host idsrv separately, make both apis and both javascript apps clients in idsrv, login to idsrv from the javascript apps (=SSO) and use bearer tokens for the api
Is it possible to audit log to db in identity server including failed request along with user's ip and browser agent. Also is it possible to log user's ip even if i am calling from web api as my web api is being called by a user using browser?
Yes, this should be possible, check the logging implementation for idsrv, at the least you should be able to plug in a provider that writes to a database.
In my case should i keep two different user base for two different projects or move all my users to identityserver. If i move all the user info to identityserver, how am i going to handle all the joins with other tables in different applications or should i keep a copy of user with minimum info such as id, email and name?
Idsrv does not need to have all the user info, just an email-address is enough, you can use that as link to the user data in your api databases if you use that as unique identifier.

How to protect the 'create new user' action for a private mobile API?

I'm developing a private API for a mobile app. I plan on securing and authenticating logged in users using JSON Web Tokens.
When a user authenticates and logs in to the service, the server will return a signed JWT in the response. The device stores this securely and sends it back as an HTTP Authorization header in every subsequent request.
So far so good. However, where I'm a bit puzzled is this: the token is generated for a new user when their account is created (ie they registered). This API endpoint (POST to create) is open and there is no token verification (naturally since it's a new user).
How can I ensure that POST requests to create new users are only authorized from the mobile app? In other words, if a malicious user sends POSTs to create spam users, how do I recognize this?
The API is over https. Though, even if I were to require the app to use an API key as a query param, that would expose it on the wire. I suppose I could pass in a Basic Header with a hashed API key/Secret.
What is a way to do this securely?
Edit: How to protect the 'public' part of a REST service from spam?

Token authentication in SPA app

I started new project. It is small application (playground) to learn couple new concepts. I will create backend API using Ruby on Rails and Single Page Application using React. I stuck in Authentication. I would like to create custom Token-based Authorization/Authorization. I came to following auth flow:
User fill password/login and send to backed using Ajax and through secured HTTPS connection.
Backed checks if user exist in DB. If user exist backend create Token and save to Redis with user id.
Backend response with token to client app.
On client side I will save above token to local storage.
Before every request I will get token from locale storage and pass to request header.
On backend I will take token from header and check if exist in Redis db.
Is this flow correct? Should I decrypt token on client side or It is not necessary? This project is only playground but I would like to do It properly. Please give me some comments if above flow isn't good enough.
I think that you have the right approach. This link could give you more details about token-based authentication:
Implementing authentication with tokens for RESTful applications - https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
Hope it helps you,
Thierry

How to do authentication with a single page app and API backend?

I own both, an API backend at api.example.com and a frontend single page app at example.com . The API is basically a wrapper for a database backend.
Now, I want to have a user of the single page app (= client app) to authenticate with the API. For this, as far as I understand, the client (= single page app) sends a client_id together with a user_id to the API, and the API then gives out an AccessToken.
However, in my single page app, I am not sure where/how to store the access token. I am looking for a simple reference, or a good concept to have a logged in user access the API application.
A friend suggested me this flow:
The client displays inputs for login (be it e-mail or username) and password,
The client app makes a request to your API to obtain an unauthorized token (e.g. POST /api/v1/auth/new),
The server creates a token for the app and sends it back,
The client app sends the token along with the login, password and request signature to the API (e.g. POST /api/v1/mobile_authenticate),
The API validates and verifies the credentials,
If everything is OK the app uses the token to make further on the user's behalf.
Any thoughts? How can this be simplified or improved?
I'm using the api key for the permission check in the server API. The workflow how the api key works is as below.
The client app displays inputs for login (be it e-mail or username) and
password.
The client app makes a request to the API to obtain an
api key (e.g. POST /api/v1/users/validate).
The client app accesses the API with the api key. (If it is the http request, the api key can be included in the http header or query string.)
Hope it helps.