1

I have a rails backend api application integrated with auth0 service that only verifies validity of auth_token received from frontend application. After securing all backend api endpoints all my tests fail with a result "Not Authenticated", which is how it should be. However I cannot figure out how to get through the authentication and to not require it for rspec tests. Here are my classes:

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

concerns/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
1

1 Answer 1

1

It looks like I found a solution by adding the following line into every controller spec file:

before { allow(controller).to receive(:authenticate_request!).and_return(true) }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.