Search code examples
ruby-on-railsrubytwitterdeviseomniauth

How to update twitter omniauth access token and access token secret


In my rails 6 app, users have to sign in with twitter omniauth and devise. I have been able to implement it by following this tutorial.

The issue I have is that when a user revokes my app permissions from their twitter account, the omniauth access tokens and access secrets that I previously saved into my database becomes invalid. If the same user decides to re-authenticate, the user gets access to the app but the user's tokens are not updated in the database, rendering the existing tokens invalid.

My question is, how do I continuosly update the user columns in my database so I continue to receive valid access tokens from twitter, especially when the user has access tokens.

This is relevant code from my user model

  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.email = auth.info.email
    user.password = Devise.friendly_token[0, 20]
    user.name = auth.info.name
    user.username = auth.info.nickname
    user.location = auth.info.location
    user.access_token = auth.credentials.token
    user.access_secret = auth.credentials.secret
    end
  end

My user controller looks like this

  def twitter
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, kind: "Twitter") if is_navigational_format?
    else
      session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to new_user_registration_url
    end
  end

Solution

  • I got it working with by using find_or_initialize_by

       def self.from_omniauth(auth)
        user = find_or_initialize_by(provider: auth.provider, uid: auth.uid)
        user.email = auth.info.email
        user.password = Devise.friendly_token[0, 20]
        user.name = auth.info.name
        user.username = auth.info.nickname
        user.location = auth.info.location
        user.access_token = auth.credentials.token
        user.access_secret = auth.credentials.secret
        user.save!
        return user
      end