【问题标题】:How to skip authentication when testing rails controllers in rspec?在 rspec 中测试 Rails 控制器时如何跳过身份验证?
【发布时间】:2019-11-09 09:12:22
【问题描述】:

我有一个与 auth0 服务集成的 rails 后端 api 应用程序,它仅验证从前端应用程序接收到的 auth_token 的有效性。在保护所有后端 api 端点之后,我的所有测试都失败了,结果是“未经过身份验证”,这就是它应该的样子。但是我无法弄清楚如何通过身份验证并且不需要它进行 rspec 测试。这是我的课程:

projects_controller_spec.rb

require "rails_helper"

RSpec.describe Api::V1::ProjectsController, :type => :controller do
  describe 'GET /api/v1/organizations/1/projects' do
    let!(:organization) { create(:organization_with_projects) }
    before { get :index, params: { organization_id: organization } }

    context 'when authorized' do
      it 'should return JSON objects' do
        expect(json['projects'].count).to equal(3)
      end

      it { expect(response).to have_http_status(:ok) }
      it { expect(response.content_type).to include('application/json') }
    end

  describe 'POST /api/v1/organizations/1/projects' do
    let!(:organization) { create(:organization) }
    let(:project) { organization.projects.first }
    before { post :create, params: { organization_id: organization, project: attributes_for(:project) } }

    context 'when authorized' do
      it { expect(response).to have_http_status(:created) }
      it { expect(response.content_type).to include("application/json") }
      it { expect(json).to eq(serialized(project)) }
    end
  end
end

application_controller.rb

class ApplicationController < ActionController::API
  include Pundit
  include Secured

  rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found

  private
  def record_not_found(error)
    render json: { error: error.message }, status: :not_found
  end
end

关注/secured.rb

module Secured
  extend ActiveSupport::Concern

  included do
    before_action :authenticate_request!
  end

  private

  def authenticate_request!
    # Create user if not existing
    pundit_user

    auth_token
  rescue JWT::VerificationError, JWT::DecodeError
    render json: { errors: ['Not Authenticated'] }, status: :unauthorized
  end

  def http_token
    if request.headers['Authorization'].present?
      request.headers['Authorization'].split(' ').last
    end
  end

  def auth_token
    JsonWebToken.verify(http_token)
  end

  def pundit_user
    User.create_from_token_payload({token: auth_token[0], organization_id: 
request.parameters['organization_id']})
  end

end

lib/json_web_token.rb

require 'net/http'
require 'uri'

class JsonWebToken
  def self.verify(token)
    JWT.decode(token, nil,
           true, # Verify the signature of this token
           algorithm: 'RS256',
           iss: 'https://xxx.auth0.com/',
           verify_iss: true,
           aud: Rails.application.secrets.auth0_api_audience,
           verify_aud: true) do |header|
      jwks_hash[header['kid']]
    end
  end

  def self.jwks_hash
    jwks_raw = Net::HTTP.get URI("https://xxx.auth0.com/.well-known/jwks.json")
     jwks_keys = Array(JSON.parse(jwks_raw)['keys'])
    Hash[
        jwks_keys
            .map do |k|
          [
              k['kid'],
              OpenSSL::X509::Certificate.new(
                  Base64.decode64(k['x5c'].first)
              ).public_key
          ]
        end
    ]
  end
end

【问题讨论】:

标签: ruby-on-rails authentication rspec auth0 rails-api


【解决方案1】:

看起来我通过在每个控制器规范文件中添加以下行找到了解决方案:

before { allow(controller).to receive(:authenticate_request!).and_return(true) }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多