Skip to main content

Subscribe to GoRails to get access to this episode and all other pro episodes, and new awesome content every month.

Subscribe Now
Only $19/month

Unlimited access. Cancel anytime.

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

Episode 165 · January 3, 2017

Authenticate your API using JSON Web Tokens (JWT) using the Knock gem

Authentication APIs


Transcripts

Subscribe or login to view the transcript for this episode.

Discussion


Gravatar
Bruno Batista on

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

Gravatar
Chris Oliver (159,840 XP) on

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


Gravatar
Carlos Orellana (930 XP) on

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


Gravatar
Jordano Moscoso on

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?

Gravatar
Chris Oliver (159,840 XP) on

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.

Gravatar
Jordano Moscoso on

Great, thank you.


Gravatar
David Porter (40 XP) on

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?

Gravatar
David Porter (40 XP) on

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

Gravatar
Chris Oliver (159,840 XP) on

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. 👍


Gravatar
Jochen Lillich (620 XP) on

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.

Gravatar
Chris Oliver (159,840 XP) on

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.

Gravatar
Jochen Lillich (620 XP) on

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.

Gravatar
Chris Oliver (159,840 XP) on

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


Gravatar
David Porter (40 XP) on

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?

Gravatar
David Porter (40 XP) on

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.


Gravatar
Anand Padia (1,300 XP) on

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.


Gravatar

Gravatar
Oscar Miguel Amezcua Estrella (90 XP) on

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


Gravatar
Oscar Miguel Amezcua Estrella (90 XP) on

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 ?


Login or create an account to join the conversation.