zulhfreelancer said over 7 years ago on Rails API - Authentication with JWT :
Thanks Dave for making this video. I've question about the login. That means, for the very first client request to server, the client actually sending a plain text password. Right? How secure is that? If I'm not mistaken, everything that client sends to server will be show up inside the server logs. Please clarify.

David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

By default, config/initializers/filter_parameter_logging.rb will filter the password

Rails.application.config.filter_parameters += [:password]

So, the logs would filter out the password and never be displayed in the logs. Whenever communicating with API, especially sending the password, you should always encrypt the communication with SSL. This is really no different than sending a POST request to a web login session. Unless the form is posted to an endpoint over SSL, the password would also be sent over plaintext.

Great questions!


zulhfreelancer said over 7 years ago on Rails API - Authentication with JWT :

Thanks. What do you mean by this?

"...Unless the form is posted to an endpoint over SSL, the password would also be sent over plaintext."

I'm not quite get it.


David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

If your application's traffic is not being served over SSL, anything that is sent or posted, would be essentially in plain text.  It was just illustrating the point that your worry about the API sending the plain text password would be the same worry for a login form. Unless the API endpoint as well as the login form are served over SSL, the password would have been sent over plaintext (and not encrypted via SSL). I suppose the confusion was plaintext. Technically, regardless, in both instances the password is sent as plaintext, but when served over an SSL connection, the plaintext password is protected.


rome3ro said over 7 years ago on Rails API - Authentication with JWT :

Do you have some approach around user register? I found some tutorials about jwt but it's not clear to me, how should be having an api rail app along with an web client rails app, my intention is to have an api and 2 clients, the admin app and the customer app both of them communicating to the API, so the register part needs to be on clients.


David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

With a user registration, it would function very similar to any other kind of form post that you would do. You should have some sort of registration endpoint within your API application that would create the user. You may have something like http://example.com/users/create where you would make an HTTP POST to via your app. You would pass in the parameters

{
  user: { 
    first_name: 'John',
    last_name: 'Doe',
    email: 'john.doe@example.com',
    password: '123456',
    password_confirmation: '123456'
  }
}

and your model would have the necessary validations to ensure password complexity, and email uniqueness. If the user is created, pass a successful response. Otherwise, you would respond with an error.

You would also need to provide an authenticate method for your user. In this example, we simply used devise to handle the user registration and authentication. While you could do something similar in an API only application, it might be a bit heavy. However, using the devise logic (not necessarily the views), will give you access to a lot of the built in functionality around locking out the user, confirmation signups, etc.

Depending on the architecture of your application, you can make the new user registration only available under the client portal. Also, if you are using some sort of role based authorization, make sure that you set the default access to a client role. 

Hope this helps!


Bash said over 7 years ago on Rails API - Authentication with JWT :

Thanks for this. What GUI tool are you using to send these test API requests?


David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

It is a Chrome Extension called Advanced REST Client.


danielb_leal said over 7 years ago on Rails API - Authentication with JWT :

Hi, thanks for the video.

I clone this github repo, make manual user registration (via rails console) and then make a POST request to get jwt token (authenticate). Until then, it worked perfectly.

However, when I request localhost:3000/users/1 I get the page html, instead user data as json or 401 Unauthorized. How can I solve that?


David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

The reason why it is displaying the page instead of a JSON response is due to the sample application's routes.

  namespace :api, path: '/', constraints: { subdomain: 'api' } do
    resources :users
  end
  constraints subdomain: ['', 'www'] do
    resources :users do 
      resources :phones
    end
    root 'users#index'
  end

In the example application's routes, there is a constraints on the subdomain where if it is empty, it will default to the web view of the application. If you're using an API only, you can remove the constraints block as well as the constraints on the subdomain: 'api'. So your routes may look something like

Rails.application.routes.draw do
  post 'user_token' => 'user_token#create'
  devise_for :users
  namespace :api, path: '/' do
    resources :users do 
      resources :phones
    end
  end
end


Patrício dos Santos said over 7 years ago on Rails API - Authentication with JWT :

If you prefer, you can use Postman too: https://www.getpostman.com/


Bash said over 7 years ago on Rails API - Authentication with JWT :

Thanks!


Patrício dos Santos said over 7 years ago on Rails API - Authentication with JWT :

First thanks for this video. Helps a lot. 

But I am having a trouble implementing this like.

I have the following Routes:

Rails.application.routes.draw do
    namespace :api, constraints: { subdomain: 'api' }, path: '/' do
        namespace :v1 do
            post 'user_token' => 'user_token#create'
        end
    end
end

With this code, I expect to be able to make a POST request like: POST http://api.domain.com/v1/user_token

But when I try to that, I receive an error: NameError: uninitialized constant API::V1::User

It seams like, its looking for the model `User` on the same namespace. But my model User is not namespaced:

class User < ApplicationRecord
    has_secure_password
end

How can I make it work? What I am missing?

Thanks


Patrício dos Santos said over 7 years ago on Rails API - Authentication with JWT :

I think I found a temporary fix :  https://github.com/nsarno/knock/issues/120


David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

It looks like it was from where the TokenController was getting parsed.

https://github.com/nsarno/knock/commit/ed467d1e3e70dde5b4a367ac1b73dcf48ae4cebb


stephane.cedroni said over 7 years ago on Rails API - Authentication with JWT :

Thanks for the interesting video Dave. JWT tokens provided by the Knock gem have a default expiration of 1 day, and it would not be a very good user experience to ask login/password that often on expiration. Have you tried or can you think of a way to refresh tokens client-side to improve the UX?


David Kimura PRO said over 7 years ago on Rails API - Authentication with JWT :

You can change the default expiration. See the initializer at

https://github.com/nsarno/knock/blob/master/lib/generators/templates/knock.rb

  ## Expiration claim
  ## ----------------
  ##
  ## How long before a token is expired. If nil is provided, token will
  ## last forever.
  ##
  ## Default:
  # config.token_lifetime = 1.day

You should be able to set the token_lifetime to nil to make the token never expire if that is a requirement as well.

config.token_lifetime = nil

abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

Hi,

I am using Devise and have followed same steps as mentioned in your video. My view is not rendering elements as i have in my view:

<% if user_signed_in %>


Can you suggest?


David Kimura PRO said almost 7 years ago on Rails API - Authentication with JWT :

It should be user_signed_in?, not user_signed_in.


abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

Sorry, still it is not working.


David Kimura PRO said almost 7 years ago on Rails API - Authentication with JWT :

What error are you receiving? 


abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

There is no error, this"if condition" always returns false, so i am not able to load the components:

 <% if user_signed_in? %>
                                    <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Account
                                        <b class="caret"></b></a>
                                        <ul class="dropdown-menu">
                                            <li>
                                                <div class="navbar-content">
                                                    <div class="row">
                                                        <div class="col-md-7">
                                                            <span>User Name</span>
                                                            
                                                                <%= current_user.email %>
                                                            <div class="divider">
                                                            </div>
                                                            <a href="#" class="btn btn-primary btn-sm active">View Profile</a>
                                                            <div class="divider">
                                                        </div>
                                                    </div>
                                                </div>
                                                <div class="navbar-footer">
                                                    <div class="navbar-footer-content">
                                                        <div class="row">
                                                            <div class="col-md-6">
                                                                <a href="#" class="btn btn-default btn-sm">Change Password</a>
                                                            </div>
                                                            <div class="col-md-6">
                                                                <%= link_to "Log out", destroy_user_session_path, :method=>'delete', :class => 'class="btn btn-default btn-sm pull-right' %>
                                                            </div>
                                                        </div>
                                                    </div>
                                                </div>
                                            </li>
                                        </ul>
                                    </li>
                                    <% else %>
                                    <li class="dropdown"><%= link_to "Login", new_user_session_path %>
                                    <% end %>

abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

Thanks Kobaltz, i figured it out that i was using my application controller not the one which is present under api folder.

But there is a different problem now, i am trying to get information from students controller, and it doesn't work because of this line in the controller:

before_action :authenticate_user!

(P.S. I am using devise) 


Do you suggest?


David Kimura PRO said almost 7 years ago on Rails API - Authentication with JWT :

If I remember correctly, the authenticate_user has some weird interactions with JWT. This was part of the reason for the alias methods in the User model. Part of the solution was to undefine the method current_user and and with the includes of the Knock Authenticatable, the current user would be set.

Are you receiving any specific error messages?


abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

True, i implemented the same way:

This is my error(Json response, i think this is from devise):

{
  "error": "You need to sign in or sign up before continuing."
}

This is my user model:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
         # remove required: false later
  alias_method :authenticate, :valid_password?
  def self.from_token_payload(payload)
        self.find payload["sub"]
  end  
end

This is my application_controller from api module:

module Api
  class ApplicationController < ActionController::API
    include Knock::Authenticable
    undef_method :current_user
  end
end





David Kimura PRO said almost 7 years ago on Rails API - Authentication with JWT :

That does appear to be a devise error message. If I had to guess, your controller/action that is redirecting/responding you to that error message is not inheriting from the Api::ApplicationController. 


abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

1 thing, https://github.com/driftingruby/051-rails-api-authentication-with-jwt/blob/master/app/controllers/user_token_controller.rb

your controller doesn't include before_action :authenticate_user!

I have this line in my applicationcontroller which is causing issue:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  before_action :authenticate_user!

 end


But i need this line for my web form to be authenticated!





David Kimura PRO said almost 7 years ago on Rails API - Authentication with JWT :

You might need to add 

skip_before_action :authenticate_user!

in the controller that is causing the error message. It may be in the user_token_controller.rb where you would need to add this.


abhinav.x.tiwari said almost 7 years ago on Rails API - Authentication with JWT :

This exposes my application without authentication. for e.g. i am able to see /students page which i was earlier not able to view without authentication.


David Kimura PRO said almost 7 years ago on Rails API - Authentication with JWT :

I'd recommend tracing it back to see where the :authenticate_user! is causing the application to fail.

If i'm stuck on an issue like this, I will sometimes put a debugger log in each controller action with the name of the action. Viewing the logs, you'd be able to see at which point (or the last point) it was able to make its way through before it returned the error. I'm definitely not suggesting to expose the app! That would be bad, but certain controllers need to have unauthenticated access so that it is able to perform the authentication. I'm a big fan of puts debugging. It's similar to rubber duck debugging.

Side note: if you're working on some kind of calculation that is rather difficult and you don't have the tests built yet or is a part of the app where tests will not be created, using a tail | grep can be very handy as well. So in the app, you might have something like

Rails.logger.info "DEBUG:: #{some var}" 

and in your console, do

tail -f log/development.log | grep DEBUG

David Ng said over 3 years ago on Rails API - Authentication with JWT :
Hi, could I know the testing tools, which shows the JSON details and return values,  you are using in the Episodes?


David Kimura PRO said over 3 years ago on Rails API - Authentication with JWT :
  This was using Postman but lately, I've been using Insomnia for testing APIs https://insomnia.rest/


Emma W. Jones said about 2 years ago on Rails API - Authentication with JWT :
Such an amazing and informative blog, It was a real treat to read this blog. We also posted the same blog in detail, if you want to explore more then must visit our blog. Rails API Authentication with JWT (Token Based Authentication)

Login to Comment