Skip to content

Instantly share code, notes, and snippets.

@stratigos
Last active August 28, 2020 17:23
Show Gist options
  • Save stratigos/88ff670930369802d187fe478d1d6a59 to your computer and use it in GitHub Desktop.
Save stratigos/88ff670930369802d187fe478d1d6a59 to your computer and use it in GitHub Desktop.
RSpec Helper for Token-based Authentication Sign-In
# Helpers to assist with the `devise_token_auth` security features, such as
# generation of new authentication tokens for each request.
# @see [devise_token_auth Github issue](https://github.com/lynndylanhurley/devise_token_auth/issues/75)
module RequestSpecHelper::ApiAuthHelper
module Extensions
# Helper method for authenticating a User for each Request type spec.
# Use `devise_token_auth` callback to generate an authentication token
# for each request.
# Call this on a created User at the beginning of a `describe` or `context`
# block where authentication is required for each assertion.
# Note that this methodology creates valid tokens for a `devise` resource
# namespace, i.e., a `:user` or similar symbol. This technique does not
# require the actual creation of a User record, which will significantly
# improve the speed of Request specs (or Controller specs, if youre into
# that sort of pain and suffering :] ). Simply build a valid resource
# (i.e., a User), and pass the symbol into this method.
def api_sign_in(devise_token_auth_resource)
let(:api_auth_helpers_auth_token) {
self.public_send(devise_token_auth_resource).create_new_auth_token
}
end
end
module Includables
# Request spec helper methods
HTTP_HELPERS_TO_OVERRIDE = [:get, :post, :patch, :put, :delete].freeze
# Insert auth headers into the args for each Request spec helper.
HTTP_HELPERS_TO_OVERRIDE.each do |helper|
define_method(helper) do |path, **args|
add_auth_headers(args)
args == {} ? super(path) : super(path, **args)
end
end
private
# Add authentication headers for the current User, if one is set
def add_auth_headers(args)
return unless defined? api_auth_helpers_auth_token
args[:headers] ||= {}
args[:headers].merge!(api_auth_helpers_auth_token)
end
end
end
# Include the helper in your `spec_helper.rb` or if using Rails, the `rails_helper.rb` file as follows:
# config code ...
config.include RequestSpecHelper::ApiAuthHelper::Includables, type: :request
config.extend RequestSpecHelper::ApiAuthHelper::Extensions, type: :request
# more config...
@stratigos
Copy link
Author

stratigos commented Apr 19, 2018

Use this helper with devise_token_auth for spec'ing any :request or other application feature where token based authentication is required.

πŸ”’ πŸ”‘

This essentially stubs the login process, and shoves valid bearer-token authentication headers into a request, to allow access to resources/paths which require prior authentication. E.g., user signs in, browses a list of resources, selects a resource, edits a resource, and navigates elsewhere, each request/response requiring the user be authenticated.

@stratigos
Copy link
Author

stratigos commented Aug 28, 2020

πŸ“ Also worth noting: this is one of the rare occasions I believe a let statement is appropriate. I would not let one appear in an actual test. I want to avoid having a mystery guest in my tests, and like to keep all test resources local to the test itself.

πŸ“– You can read more on why avoiding let statements adds value to your tests, here: Lets Not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment