0.01
Low commit activity in last 3 years
No release in over a year
[Unofficial] Authentication Strategy for Warden to allow Amazon Cognito user sign in and JWT
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.1
>= 12.3.3
~> 3.0
~> 1.2

Runtime

 Project Readme

Warden::Cognito

Build Status

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file lib/warden/cognito. To experiment with that code, run bin/console for an interactive prompt.

TODO: Delete this and the text above, and describe your gem

Installation

Add this line to your application's Gemfile:

gem 'warden-cognito'

And then execute:

$ bundle

Or install it yourself as:

$ gem install warden-cognito

Usage

Configure how the gem maps Cognito users to local ones adding to your initializers the following:

 Warden::Cognito.configure do |config|
    config.user_repository = User
    config.identifying_attribute = 'sub'
    config.after_local_user_not_found = ->(cognito_user, pool_identifier) { User.create(username: cognito_user.username) }
    config.cache =  ActiveSupport::Cache::MemCacheStore.new
    config.user_pools = { default: {region: 'AWS_REGION', pool_id: 'AWS Cognito UserPool Id', client_id: 'AWS Cognito Client Id'} }
end

With Devise

You can know protects endpoints by settings the available strategies in the Warden section of your Device's configuration:

  # config/initializers/devise.rb
  # 
  # /***/
  config.warden do |manager|
    manager.default_strategies(scope: :user).unshift :cognito_auth
    manager.default_strategies(scope: :user).unshift :cognito_jwt
    # /***/
  end

User Repository

The user repository will be used to look for an entity to mark as authenticated, it must implement the following:

  • find_by_cognito_username that should return the user identified by the given username or nil (receives as second param the pool_identifier)
  • find_by_cognito_attribute that should return the user identified by the given Cognito User attribute (config.identifying_attribute) or nil (receives as second param the pool_identifier)

User Model

The user model must expose a message cognito_id that returns the identifying_attribute for the given user.

after_local_user_not_found Callback

A callback triggered whenever the user correctly authenticated on Cognito but no local user exists (receives the full cognito user, and the pool_identifier as second parameter).

Cache

The cache used to store the AWS Json Web Keys as well as the mapping between local and remote identifiers. Defaults to ActiveSupport::Cache::NullStore

Testing

The TestHelpers module is here to help testing code using this gem to validate tokens and authenticate users:

Create a module and make sure it is loaded as part of the support files of your rspec configuration:

module Helpers
  module JWT
    def self.included(base)
      base.class_eval do
        Warden::Cognito::TestHelpers.setup
      end
    end

    def auth_headers_for_user(user, pool_identifier, headers = {})
      Warden::Cognito::TestHelpers.auth_headers(headers, user, pool_identifier)
    end

    def jwt_for_user(user, pool_identifier)
      auth_headers_for_user(user, pool_identifier)[:Authorization].split[1]
    end
  end
end

Include this module in the relevant test types:

RSpec.configure do |config|
  # /***/
  config.include Helpers::JWT, type: :request
end

You can now generate tokens for your users in your tests, for instance:

let(:user) { create(:user) } # Your users needs to be available through the UserRepository you defined
let(:headers) { auth_headers_for_user(user) }
let(:token) { jwt_for_user(user) }

API

This gem also exposes classes that you can use to validate tokens and/or fetch a user from a given token:

token = 'The token a user passed along in a request'
token_decoder = TokenDecoder.new(token, nil) # Pass nil as pool_identifier to loop over all the configured pools and automatically bind the right one [Based on the issuer]

# Is the token valid ?
token_decoder.validate!

# What's in this token ?
token_decoder.decoded_token

# What's the phone_number attribute of the user identified by this token ?
token_decoder.user_attribute('phone_number')

# Who is the local user associated with this token
user = LocalUserMapper.find(token_decoder)
# or 
user = LocalUserMapper.find_by_token(token)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

With Docker

There are docker and docker-compose files configured to create a development environment for this gem. So, if you use Docker you only need to run:

docker-compose up -d

An then, for example:

docker-compose exec app rspec

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/barkibu/warden-cognito.

License

The gem is available as open source under the terms of the MIT License.