Skip to content

Instantly share code, notes, and snippets.

@stratigos
Last active August 28, 2020 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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