Git Product home page Git Product logo

grape_token_auth's Introduction

GrapeTokenAuth

Gem Version Code Climate GPA Test Coverage Circle CI

GrapeTokenAuth is a token authentication solution for grape. It is compatible with ng-token-auth (for angular) and j-toker (for jQuery), and is meant as a grape (rather than rails) version of devise_token_auth. As such, this project is built entirely upon grape and warden and avoids the need for rails. However, it has built in compatibility for devise if you are looking to mount a grape app within your rails app. Finally, If you are placing a grape app within an existing rails + devise_token_auth app you might be interested in grape_devise_token_auth.

This gem is a port of devise_token-auth written by Lyann Dylan Hurley and the team of contributors. That team does great work and the conceptual section on that gem is highly recommended reading.

Philosophy

This gem aims to maintain a small direct dependency footprint. As such, it currently depends only on grape, warden, mail, and bcrypt. In the future, the hope is to break this gem up into modules so that you can be even more selective on the code and dependencies that are included.

Installation

Add this line to your application's Gemfile:

gem 'grape_token_auth'

And then execute:

$ bundle

Or install it yourself as:

$ gem install grape_token_auth

Quick-Start Setup

This is the minimum setup to get GrapeTokenAuth running. For a more detailed walkthrough, you can refer to this blog post, the demo repo, and the wiki. Setup has 4 parts:

  1. Middleware Setup
  2. Model/ORM setup
  3. Grape Token Auth configuration
  4. Mounting Authentication APIs

###Middleware setup

GrapeTokenAuth requires setting up warden middleware in order to function properly. In a simple rack environment this is usually as easy as adding the following to the config.ru:

# config.ru

require 'warden'
require 'grape_token_auth'

## Setup session middleware (E.g. Rack::Session::Cookie)

GrapeTokenAuth.setup_warden!(self)

run YourGrapeAPI

In rails, you will need to setup warden as so:

# application.rb

config.middleware.insert_after ActionDispatch::Flash, Warden::Manager do |manager|
  manager.failure_app = GrapeTokenAuth::UnauthorizedMiddleware
  manager.default_scope = :user
end

Model/ORM setup

Include the module for your ORM within the model classes. At the moment, only ActiveRecord is supported but other ORMs are planned. Your model must contain a text-type field called tokens.

####ActiveRecord

class User < ActiveRecord::Base
  include GrapeTokenAuth::ActiveRecord::TokenAuth
end

Grape Token Auth Configuration

GTA does not make guesses about what scopes and user classes you are using, you must define them before the Grape API is loaded. In rails this could be in an initializer, for a rack app run the setup before the API class definitions.

To define mappings, the scope is the key of the mapping hash, and the value is the model to which the scope is mapped. For the above user class this would be:

GrapeTokenAuth.setup! do |config|
	config.mappings = { user: User }
	config.secret   = 'THIS MUST BE A LONG HEX STRING'
end

Note on Secret: generate a unique secret using rake secret in a rails app or via these directions.

In addition, if you are using the mail features in grape_token_auth you will want to set the appropriate configuration options. See the mail wiki page for more information.

Mounting authentication APIs

In order to use a given feature of GrapeTokenAuth, the corresponding API must be mounted. This can be accomplished in your grape app by first including the mount helpers:

class TestApp < Grape::API
  format :json

  include GrapeTokenAuth::MountHelpers

  #...
end

Then you can use the individual helpers to mount a given GTA API:

class TestApp < Grape::API
  # ...

  mount_registration(to: '/auth', for: :user)
  mount_sessions(to: '/auth', for: :user)
  mount_token_validation(to: '/auth', for: :user)
  mount_confirmation(to: '/auth', for: :user)

  # ...
end

The first line indicates the GrapeTokenAuth registration API will be mounted to '/auth' relative to the location where the TestApp is mounted. Presuming that TestApp is being run at root, registration endpoints will be at /auth. Also, we are defining the scope that these endpoints pertain to (user). Important the scope must be defined in the configuration step.

A table of the various APIs and their associated helpers follows:

API helper description
Registration mount_registration used to register new 'email' type users
Session mount_sessions used to login 'email' type users
Confirmation mount_confirmation used to confirm 'email' users new emails
TokenValidation mount_token_validation used to tokens for all type users
OmniAuth mount_omniauth used to register/login omniauth users, requires the OmniAuthCallback API
OmniAuthCallback mount_omniauth_callbacks used to register/login omniauth users, requires the OmniAuth API
PasswordReset mount_password_reset used to issue password resets for forgotten passwords

Usage

First, include the TokenAuthentication module in the grape API you want to enforce authentication on.

class TestApp < Grape::API
  # ...

  include GrapeTokenAuth::TokenAuthentication

  # ...
end

Enforcing authentication on an endpoint

In any grape endpoint you can call authenticate_{SCOPE}! to enforce authentication on that endpoint. For instance, the following:

get '/' do
  authenticate_user!
  present Post.all
end

will authenticate against the :user scope when trying to GET the / route.

Enforcing authentication on all endpoints

Alternatively, if you want to protect all of the endpoints in an API, place the authentication call in a before_filter, like so:

class TestApp < Grape::API
  before do
    :authenticate_user!
  end
end

Development

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

To run tests, you will need postgres to be setup and configured correctly. Run rake db:setup to create the test db and rake db:reset to reset the db.

Contributing

See CONTRIBUTING.md

grape_token_auth's People

Contributors

mcordell avatar npras avatar stephanvane avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

grape_token_auth's Issues

Mailer doesnt provide token expiration for :reset_password

The PasswordApi should add the expiry params in the query string when performing a send_reset_password_instructions.

The send_password_instructions should use resource.build_auth_url
Then, the query string would be properly built.

Warden and session handling

Need to properly handle warden users. Likely the resources need to be changed to not store. This of course raises the question of warden necessity or allowing warden/devise integration to be optional.

DTA has recently disable devise integration by default. Which was actually causing bugs in grape_devise_token_auth. See lynndylanhurley/devise_token_auth@ee7e3f6

Logically, at minimum, devise integration support should be disabled by default, per DTA.

Headers don't contain access-token

curl -H "Content-Type: application/json" -X POST localhost:3000/sign_in -d '{"email":"[email protected]","password":"password"}' -v

Results to

Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST /api/v1/sign_in HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 54
>
* upload completely sent off: 54 out of 54 bytes
< HTTP/1.1 200 OK
< Date: Mon, 30 Jan 2017 14:05:56 GMT
< Connection: close
< Content-Type: application/json
< Content-Length: 962
< ETag: W/"ed93fa39d3ffaddff1c365b7f83001e1"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: 6c5351f3-e7fc-44b8-bac0-0a70048a9ac3
< X-Runtime: 0.024704
<
* Closing connection 0
{"data":{"id":7, .....}}

Expected:

Response headers contain access-token

Actual result:

Response headers don't contain them.

Files

# api_engine.rb
    include GrapeTokenAuth::MountHelpers
    mount_sessions(for: :user)
#config/routes
  mount API::Engine => '/'
# config/application.rb
    config.after_initialize do
      GrapeTokenAuth.setup! do |config|
        config.change_headers_on_each_request = false
        config.mappings = { user: User }
        config.secret   =  Rails.application.secrets.grape_token_secret
      end
    end
# config/initializers/devise.rb
  config.warden do |manager|
    manager.failure_app = GrapeTokenAuth::UnauthorizedMiddleware
    manager.default_scope = :user
  end
# app/models/user.rb
  include GrapeTokenAuth::ActiveRecord::TokenAuth
  devise :invitable, :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable, :validatable

In my Gemfile.lock:

grape (0.17.0)
grape_token_auth (0.1.1)
devise (~> 4.2)
rails (= 4.2.7.1)

Ruby version: ruby 2.3.1p112

Multiple calls to db on authenticate

it seems like authenticate_user! is making multiple queries up to 5 times for the current user, seems a little bit un necessary, causing some response time increases for me, will dig though the code base when i wake up in the morning.

but anyone noticing this?

Override API responses

Hi! I'm using Grape + Grape Token Auth inside an Rails app.

I also use active_model_serializers gem and have an serializer for my User model. API doesn't use the serializer and when I sign in via API I get response containing all user's attributes.

I think there should be a way to override this behavior.

Requiring gem pollute routes with all possible endpoints bound to root

This is done by code like this for every strategy @ a time gem is loading:

https://github.com/mcordell/grape_token_auth/blob/master/lib/grape_token_auth/apis/session_api.rb#L53-L61

GET    |  /(.:format)
GET    |  /:provider(.:format)
GET    |  /:provider/callback(.:format)
GET    |  /failure(.:format)
POST   |  /(.:format)
GET    |  /edit(.:format)
PUT    |  /(.:format)
DELETE |  /(.:format)
POST   |  /sign_in(.:format)
DELETE |  /sign_out(.:format)
GET    |  /validate_token(.:format)

This is especially strange for confirmation module, which produce this endpoint:

GET  |  /(.:format) 

Of using mount helpers for scopes adds routes properly.
P.S. I'm using grape_on_rails_routes gem to get the list of routes

update documentation (configure_warden)

The documentation instructs to call GrapeTokenAuth.configure_warden(manager) in application.rb.

This throws an undefined method 'configure_warden' for GrapeTokenAuth:Module (NoMethodError) error. This happens because the configure_warden method is removed in ae43b72. Could you update the documentation for this?

edit: I added a pull-request, there was an other small typo as well. Documentation seems to be working now. Great project, thanks!

Resource should not generate a new token after signout

The var Configuration::CLIENT_KEY maps to 'client' but in our case it should be 'HTTP_CLIENT'

resource.tokens.delete returns nil:

resource.tokens.delete(env[Configuration::CLIENT_KEY])

While this succeeds:

resource.tokens.delete(env['HTTP_CLIENT])

require dep tree is imprevisible

When deploying, we encountered the following issues:

`forgiving_load_missing_constant': uninitialized constant GrapeTokenAuth::ResourceCrudBase (NameError)
    from /grape_token_auth/resource/resource_updater.rb:2:in `<module:GrapeTokenAuth>

This happens because

Dir.glob(File.expand_path('../**/*.rb', __FILE__)).each { |path| require path }

might not return an alphabetical ordered list of files.

See
frobichaud@2107423
and
frobichaud@022fb77

Application flow

Hi,
Is there any way I can see how to use this gem in the client perspective?
What calls should I do? I already installed but I am not sure how to access data from the json client perspective.
Does this follow some standard request flow that I can search upon?
Perhaps you can put some clue about it in the readme?
By the way is this token approach still valid now in 2020 or do you suggest some other?
Thank you very much

v 0.1.0 Documentation updates

Need instructions for:

  • omniauth
    • need mount_omniauth_callbacks and mount_omniauth
    • need to setup OmniAuth in rack
  • need configuration wiki section
  • blacklist and whitelist
  • development section
  • move contributing to Contributingmd

`case_insensitive_keys` returns nil

When I put

include GrapeTokenAuth::ActiveRecord::TokenAuth

In my User model, the case_insensitive_keys method returns nil (which breaks everything)

Without include GrapeTokenAuth::ActiveRecord::TokenAuth

[1] pry(main)> User.case_insensitive_keys
=> [:email]

With include GrapeTokenAuth::ActiveRecord::TokenAuth

[1] pry(main)> User.case_insensitive_keys
=> nil

Any suggestions?

“error”: “404 API Version Not Found”

Hi,

I am facing the following error while integrating grape token auth with grape.

I have mounted the auth api and it is available in the routes, but when i access the specific endpoints it is not available it says “error”: “404 API Version Not Found”. i dont know whether it is problem with grape / gta / routes that i mentioned.

but other urls doesn't have any problem except for auth urls.

Detailed explanation can be found here http://stackoverflow.com/questions/40672072/grape-token-auth-error-404-api-version-not-found

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.