2017-12-30 91 views
2

リクエスト仕様の認証に問題があります。各HTTP要求のヘッダに有効な認証トークンをどのように渡すのですか?私のアプローチは正しいか?ここ各http RSpecテストヘッダーに認証トークンを追加する方法

tweets_request_spec.rb

require 'rails_helper' 

RSpec.describe 'Tweets API', type: :request do 
    before do 
    @tweets = create_list(:tweet, 10) 
    @tweet = @tweets.first 
    end 

    describe 'GET /tweets' do 
    before { get '/tweets', { "Authorization": *some sort of token*} } 

    it "returns tweets" do 
     expect(json).to_not be_empty 
     expect(json).to eq(10) 
    end 

    it "is a successful http request" do 
     expect(response).to have_http_response(200) 
    end 
    end 
end 

は私の認証制御するためのコード、ならびにHTTPヘッダーに渡される認証トークンを生成及び復号化を支援モジュールです。

authentication_controller.rb

class AuthenticationController < ApplicationController 
    skip_before_action :authenticate_request 

    def authenticate 
    command = AuthenticateUser.call(params[:email], params[:password]) 

    if command.success? 
     render json: { auth_token: command.result } 
    else 
     render json: { error: command.errors }, status: :authorized 
    end 
    end 
end 

authorize_api_request.rb

class AuthorizeApiRequest 
    prepend SimpleCommand 

    def initialize(headers = {}) 
    @headers = headers 
    end 

    def call 
    user 
    end 

    private 

    attr_reader :headers 

    def user 
    @user ||= User.find(decoded_auth_token[:user_id]) if decoded_auth_token 
    @user ||= errors.add(:token, 'Invalid token') && nil 
    end 

    #decode the auth token and retrieve the user id 
    def decoded_auth_token 
    @decoded_auth_token ||= JSONWebToken.decode(http_auth_header) 
    end 

    #retrieve auth token from header 
    def http_auth_header 
    if headers['Authorization'].present? 
     return headers['Authorization'].split(' ').last 
    else 
     errors.add(:token, 'Missing token') 
    end 
    end 
end 
+0

であざけるについての詳細を読むことができますが、私は、ユーザー認証を追加するには、このリンクをたどってきたあなたは、この –

+0

を構築するために使用されているリンクが含まれます。https://www.pluralsight ruby-on-rails/token-based-with-ruby-on-rails-5-api – Jas1997

+1

おかげで幸せな新年 –

答えて

3

the official pluralsight page

エンドポイントからコピーされたいくつかのコードを抽出し、認証するためには、config/routes.rb

post 'authenticate', to: 'authentication#authenticate' 
01であります

このアクションを実行します。正しく認証すると、アクションはトークンを返します。

def authenticate 
    command = AuthenticateUser.call(params[:email], params[:password]) 
    if command.success? 
     render json: { auth_token: command.result } 
    else 
     render json: { error: command.errors }, status: :unauthorized 
    end 
end 

rspecには2つのオプションがあります。このメソッドをモックするか、ファクトリを作成します。

token based認証の概念は、一度要求

$ curl -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"123123123"}' http://localhost:3000/authenticate 

が与えるユーザーのみに予約

ユーザーがトークンを持つことになります認証され、このトークンを提供することで、彼は機能にアクセスできるようになるということですトークンに応答して

{"auth_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA"} 

トークンにヘッダーを含めると、要求によってaut horizationエラー

$ curl -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA" http://localhost:3000/items [] 

ので、あなたのGET要求を行う前に、auth_tokenの正しい値を提供するために、どのようにリクエストヘッダにトークン

request.headers['Authorization'] = auth_token 
get :your_action 

が含まれていますか?

それはbeforeaction

#app/controllers/application_controller.rb 
class ApplicationController < ActionController::API 
before_action :authenticate_request 
    attr_reader :current_user 

    private 

    def authenticate_request 
    @current_user = AuthorizeApiRequest.call(request.headers).result 
    render json: { error: 'Not Authorized' }, status: 401 unless @current_user 
    end 
end 

と呼ばれているとしてあなたは私はあなたが認証エラーを受信しないようにするには、このコード行を模擬すべきであると信じて、ApplicationController方法authenticate_requestmockにする必要があります。私はbefore_actionを使用することにより

を引用

@current_user = AuthorizeApiRequest.call(request.headers).result 

ので、私はスペックを書きますが、この

user = FactoryBot.create(:user) 
allow(AuthorizeApiRequest).to receive(:call).and_return(user) 
# request.headers['Authorization'] = auth_token # this is not required anymore the authentication is skipped 
get :your_action 

ようsomethind、サーバーは組み込みのオブジェクトのプロパティの要求を使用して(request headersを渡します.headers)をAuthorizeApiRequestに変更します。 AuthorizeApiRequest.call(request.headers)resultを呼び出すことはSimpleCommandモジュールから来ており、ここではattr_reader :resultと定義されています。要求結果は@current_userに返され、ApplicationControllerを継承するすべてのコントローラで使用できるようになります。

あなたは

https://github.com/rspec/rspec-mocks

関連する問題