Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IndexError: string not matched on User sign_in #681

Closed
JackWCollins opened this issue Jul 17, 2016 · 3 comments
Closed

IndexError: string not matched on User sign_in #681

JackWCollins opened this issue Jul 17, 2016 · 3 comments

Comments

@JackWCollins
Copy link

I'm trying to sign in an existing user, but I'm hitting an IndexError: string not matched in the 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 (!@resource.respond_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 (version 0.1.38) 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 user 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 #101, but that didn't have a specific resolution. Any ideas?

@JackWCollins
Copy link
Author

I found the fix in #121 - I need to set the token to nil when it is being created for an existing user.

 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

@superrandres
Copy link

superrandres commented Mar 22, 2017

@JackWCollins help to me! I'm use Postgresql and I have go to my row on db for setting to nil, e.j.

2.3.0 :002 > user.tokens
=> "{}"
2.3.0 :003 > user.tokens = nil
=> nil
2.3.0 :004 > user.save
(0.1ms) BEGIN
SQL (0.3ms) UPDATE "users" SET "tokens" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["tokens", nil], ["updated_at", 2017-03-22 17:31:23 UTC], ["id", 1]]
(23.9ms) COMMIT
=> true
2.3.0 :005 > user.tokens
=> {}

Also I've changed my seed file, here it is.
User.create(email: 'developerjs@austrosoft.com.ec', nickname: 'ronald', name: 'Ronald Espinoza', password: "austro1992", tokens: nil)

I've attempt put your solution on my migration file but not working for me. Here my file "db/migrate/20170321204000_devise_token_auth_create_users.rb".

`class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table(:users) do |t|
## Required
t.string :provider, :null => false, :default => "email"
t.string :uid, :null => false, :default => ""

  ## Database authenticatable
  t.string :encrypted_password, :null => false, :default => ""

  ## Recoverable
  t.string   :reset_password_token
  t.datetime :reset_password_sent_at

  ## Rememberable
  t.datetime :remember_created_at

  ## Trackable
  t.integer  :sign_in_count, :default => 0, :null => false
  t.datetime :current_sign_in_at
  t.datetime :last_sign_in_at
  t.string   :current_sign_in_ip
  t.string   :last_sign_in_ip

  ## Confirmable
  t.string   :confirmation_token
  t.datetime :confirmed_at
  t.datetime :confirmation_sent_at
  t.string   :unconfirmed_email # Only if using reconfirmable

  ## Lockable
  # t.integer  :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
  # t.string   :unlock_token # Only if unlock strategy is :email or :both
  # t.datetime :locked_at

  ## User Info
  t.string :name
  t.string :nickname
  t.string :image
  t.string :email

  ## Tokens
  t.json :tokens

  t.timestamps
end

add_index :users, :email,                unique: true
add_index :users, [:uid, :provider],     unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token,   unique: true
# add_index :users, :unlock_token,       unique: true

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

end
end`

@JohnMerlino2
Copy link

JohnMerlino2 commented Aug 15, 2017

@JackWCollins Why would you create a migration that sets defaults for provider and uid and then in the same migration specify that provider and uid must in combination be unique? Oauth is optional in most systems and therefore both those values will often be populated with the same defaults in your case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants