0
votes

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
2

2 Answers

0
votes
  1. Find the user.
  2. If no user - create user.
  3. Update user (bothe exisitng and new) with fresh omniauth data

Something like this should do the job:

def self.from_omniauth(auth)
  #find from omniauth
  user = User.where(email: auth.email).first

  #find or create
  user ||= User.create(
    email: data["email"],
    password: Devise.friendly_token[0, 20]
  )
  #update with fresh data
  user.name = auth.info.name
  user.image = auth.info.image
  user.expires = auth.credentials.expires
  user.refresh_token = auth.credentials.refresh_token
end
0
votes

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