All threads / API Authentication with JSON Web Tokens (JWT) and Knock Discussion
Ask A Question


You’re not receiving notifications from this thread.

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

Bruno Batista ·

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

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

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:

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: but still not clear and I think with you we can have even best practices.


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?

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.

Jordano Moscoso ·

Great, thank you.

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?

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:

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

That turned out nice and simple! :) I hadn't actually customized it to be username/pw but that looks pretty much exactly like what I imagined you'd have to do. Nice and simple, thanks for sharing your solution. 👍

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.

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.

Yes, this is about a worst-case scenario, as it is often in the context of security. You would want to delete the token and reissue a new one ASAP. If you added your email address to the token, that's now out in the wild, making things even worse.

Well, the real worst-case scenario is that your JWT is out in the wild and still valid, then someone just changes your account details to their own and hijacks it from you without you knowing.

Obviously, letting people know that your email address has an account is not great, but it's no different than someone attempting to register a new account with your email and it saying "This email address has already been taken".

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?

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.

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.

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

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 ?

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.

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

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.

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.

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
    config.load_defaults 6.0
    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:
    so the controller needs to look like:

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

AFTER these two fixes:
curl --data "auth[email][password]=*******" http://localhost:3000/api/v1/user_token

Hi Chris,

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


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

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" ?

Hey Justin, I'm not sure if you've found it yet, but Chris already has you covered with a video on that.

Join the discussion

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

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

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

    logo Created with Sketch.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more. Icons by Icons8

    © 2022 GoRails, LLC. All rights reserved.