[BUG] Authorization Bearer header not passed to controller
xkraty opened this issue · 12 comments
Describe the bug
My test fail becuase the Authorization
header with the Bearer <token>
is not passed to the controller unless i set the parameter
manually.
Everything works fine in the Swagger UI.
Steps to Test or Reproduce
Spec file
# frozen_string_literal: true
require 'swagger_helper'
describe 'Token info' do
path '/api/auth/tokens/info' do
# rubocop:disable RSpec/VariableName
get 'Info' do
tags :tokens
# Without the parameter the test fail
# parameter name: :Authorization, in: :header, type: :string
security [bearer: []]
produces 'application/json'
response '200', 'Success' do
let('Authorization') { "Bearer #{create(:devise_api_token).access_token}" }
run_test!
end
end
# rubocop:enable RSpec/VariableName
end
end
Generated swagger.yaml
---
openapi: 3.0.3
info:
title: API V1
version: v1
paths:
"/api/auth/tokens/info":
get:
summary: Info
tags:
- tokens
parameters:
- name: Authorization
in: header
schema:
type: string
security:
- bearer: []
responses:
'200':
description: Success
content:
application/json:
examples:
Success:
value:
id: cdd5f039-3f61-4f41-a09f-2b9aa5de2c07
email: elene@boyer.example
- name: tokens
description: Tokens generations
security:
- bearer: []
components:
securitySchemes:
bearer:
type: http
scheme: bearer
bearerFormat: JWT
Expected behavior
Expect request.headers['Authorization'] to be set with Bearer
so test would pass.
Additional context
I'm using devise
with devise-api
not sure this can be helpful.
I've been reading all the related issues I've found such us #74 #418 #377 but nothing seems to be fixing my problem.
Dependency versions
The version of are you using for:
- Rswag: 2.9
- RSpec: 6.0
- Rails: 7.0.5
- Ruby: 3.2.2
Relates to which version of OAS (OpenAPI Specification)
- OAS2
- OAS3
- OAS3.1
Thanks in advance
xKraty
Could you try to use in your swag_helper:
security: [ { bearerAuth: [] } ]
Could you try to use in your swag_helper:
security: [ { bearerAuth: [] } ]
Hello thanks for your answer,
you mean trying to rename bearer
to bearerAuth
, I've tried and it doesn't work, also my swagger output is correct, with that syntax, it's just failing the test
The other difference between my code and your code is that I am using OpenAPI 3.0.1
That's my swag_helper:
config.swagger_docs = { 'v1/swagger.yaml' => { openapi: '3.0.1', info: { title: 'API V1', version: 'v1' }, paths: {}, servers: [ { url: 'http://{defaultHost}', variables: { defaultHost: { default: 'localhost:3000/api/v1' } } } ], components: { securitySchemes: { bearerAuth: { type: :http, scheme: :bearer, bearerFormat: JWT } } }, security: [ { bearerAuth: [] } ] } }
Even with 3.0.1 test still fails, Swagger UI it would work fine
@xkraty did you ever find a solution for this?
@dantonyblanco nope, I'm still passing the header params and explained to devs to ignore it into swagger
I think the parameter is the only thing that worked for me although it wasn't really intuitive intially.
Here is my test in case it helps anyone:
# frozen_string_literal: true
require "swagger_helper"
RSpec.describe "api/v1/onboardings", type: :request do
before do
post auth_login_index_path
@token = response.parsed_body["token"]
end
path("/api/v1/onboardings") do
let!(:Authorization) { "Bearer #{@token}" }
get("list onboardings") do
security [Bearer: []]
tags "Onboardings"
produces "application/json"
parameter name: :status, in: :query, type: :string, enum: %w[active finished], required: false,
description: "Filter onboardings by status"
parameter name: :Authorization, in: :header, type: :string, required: true
response(200, "successful") do
let(:status) { "active" }
schema type: :array,
items: {
type: :object,
properties: {
id: { type: :integer, example: 1 },
description: { type: :string, nullable: true, example: "Onboarding Description" },
end_date: { type: :string, format: "date-time", nullable: true, example: "2023-10-10T17:00:00Z" },
learning: { type: :string, nullable: true, example: "Learning Content" },
start_date: { type: :string, format: "date-time", example: "2023-10-05T09:00:00Z" },
title: { type: :string, example: "Onboarding Title" },
created_at: { type: :string, format: "date-time", example: "2023-10-04T20:48:46.929Z" },
updated_at: { type: :string, format: "date-time", example: "2023-10-05T09:00:00Z" },
progress: { type: :integer, example: 50 },
status: { type: :string, enum: %w[active finished], example: "finished" },
user_id: { type: :integer, example: 1 },
},
}
run_test!
end
response(400, "bad request") do
let(:status) { "invalid_status" }
schema type: :object,
properties: {
error: {
type: :string,
example: "Invalid status parameter. Allowed values are active, finished",
},
}
run_test!
end
end
end
end
@dantonyblanco that's the workaround I applied but AFAIK you should not add it. I've tried to enable the dry run, and the documentation get generated correctly without it, problem is rspec fail without.
- parameter name: :Authorization, in: :header, type: :string, required: true
For those who's experimenting this issue, have you defined correctly the securitySchemes
within config.swagger_docs
?
This seems to be working on my project with this configuration:
{
openapi: '3.0.1',
...,
components: {
securitySchemes: {
bearer_auth: {
type: :http,
scheme: :bearer
}
}
} ,
...
}
Then Use it with something like this:
get 'Returns the current logged in user' do
tags 'Users'
security [bearer_auth: []]
response '200', 'user detail' do
let(:Authorization) { "Bearer #{access_token.token}" }
run_test!
end
end
@Ksm125 do you have dry run disabled?
RSpec.configure do |config|
config.rswag_dry_run = false
end
config.rswag_dry_run = false
@xkraty well, i didn't add this line on my configuration, so i'm using the default configuration (which if i'm not mistaken true
)
and i run this command when i want to generate the doc:
RAILS_ENV=test RSWAG_DRY_RUN=0 rails rswag
here is my sample config
require 'rails_helper'
require_relative 'swagger_schema/version1'
RSpec.configure do |config|
config.swagger_root = Rails.root.join('swagger').to_s
config.swagger_strict_schema_validation = true
config.swagger_docs = {...}
config.swagger_format = :json
end