I'm building authentication on a Rails 5 API, and I'm having issues with the logout piece. I'm hitting the /logout
route and receive a 500 error reading NoMethodError: undefined method 'invalidate_token' for nil:NilClass>
, and it then references my sessions_controller. My sessions_controller references an invalidate_token
method in the logout method that's declared in the Users model, and I'm stumped as to why the error is undefined in the controller when I have defined it in the model.
sessions_controller:
class SessionsController < ApiController
skip_before_action :require_login, only: [:create], raise: false
def create
if (user = User.validate_login(params[:username], params[:password]))
allow_token_to_be_used_only_once_for(user)
send_token_for_valid_login_of(user)
else
render_unauthorized('Error creating the session with provided credentials')
end
end
def destroy
logout
head :ok
end
private
def send_token_for_valid_login_of(user)
render json: { token: user.auth_token }
end
def allow_token_to_be_used_only_once_for(user)
user.regenerate_auth_token
end
def logout
@current_user.invalidate_token
end
end
Users model
class User < ApplicationRecord
# validate unique username and email
validates_uniqueness_of :username, :email
has_secure_password
has_secure_token :auth_token
# clear token value, used to logout
def invalidate_token
self.update_columns(auth_token: nil)
end
def self.validate_login(username, password)
user = User.find_by(username: username)
if user && user.authenticate(password)
user
end
end
end
API Controller:
class ApiController < ApplicationController
def require_login
authenticate_token || render_unauthorized('Access Denied: Unauthorized Access')
end
def current_user
@current_user ||= authenticate_token
end
protected
def render_unauthorized(message)
errors = { errors: [detail: message] }
render json: errors, status: :unauthorized
end
private
def authenticate_token
authenticate_with_http_token do |token|
User.find_by(auth_token: token)
end
end
end
Ideally, this should get past the logout method so it can render a 200 and actually invalidate the logged in users token.
You are doing a find_by
when fetching the user record in authenticate_token
. If no record is found, nil
is returned.
Either you got bad data, or your header is not valid.