Saya mencoba menguji CredentialsController, yang berfungsi dengan baik dalam produksi, menggunakan spesifikasi permintaan RSpec.

Kode

Pengontrol

class CredentialsController < ApplicationController
  before_action :doorkeeper_authorize!
  def me
    render json: current_user
  end
end

(GET /me rute ke CredentialsController#me.)

Minta Spesifikasi

describe 'Credentials', type: :request do
  context 'unauthorized' do
    it "should 401" do
      get '/me'
      expect(response).to have_http_status(:unauthorized)
    end
  end

  context 'authorized' do
    let!(:application) { FactoryBot.create(:application) }
    let!(:user)        { FactoryBot.create(:user) }
    let!(:token)       { FactoryBot.create(:access_token, application: application, resource_owner_id: user.id) }

    it 'succeeds' do
      get '/me', params: {}, headers: {access_token: token.token}
      expect(response).to be_successful
    end
  end
end

Tes yang tidak sah lolos, tetapi tes yang diotorisasi gagal:

diharapkan #<ActionDispatch::TestResponse:0x00007fd339411248 @mon_mutex=#<Thread::Mutex:0x00007fd339410438>, @mo..., @method=nil, @request_method=nil, @remote_ip=nil, @original_fullpath=nil, @fullpath=nil, @ip=nil>>.successful? mengembalikan true, mendapat false

Header menunjukkan masalah dengan token:

0> response.headers['WWW-Authenticate']
=> "Bearer realm=\"Doorkeeper\", error=\"invalid_token\", error_description=\"The access token is invalid\""

token terlihat baik-baik saja bagi saya, meskipun:

0> token
=> #<Doorkeeper::AccessToken id: 7, resource_owner_id: 8, application_id: 7, token: "mnJh2wJeEEDe0G-ukNIZ6oupKQ7StxJqKPssjZTWeAk", refresh_token: nil, expires_in: 7200, revoked_at: nil, created_at: "2020-03-19 20:17:26", scopes: "public", previous_refresh_token: "">

0> token.acceptable?(Doorkeeper.config.default_scopes)
=> true

Pabrik

Token Akses

FactoryBot.define do
  factory :access_token, class: "Doorkeeper::AccessToken" do
    application
    expires_in { 2.hours }
    scopes { "public" }
  end
end

Aplikasi

FactoryBot.define do
  factory :application, class: "Doorkeeper::Application" do
    sequence(:name) { |n| "Project #{n}" }
    sequence(:redirect_uri)  { |n| "https://example#{n}.com" }
  end
end

Pengguna

FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "email#{n}@example.com" }
    password { "test123" }
    password_confirmation { "test123" }
  end
end

Pertanyaan

  • Mengapa saya mendapatkan invalid_token atas permintaan ini?
  • Apakah pabrik Penjaga Pintu saya terlihat benar?
1
Aaron Brager 19 Maret 2020, 23:23

2 jawaban

Jawaban Terbaik

Saya salah melewati token. Dari pada:

get '/me', params: {}, headers: {access_token: token.token}

Saya harus menggunakan:

get '/me', params: {}, headers: { 'Authorization': 'Bearer ' + token.token}
4
Aaron Brager 19 Maret 2020, 20:36

Anda dapat memeriksa cakupan pabrik Token Akses Anda, Ini harus sama dengan default_scopes penginisialisasi

Misalnya

config/initializers/doorkeeper.rb

default_scopes :read

Di bawah, cakupan pabrik Token Akses Anda seharusnya your

factory :access_token, class: "Doorkeeper::AccessToken" do
  sequence(:resource_owner_id) { |n| n }
  application
  expires_in { 2.hours }
  scopes { "read" }
end

Selain itu, jika Anda menemukan status respons: 406 while get '/me'....

Ini berarti format yang diminta (secara default HTML) tidak didukung. Alih-alih '.json' Anda juga dapat mengirim Accept="application/json" di header HTTP.

get '/me', params: {}, headers: { 
  'Authorization': 'Bearer ' + token.token, 
  'Accept': 'application/json'}

Saya menyelesaikan masalah saya dengan solusi ini, mungkin Anda bisa mencobanya.

1
Cody Chang 25 November 2020, 13:35