Ask A Question

Notifications

You’re not receiving notifications from this thread.

API Authentication with JSON Web Tokens (JWT) and Knock Discussion

Bruno Batista Bruno Batista

Nice tip. @Chris, you forgot push the changes on repository!

Reply

Good catch, forgot to push. Just did it now!

Reply

Good tutorial Chris. Will be nice if you can create a complete tutorial or tutorials using devise. In my particular case I'm looking for something like this:

Register
Login
Logout
Forgot Password
How to send and manage all these things (Of course I understand if you don't cover a front-end part)

I read materials like this: https://www.sitepoint.com/i... but still not clear and I think with you we can have even best practices.

Thanks

Reply
Jordano Moscoso Jordano Moscoso

Awesome episode, but how do u deal with authorization? I have been using cancancan with devise. Currently i have a project with devise and cancancan and i need JWT for other model. How can i solve it on the same way?

Reply

Check out this week's episode where I talk a little bit about this for authentication. For the individual role authorization, you'll encode the roles of the user into the JWT payload and send that over to the client when they auth. Then you can simply base64 decode the payload of the JWT in Javascript. (See https://developer.mozilla.o... This will give you the roles on the client that you can pass to your JS to hide/show certain links. This way you can know the roles client side to determine what to display and server side you can use cancan/pundit to do the real authorization for the actions the user would take.

Anything client side is just going to be for displaying the UI and therefore should never be trusted so the server will still need to implement authorization as you normally would.

Reply

Hi Chris,

How do you customize what is required to authenticate the user? For example, you're using email and password to authenticate. In my app, an email is optional and a username is required. So I'd like to authenticate using username and password. Right now, however, if I create a user with a username and a null email, I am able to receive a token by just using "auth[password]=password". I'm assuming this is because Knock default uses email (which is null in this case and would pass authentication). Any tips?

Reply

Oops, looks like I only needed a few more minutes of reading the Knock docs :p
Knock does use email by default, and you have to specify if you want to use something else. Read here: https://github.com/nsarno/k...

Basically, you need to add this to the User model (replacing 'username' with whatever you need):
def self.from_token_request request
username = request.params["auth"] && request.params["auth"]["username"]
self.find_by username: username
end

Reply

I'd advise against adding the email address to the payload. The purpose of tokens is being able to store them client-side in a secure fashion. By adding the email address to the token, you'd expose 50% of your login credentials.

Reply

That's not much to worry about because if someone gets your token, they have full access to your account and can do anything they want. You've got much bigger problems in that situation because your JWTs should never be exposed.

Reply

Hi Chris,

How do you go about creating a user with Knock? As I understand it, the method you're showing above is to sign in a user and create a token. How would my create User controller method sign in the new user and create their token?

Reply

We wouldn't want our User controller to inherit from ApiController, correct? Because this has the before_action of :authenticate_user, which wouldn't make sense given there's no user to authenticate yet.

Reply

Is there a example available which shows how the Access token can be dealt with on the client side.

I have built the API with user authentication via Knock.
I am now trying to build a seprate Rails app which would consume this API however I am lost as to how the token would be saved client side.

Reply

Awesome!

Reply

Hiyas i have try to use this tutorial for that i get the pro :) and is cool but i have a problem try to use in my actual project im using Mongoid and devise i get errir at try to use has_secure_password :( can i get some help please

Reply

Hi again i try to use normaly make a new project and only use a controller it make to my the token but at try to autentificate using the token i get 401
HTTP/1.1 401 Unauthorized, i detect the problem is Devise can i get help to make working using devise and dont get conflict ?

Reply

Oh my!
I was just going paste my solution to this here and I find the same one, haha.
Great community.
Next I'll try to read first the comments, rather than searching on google, haha.

Reply

Looks like knock has an eager_load problem with Rails 6 & knock is no longer being maintained.

Reply

Yep, check out the JWT from scratch episode instead. That one will work just fine and you won't have to depend on other maintainers.

Reply

I will do that next - for better understanding indeed. I am mostly interested in the Devise JWT - since that is what I use most of the time anyway, but the series is interesting so I figured it can't hurt to debug a little.

Reply

Solution for Rails 6

  • To fix the autoloading problem on config and the error (uninitialized constant Knock) while trying to use
    change the line in: config/application.rb
    from
    config.load_defaults 6.0
    to
    config.load_defaults 6.0 and config.autoloader = :classic

  • To fix the problem Can't verify CSRF token authenticity.
    include skip_before_action :verify_authenticity_token in the file:
    app/controllers/api/v1/user_token_controller.rb
    so the controller needs to look like:

    class Api::V1::UserTokenController < Knock::AuthTokenController
    skip_before_action :verify_authenticity_token
    def entity_name
    'User'
    end
    end
    

AFTER these two fixes:
curl --data "auth[email]=user@email.com&auth[password]=*******" http://localhost:3000/api/v1/user_token
works!

Reply

Hi Chris,

Nice episode.
How do deal with token refesh?
Are you going to record something baout this?

Regards

Reply

Hi Chris,
I am getting this weird error where a HTML page is returned when the curl request for data is made and no JWT is seen.
Also, for curl -v status code is also 200 OK hence shows that no JWT is made

Reply

The knock gem GitHub page says: "This project is not being maintained and I don't recommend using it in its current form. As an alternative, I recommend using the jwt gem directly."

Could someone post an update in the comments at least showing how to "use the jwt gem directly" ?

Reply

Hey Justin, I'm not sure if you've found it yet, but Chris already has you covered with a video on that. https://gorails.com/episodes/jwt-authentication-from-scratch-with-rails

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 82,464+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.