Git Product home page Git Product logo

tiddle's Introduction

Tiddle

Tiddle provides Devise strategy for token authentication in API-only Ruby on Rails applications. Its main feature is support for multiple tokens per user.

Tiddle is lightweight and non-configurable. It does what it has to do and leaves some manual implementation to you.

Installation

Add this line to your application's Gemfile:

gem 'tiddle'

And then execute:

$ bundle

Usage

  1. Add :token_authenticatable inside your Devise-enabled model:
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :trackable, :validatable,
         :token_authenticatable
end
  1. Generate the model which stores authentication tokens. The model name is not important, but the Devise-enabled model should have association called authentication_tokens.
rails g model AuthenticationToken body:string:index user:references last_used_at:datetime expires_in:integer ip_address:string user_agent:string
class User < ActiveRecord::Base
  has_many :authentication_tokens
end

body, last_used_at, ip_address and user_agent fields are required.

  1. Customize Devise::SessionsController. You need to create and return token in #create and expire the token in #destroy.
class Users::SessionsController < Devise::SessionsController

  def create
    user = warden.authenticate!(auth_options)
    token = Tiddle.create_and_return_token(user, request)
    render json: { authentication_token: token }
  end

  def destroy
    Tiddle.expire_token(current_user, request) if current_user
    render json: {}
  end

  private

    # this is invoked before destroy and we have to override it
    def verify_signed_out_user
    end
end
  1. Require authentication for some controller:
class PostsController < ApplicationController
  before_action :authenticate_user!

  def index
    render json: Post.all
  end
end
  1. Send X-USER-EMAIL and X-USER-TOKEN as headers of every request which requires authentication.

You can read more in a blog post dedicated to Tiddle - https://blog.sundaycoding.com/blog/2015/04/04/token-authentication-with-tiddle/

Note on Rails session

The safest solution in API-only application is not to rely on Rails session at all and disable it. Put this line in your application.rb:

config.middleware.delete ActionDispatch::Session::CookieStore

More: https://blog.sundaycoding.com/blog/2015/04/04/token-authentication-with-tiddle/#rails-session

Using field other than email

Change config.authentication_keys in Devise intitializer and Tiddle will use this value.

Security

Usually it makes sense to remove user's tokens after a password change. Depending on the project and on your taste, this can be done using various methods like running user.authentication_tokens.destroy_all after the password change or with an after_save callback in your model which runs authentication_tokens.destroy_all if encrypted_password_changed?.

In case of a security breach, remove all existing tokens.

Tokens are expiring after certain period of inactivity. This behavior is optional. If you want your token to expire, create it passing expires_in option:

token = Tiddle.create_and_return_token(user, request, expires_in: 1.month)

tiddle's People

Contributors

adamniedzielski avatar andrepiske avatar andyklimczak avatar arielsilveira avatar bmorrall avatar calleo avatar dapx avatar dflourusso avatar jonekdahl avatar kwals avatar mhfs avatar riggy avatar romankovt avatar serabe 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  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  avatar  avatar  avatar  avatar  avatar

tiddle's Issues

[Question] - What is verify_signed_out_user?

Hi,

Could you please explain more about this method?

# this is invoked before destroy and we have to override it
def verify_signed_out_user
end
  1. What actually the method do in more detail?
  2. What will happend if we remove it?
  3. What should we do inside it?

Thanks!

Version 1.0

This gem has over a year and I consider it to be pretty stable at this point, so I would like to release version 1.0. Please share your feedback if you are using Tiddle in production.

DEPRECATION WARNING: ActionDispatch::IntegrationTest

When the test suite is run under Rails 5:

DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as

Examples:

get '/profile',
  params: { id: 1 },
  headers: { 'X-Extra-Header' => '123' },
  env: { 'action_dispatch.custom' => 'custom' },
  xhr: true,
  as: :json
 (called from block (3 levels) in <top (required)> at /home/adamsunday/workspace/tiddle/spec/strategy_spec.rb:131)

The tricky part here is that the solution has to work both with Rails 4.2 and Rails 5.0.

tiddle & omniauth

Hello,

I am curious if I can omniauth features of devise while using tiddle.

Would this work without having to do anything custom?

Thanks.

Remove unnecessary secure compare

Thanks @DamirSvrtan for explaining this to me! 💚

Here we load all the tokens for the given user into the memory and perform secure compare on them.

Secure compare was necessary to prevent timing attacks when we were storing tokens in the database. However, since version 0.5.0 we are storing only token digests which has a side effect of preventing timing attacks.

We can:

  1. replace the code with a single SQL query
  2. suggest adding an index on body column in the README

Randomly Generated Token is saved directly to the Database

I noticed the Token returned by create_token is the same token that has been saved to the database.

This could lead to issues where accidentally revealing a token (i.e. Rails default JSON prints too much info) can allow a malicious user direct access to another account.

Generating a Digest and saving that to the database would be much more secure.

Tokens pile up in the database forever

Hey! I'd like to collect your ideas on how to approach this issue and try to come up with a solution.

Currently when a token is issued and, after a while, never used anymore (which I expect to be a common scenario), the tokens will just pile up and never be deleted from the database. It should be deleted at some point after the token is expired.

The trivial solution to this is to have a background/async job periodically checking for expired tokens and delete them. But that's a custom solution I guess everyone would have to rollout.

IMHO, Tiddle would benefit by having at least a method to help achieve that and then have that documented in the Readme. I guess what that method would do is to help to find all expired tokens in the database and then (maybe a second method) also delete them from the DB.

That's my take, but I'd like to know what are your plans or thoughts on this.

Devise 4.4

I can’t use tiddle 1.0.2 with devise 4.4

Bundler could not find compatible versions for gem “devise”:
In Gemfile:
devise (~> 4.4)

tiddle (>= 1.0.2, ~> 1.0) was resolved to 1.0.2, which depends on
devise (< 4.4, >= 4.0.0.rc1)

devise, ">= 4.0.0.rc1", "< 4.1"

Because there is a new devise version (4.1.1) I think we need to upgrade dependencies to:

spec.add_dependency "devise", ">= 4.0.0.rc1", "< 5.0.0"

What do you think? On another issue, are you planning to release other version?

Use in Angularjs

To make the use more easy, i created a Angularjs plugin to use with tiddle.
Follows the link: ng-tiddle :)

Revoke all tokens on password change

How about deleting all tokens of a user after they change their password? Since they don't want their old password to be used for accessing the app, it makes sense doing the same for the tokens generated through that password.

I imagine utilizing a callback in the user model (something like this, though I guess we can use after_save rather than before_save since we're not storing all tokens in a single field of the user model).

Devise cannot be updated to 3.5.1

It's locked to ~> 3.4.1 due to your gemspec.

Changing the dependency to ~> 3.4 still works as expected, and allows devise to be updated to the latest release.

Pull request in #6

Time-based expiration mechanism for tokens

Hello,

Really love the work you did with this gem!

Currently as much as I see, tokens can be used forever, there is no support for generating tokens that last for a certain amount of time (e.g. 2 weeks).

Do you plan on supporting something like this, and what's your take on this?

Error after install

After add gem 'tiddle' and bundle, when i restart the server, i got the follow error:
.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/devise-3.5.2/lib/devise/strategies/base.rb:4:in '<module:Strategies>': uninitialized constant Warden (NameError)

Timeout and expiration for token

Hello,

Thanks for you sharing this authentication token tool. I have some question regards to the expiration timeout for the authentication tokens in database. Is there a place to set up the timeout value? How does it cooperate with Devise remember?

Mongoid support

Does somebody use Tiddle with Mongo?

I've never done it myself. I accepted the contribution back in 2018, because the PR (#42) was clear and nicely done. Since that time I had to put some effort into maintaining the support, mostly related to fixing the CI build when new versions of Ruby and Rails come out. It also duplicates the number of CI jobs we're running.

@calleo @jonekdahl are you still using Tiddle with Mongo?

Fix Rubocop offences

There are Rubocop offences thrown when you run the test suite. I'm open for discussion which ones should be ignored (disabled in .rubocop.yml file) and which ones should be fixed.

Token last_used_at not being updated properly

Hello,

I've been using Tiddle using the expiration option, and there is a bug for tokens that expires in less than 1 hour.

For some reason, it does not update the last_activity_at on every request (maybe to save some db updates), making tokens that expire for example in 30 minutes don't ever refresh because of that. So what happens is that those tokens will expire even right after usage.

It also leaves the last_activity_at with an approximate value instead of the real-time the token was used.

There is a spec for this behavior, and I wonder the reason for that:
https://github.com/adamniedzielski/tiddle/blob/master/spec/strategy_spec.rb#L39

I will also create a PR removing that in case we can take that out :)

[Question] Cookieless Tiddle & ActionCable

I've been looking in the documentation and have not found a way to do "manual" authentication to authenticate a websocket connection. Is there any way to do this without using cookies?

Tiddle can not work with devise 4.5.0.

This constrain does not allow to use devise 4.5.0:
spec.add_dependency "devise", ">= 4.0.0.rc1", "< 4.5"

It would be better:
spec.add_dependency "devise", ">= 4.0.0.rc1", "< 5.0"

Removing or lowering required Ruby

I'd like to try out Tiddle with a project running a previous Ruby (2.1.1) which I'm not able to update. However, currently the gemspec specifies ~> 2.2.0. Is there any specific functionality in Tiddle that requires a Ruby that recent?

Peeking through the code, I didn't find any, but I could be wrong.

Support devise > 4.3.X

Hi Adam!

We need to add support for new devise version (4.3.0).
devise < 5 may works!

Greetings!

Cannot authenticate

Given a sessions controller:

class Api::V1::SessionsController < Devise::SessionsController
  protect_from_forgery with: :null_session
  skip_before_action :verify_authenticity_token
  respond_to :json

  def create
    user = warden.authenticate!(auth_options)
    token = Tiddle.create_and_return_token(user, request)
    render json: { authentication_token: token }
  end

  def destroy
    Tiddle.expire_token(current_user, request) if current_user
    render json: {}
  end

  private

  # this is invoked before destroy and we have to override it
  def verify_signed_out_user
  end
end

routes:

Rails.application.routes.draw do
  namespace :api, defaults: { format: :json } do
    scope module: :v1, constraints: ApiConstraints.new(version: 1, default: :true) do
      devise_for :users, path_names: {
        sign_in: 'login', sign_out: 'logout', sign_up: 'register' },
        controllers: { registrations: 'api/v1/registrations', sessions: 'api/v1/sessions' }
    end
  end
end

Sending a post request to /api/users/login only results in:

{
  "error": "You need to sign in or sign up before continuing."
}

The log says:

Started POST "/api/users/login" for 127.0.0.1 at 2015-11-19 00:21:36 +0000
Processing by Api::V1::SessionsController#create as JSON
  Parameters: {"user"=>{"email"=>"[FILTERED]", "password"=>"[FILTERED]"}}
Completed 401 Unauthorized in 2ms (ActiveRecord: 0.0ms)

Using:

ruby  2.2.3p173
rails 4.2.4
tiddle 0.5.1
devise  3.5.2

I've also tried config.middleware.delete ActionDispatch::Session::CookieStore and using reset_session in a before_action. This is in an app where I am also allowing web access so will need to keep the cookie store middleware, but even removing it did not solve this issue.

Any ideas?

Error after installed Tiddle

I get this error after installing Tiddle gem, I try everything but it persist...

.rvm/gems/ruby-2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:89:inrescue in block (2 levels) in require': There was an error while trying to load the gem 'tiddle'. (Bundler::GemRequireError)
Gem Load Error is: uninitialized constant Warden
Backtrace for gem load error is:
/home/cardotrejos/.rvm/gems/ruby-2.3.0/gems/devise-3.5.10/lib/devise/strategies/base.rb:4:in <module:Strategies>' /home/cardotrejos/.rvm/gems/ruby-2.3.0/gems/devise-3.5.10/lib/devise/strategies/base.rb:2:inmodule:Devise'
/home/cardotrejos/.rvm/gems/ruby-2.3.0/gems/devise-3.5.10/lib/devise/strategies/base.rb:1:in <top (required)>'....

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.