so we are currently using a Rails application as our primary backend but we are also using a node.js server with socket.io to allow for some realtime updating data on each page. Setting up the connections and socket.io rooms is fine right now, the issue is I need to validate that a user has permission to access the information in the room they are trying to join. What I need to do is validate that the user making the javascript socket.io request is logged in on that same session to the rails server (I.E. If someone tries to access data restricted to user X on the node server, they must be logged in as user X on the rails server). I'm using sorcery on the rails server for my account authorization.
My initial idea for this was to store two cookies in the user session when they log into rails: a session_token and their email. Say user X logged in once again, his email is X#mail.com. X's account credentials (user and password) are validated on rails and the two cookies are stored in his session. Then the rails server would store X#mail.com's session_token in the SQL database. Then X navigates to a page with a socket.io connection. Then the node server would read these cookies, find the user with that email, and validate that their session token cookie is the same as the entry in the database. If it is, they effectively are now logged in on the node server and I can give them access to the same information they would have on the rails server. Is this an effective solution, or are there potential security holes here?
I'm very familiar with Rails, but new to node.js/socket.io, so I'd ask that you are fairly descriptive when describing node stuff.
Related
I've a site which will hopefully use a third party service for logging in (through use of OAuth2 and OIDC). I understand 90% of the process involved but am failing to get what I see as the final step. I'll describe the steps as I see them here and maybe someone can help me fill in the gaps. In my set up the Resource Server and Authorisation servers are the same machine.
This is the login process as I envisage it.
User comes to my site (let's call it Site A) and clicks login
They're redirected to the authentication site (Site B) where they
input their username / password.
Assuming correct credentials they're then redirected back to Site A with an auth code.
Site A takes this auth code and in a back channel communicates with Site B
again asking to exchange the code for a token.
Site B provides an access token to Site A (not to the end user, to the server)
Site A then communicates with Site B again (Resource and Authentication servers are the same in this scenario) and gets the relevant user detail.
So the user is authenticated and we know what claims they have, however, what I don't get in the above scenario is how Site A knows who I (the end user) am.
I never logged in on Site A so presumably no cookie was set. Basically I've gone to the site, been redirected to another site, logged in there and then am redirected back to Site A but is there a cookie set at that last redirect to identify me?
I've read plenty about this online but haven't found a clear answer.
Also, am I correct in thinking that in authorization code flow that the access token never gets to the user but instead resides on the application server?
If you really want to know who the user is on SiteA, it has to be the user from SiteA's own user database. It makes sense if SiteA is not just a proxy for SiteB's API and has its own users, permissions and functionality.
To figure out who the user is on SiteA you will need to match all your SiteA's users with Auth Server's users.
Part 1. Import your existing users into Auth Server
If you control Auth Server, import all your current users into its user database. Every one of them will have Subject ID (Id on Auth Server side). Copy those IDs back to corresponding users in your SiteA's db: your SiteA's User table will have new column, for example:
userid, user_name, user_last_name, user_auth_id (new column)
if you can't import all your users, it gets complicated. The only way I can think of: you will have to log those users in twice - once into OIDC provider and once in SiteA and then associate SiteA's user with OIDC user.
Part 2. Matching the incoming user to the internal user in SiteA
In successful response from OIDC Server you will get ID Token back. It contains sub claim with Subject ID of the user. When you've got that, you will need to do a lookup in your internal DB and find a corresponding SiteA's user. If you did not find one, create a new user at SiteA (if all existing users had been imported)
Once you know who the user is, log them in to SiteA like you would normally do (give them a cookie for example).
OpenID Connect auth servers provide the userinfo endpoint, which Site A can use for getting info about the user who authorized the access token (or the authorization code). For the auth provider (Site B) to be able to do it, it needs to keep association between a token and its user. So there is no cookie for this purpose.
You are correct about the auth code flow - the access token stays at the backend - there is no need to send it to the frontend / user.
To be able to pair the tokens kept at the SiteA backend with the consequent requests from the browser, you have few options:
You can use a backend session with cookies, which is very easy, because most backend frameworks have a built-in support for it. The cookie is sent automatically with each request and the tokens can be stored in a session object. This solution may be harder to scale - if you need a cluster.
You can create your own session implementation - either by using cookies or by some identifier expected on REST API as the Authorization HTTP header value. The backend session data can be kept in some distributed storage, such as Hazelcast or database. The session identifier can be in form of signed JWT, so you can keep user info in it.
Hi I'm building a authentication scenario of my Rails REST API server.
My plan is:
User send their username and password in the authorization header with Base64 encryption.
Once it's authenticated by the server, the server will return a auth_token to the user, which could be used for authentication of this user.
If the user log out, that auth_token in the database will be destroyed.
Is this plan ok? What kind of problem will it have, in performance and security?
So many thanks!
update: I'm using a mobile app to communicate with this server, and no session will be used.
I think there's a similar question, which is quite huge and closed...
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.
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.
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.