Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

devise_token_auth & Rails 5 - IndexError: string not matched

I'm trying to sign in an existing user using devise_token_auth version 0.1.38, but I'm hitting an IndexError: string not matched in the library's sessions_controller.

IndexError (string not matched):

devise_token_auth (0.1.38) app/controllers/devise_token_auth/sessions_controller.rb:37:in `[]='
devise_token_auth (0.1.38) app/controllers/devise_token_auth/sessions_controller.rb:37:in `create'
actionpack (5.0.0) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
actionpack (5.0.0) lib/abstract_controller/base.rb:188:in `process_action'
actionpack (5.0.0) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.0.0) lib/abstract_controller/callbacks.rb:20:in `block in process_action'

The relevant code from sessions_controller is:

  if @resource and valid_params?(field, q_value) and @resource.valid_password?(resource_params[:password]) and ([email protected]_to?(:active_for_authentication?) or @resource.active_for_authentication?)
    # create client id
    @client_id = SecureRandom.urlsafe_base64(nil, false)
    @token     = SecureRandom.urlsafe_base64(nil, false)

    #  !! Next line is line 37 with the error !!
    @resource.tokens[@client_id] = {  
      token: BCrypt::Password.create(@token),
      expiry: (Time.now + DeviseTokenAuth.token_lifespan).to_i
    }
    @resource.save

    sign_in(:user, @resource, store: false, bypass: false)

I've added devise_token_auth to an existing project so it's very possible that I've created bad data in the tokens column. I've tried various ways of defaulting token json into my existing users including mimicking the code in the sessions_controller.

add_column :users, :tokens, :json, null: false, default: {}

User.reset_column_information
client_id = SecureRandom.urlsafe_base64(nil, false)
token     = SecureRandom.urlsafe_base64(nil, false)

User.find_each do |user|
  user.uid = user.email
  user.provider = 'email'
  user.tokens[client_id] = {
      token: BCrypt::Password.create(token),
      expiry: (Time.now + DeviseTokenAuth.token_lifespan).to_i
  }
  user.save!
end

I've seen a mention of this in issue #101, but that didn't have a specific resolution. Any idea where I'm going wrong?

like image 895
Jack Collins Avatar asked Jul 17 '16 17:07

Jack Collins


1 Answers

It turns out I needed to set the tokens to nil, and then devise will take care of setting that for me. I found the answer in this devise issue.

def change
  add_column :users, :provider, :string, null: false, default: "email"
  add_column :users, :uid, :string, null: false, default: ""
  add_column :users, :tokens, :text

  reversible do |direction|
    direction.up do
      User.find_each do |user|
        user.uid = user.email
        user.tokens = nil
        user.save!
      end
    end
  end

  add_index :users, [:uid, :provider], unique: true
end
like image 70
Jack Collins Avatar answered Oct 23 '22 03:10

Jack Collins