I have an API that accepts a JWT bearer token. Expected results:
token description | status | message, if any |
---|---|---|
valid token | 200 | |
corrupt token | 400 | Your JWT appears to be invalid |
no token | 401 | Did not receive auth token |
valid but unauth | 401 | You can't do that |
My thinking is that in the past, I have worked on APIs where I wasn't sure if my auth was even getting through... am I using the wrong key for this token? So I let the user know "I got your token, but it's not right."
Here's the issue: Using rswag, I can't figure out how to test both sending an auth token and NOT sending an auth token.
# frozen_string_literal: true
require 'rails_helper'
RSpec.configure do |config|
# Specify a root folder where Swagger JSON files are generated
# NOTE: If you're using the rswag-api to serve API descriptions, you'll need
# to ensure that it's configured to serve Swagger from the same folder
config.swagger_root = Rails.root.join('swagger').to_s
# Define one or more Swagger documents and provide global metadata for each one
# When you run the 'rswag:specs:swaggerize' rake task, the complete Swagger will
# be generated at the provided relative path under swagger_root
# By default, the operations defined in spec files are added to the first
# document below. You can override this behavior by adding a swagger_doc tag to the
# the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
config.swagger_docs = {
'v1/swagger.yaml' => {
openapi: '3.0.1',
info: {
title: 'My API',
version: 'v1'
},
paths: {},
servers: [
{
url: 'https://{defaultHost}',
variables: {
defaultHost: {
default: 'www.example.com'
}
}
}
],
components: {
securitySchemes: {
AuthToken: {
type: :http, scheme: :bearer, bearerFormat: JWT
}
}
},
security: [ { AuthToken: [] } ]
}
}
# Specify the format of the output Swagger file when running 'rswag:specs:swaggerize'.
# The swagger_docs configuration option has the filename including format in
# the key, this may want to be changed to avoid putting yaml in json files.
# Defaults to json. Accepts ':json' and ':yaml'.
config.swagger_format = :yaml
end
the test:
RSpec.describe 'api/v1/unicorns', type: :request do
path '/unicorns.json' do
let(:user) { create(:perceptyx_owner) }
let(:account) { create(:account, owners: [user]) }
get 'retrieves a list of accessible unicorns' do
tags 'unicorns'
produces 'application/vnd.api+json'
security [ {AuthToken: [], NoAuth: []} ]
response '200', 'properly authenticated request' do
let(:Authorization) { JWT.encode({ auth: { user_id: user.pyx_user_id } }, nil, 'none') }
run_test!
end
response '400', 'malformatted auth token' do
let(:Authorization) { 'AAABBBCCCDDDDEEE-invalid' }
run_test!
end
response '401', 'no authentication' do
# it's not clear how you would run a test that did
# not include a bearer token header -- this tests results
# in "undefined method `Authorization'"
run_test!
end
end
end
end
I thought about using another securityScheme list here setting up a secondary authorization like ApiKeyAuth, which my app would ignore. But when I try to set security in the test, rather than as a default, it seems to apply to every test within the "path", not the individual "response".
I also tried setting "Authorization" to nil... but obviously that sent a key with no value. Which isn't the same thing.
Can this be done? How? I haven't gotten to the step of seeing this in the documentation yet but any clues about what I can do to set myself up for success there would be appreciated -- though not part of this question. :)
Try setting Authorization to nil.