Возвращать токен JWT, когда пользователь подписывается на рельсы - PullRequest
0 голосов
/ 28 июня 2018

Возникла проблема с получением токена JWT с использованием devise gem и devise-jwt gem. Вот так выглядит мое подтверждение.

devise.rb

  Devise.setup do |config|

    config.jwt do |jwt|
      jwt.secret =  SECRETS.devise_jwt_secret_key
      jwt.dispatch_requests = [ ['POST', %r{^/authentication_tokens/create$}] ]
    end
end 

user.rb

class User < ApplicationRecord

    devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable, :validatable,
           :jwt_authenticatable, jwt_revocation_strategy: Devise::JWT::RevocationStrategies::Null

  end

authentication_tokens_controller.rb

class Api::V1::AuthenticationTokensController < Devise::SessionsController
  include Devise::Controllers::Helpers
  skip_before_action :verify_authenticity_token 

  prepend_before_action :require_no_authentication, only: [:create]

  before_action :rewrite_param_names, only: [:create]

  def new
    render json: { response: "Authentication required" }, status: 401
  end

  def create
    self.resource = warden.authenticate!(auth_options)
    sign_in(resource_name, resource)
    yield resource if block_given?
     render json: {success: true, jwt: current_token, response: "Authentication successful" }
  end

  private

  def rewrite_param_names
    request.params[:user] = {email: request.params[:email], password: request.params[:password]}
  end

  def current_token
    request.env['warden-jwt_auth.token']
  end

end

routes.rb

   get 'home#secret'
   devise_for :users
   resources :tasks
   #other routes for the website removed for brevity

  namespace :api, defaults: { format: :json } do
    namespace :v1 do
      resources :users
      devise_scope :user do
        post '/authentication_tokens/create', to: "authentication_tokens#create"
      end
    end
  end

По какой-то причине request.env['warden-jwt_auth.token'] возвращает null все время, однако пользователь проходит проверку подлинности. Что-нибудь, что мне нужно добавить, чтобы получить токен JWT, когда пользователь входит в систему?

Обновление - маршруты и пространства имен

После нескольких дней отладки я считаю, что нашел источник моей проблемы. Мое приложение имеет интерфейс, который использует нормальные маршруты. Код выше не работает, однако, если я делаю что-то вроде кода ниже. Все хорошо.

  scope :api, defaults: {format: :json} do
    devise_for :users, controllers: {sessions: 'v1/authentication_tokens'}
  end

Существует ли способ присвоения имен API devise_for для меня, даже если он был использован выше для веб-сайта?

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Вам просто нужно сделать маршрут RESTful.

routes.rb

post '/authentication_tokens', to: "authentication_tokens#create"

devise.rb

config.jwt do |jwt|
  jwt.secret =  SECRETS.devise_jwt_secret_key
  jwt.dispatch_requests = [ ['POST', %r{^/authentication_tokens$}] ]
end
0 голосов
/ 11 августа 2018

обновление jwt.dispatch_requests с полным путем, после этого перезапустить рельсы, у меня работает.

devise.rb

config.jwt do |jwt|
  jwt.secret = "secret"
  jwt.dispatch_requests = [ ['POST', %r{^/api/v1/authentication_tokens/create$}] ]
  jwt.expiration_time = 1.day.to_i
end

0 голосов
/ 02 июля 2018

Я кратко рассмотрел вашу проблему и, возможно, это неправильно, но вы можете попробовать:

глядя на следующие строки

def create
  self.resource = warden.authenticate!(auth_options)
end

def current_token
  request.env['warden-jwt_auth.token']
end

Если вы говорите, что пользователь проходит проверку подлинности даже с помощью nil, возвращенного методом current_token, это означает, что jwt проходит правильно, но ваш способ его получения неверен.

Попробуйте отладить строку self.resource = warden.authenticate!(auth_options) и посмотрите, что находится внутри auth_options, возможно, вы можете взять оттуда JWT или просто пытаетесь получить warden-jwt_auth.token неверным способом. Попробуйте также отладить эту строку и посмотрите, стоит ли вам брать «warden-jwt_auth.token» из request.headers["warden-jwt_auth.token"] или что-то в этом роде. Просто распечатайте полный ответ на ваш запрос и выполните поиск по нужному заголовку.

Надеюсь, это поможет!

...