-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why is tokens
field a json type and how to create a query based on inside values?
#707
Comments
It's necessary if we want to allow users to authenticate using different clients / devices. Because each token needs to have the client's id stored with it.
The stored token values are hashes of the original tokens. You can try something like this: User.where("users.tokens.values.last['token'] = #{::BCrypt::Password.new(params[:token])}") But you should also be sending the # find the user
u = User.find(params[:uid])
# validate the token, where params[:client] is the ID of the device sending the request
u.valid_token?(params[:token], params[:client]) |
Stumbled upon this issue when I asked myself the same question about tokens stored in json column. Wouldn't it be more efficient in terms of performance if tokens were stored as separate database entries? Token lookup and token generation/storing would be much faster. Only now I noticed that technically main bottleneck of API requests my application is getting is the exact moment, when token column is updated after request. |
@riggy do you have any benchmark data to backup your claim? |
@zachfeldman Not yet. It was just a hypothetical question (maybe not phrased as one) based on my general knowledge of how relation databases work. I might lack some knowledge on how lookup is performed on json columns though. I was wondering if there was some solid argument to choose that solution over the other and I was hoping to get one. But you've posted a valid question - I'll try to come up with some data to verify that one way or the other and get back to you. |
External User.where("users.tokens.values.last['token'] = (?)", ::BCrypt::Password.new(params[:token])) |
Thanks for pointing out the SQL injection issue. But I want to make it clear that I was not advocating that anyone take the approach described in that example. This is the correct way to check if a user's token is valid: # find the user
u = User.find(params[:uid])
# validate the token, where params[:client] is the ID of the device sending the request
u.valid_token?(params[:token], params[:client]) |
How do you generate tokens for the jsons field? I've been trying a multitude of approaches, but no luck! Can you give me an example of before_save :ensure_authentication_token. Thanks. |
Hello,
I don't understand why is the
tokens
field a json type, is it really necessary to store multiple tokens?I'm sure there's a good reason, but I have some troubles because of this, on my previous token auth system (handmade) on my API, I was authenticating my users by the token provided by the clients. With a simple line as:
User.find_by(token: params[:token])
How to make this authentication works with this json objects? In the rails console I found that we can get the last generated token for a user by doing:
User.first.tokens.values.last['token']
But how to get a user based on the provided token? Something like:
User.where("users.tokens.values.last['token'] = #{params[:token]}").first
But of course this does not work
The text was updated successfully, but these errors were encountered: