Changes in omni auth strategies/custom auth plugin?


(Carlo Kok) #1

We’ve had a custom OAuth2 based authentication which looks like:

require 'auth/oauth2_authenticator'

require 'omniauth-oauth2'
class OmniAuth::Strategies::RoOauth < OmniAuth::Strategies::OAuth2
  SITE_URL = '******'
  # Give your strategy a name.
  option :name, "ro_oauth"

  # This is where you pass the options you would pass when
  # initializing your consumer from the OAuth gem.
  option :client_options, site: SITE_URL

  # These are called after authentication has succeeded. If
  # possible, you should try to set the UID without making
  # additional calls (if the user id is returned with the token
  # or as a URI parameter). This may not be possible with all
  # providers.
  uid{ raw_info['id'] }

  info do
    {
      :name => raw_info['name'],
      :email => raw_info['email'],
      :groups => raw_info['groups']
    }
  end

  extra do
    {
      'raw_info' => raw_info
    }
  end

  def raw_info
    @raw_info ||= access_token.get('*****').parsed
  end
end

class RoAuthenticator < ::Auth::OAuth2Authenticator

  CLIENT_ID = '****'
  CLIENT_SECRET = '****'

  def register_middleware(omniauth)
    omniauth.provider :ro_oauth,
      CLIENT_ID,
      CLIENT_SECRET
  end
  def after_create_account(user, auth)
    super(user, auth)
    data = auth[:extra_data]
    update_user_groups(user, data[:groups])
  end

  def update_user_groups(user, groups)
    grouplist = groups.select { |item| item.starts_with?("beta-") }.map { |item| item[5, item.length - 5] }
    Rails.logger.info "After create account " + grouplist.join(",")
    Group.joins(:users).where(users: { id: user.id } ).each do |c|
      gname = c.name
      if gname.start_with?("beta_")
        gname = gname[5, gname.length - 5]
        if grouplist.include?(gname)
          grouplist.delete(gname) # remove it from the list
        else
          c.group_users.where(user_id: user.id).destroy_all
          # Rails.logger.info "Would remove group " + c.name
        end
      end
    end
    grouplist.each do |c|
       grp = Group.where(name: "beta_" + c).first
       if not grp.nil?
         grp.group_users.create(user_id: user.id, group_id: grp.id)
         # Rails.logger.info "adding user to " + grp.name
       end
    end
  end

  def after_authenticate(auth_token)
    result = Auth::Result.new

    oauth2_provider = auth_token[:provider]
    oauth2_uid = auth_token[:uid]
    data = auth_token[:info]
    result.email = email = data[:email]
    result.name = name = data[:name]

    oauth2_user_info = Oauth2UserInfo.find_by(uid: oauth2_uid, provider: oauth2_provider)

    if !oauth2_user_info && @opts[:trusted] && user = User.find_by_email(email)
      oauth2_user_info = Oauth2UserInfo.create(uid: oauth2_uid,
                                               provider: oauth2_provider,
                                               name: name,
                                               email: email,
                                               user: user)
    end

    result.user = oauth2_user_info.try(:user)
    result.email_valid = @opts[:trusted]

    result.extra_data = {
      uid: oauth2_uid,
      provider: oauth2_provider,
      groups: data[:groups]
    }

    #result

    # result = super(auth_token)
    if not result.user.nil?
      update_user_groups(result.user, result.extra_data[:groups])
    end
    result
  end
end


auth_provider :title => 'Click here to sign in.',
    :message => 'Log in via the main site (Make sure pop up blockers are not enabled).',
    :frame_width => 920,
    :frame_height => 1000,
    :authenticator => RoAuthenticator.new('ro_oauth', trusted: true)

register_css <<CSS

.btn-login.ro_oauth {
  background: #0E76BD;
color: rgb(255, 255, 255);
text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.2);
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1) inset;
}

CSS

But it suddenly started failing with:
NoMethodError (undefined method []' for nil:NilClass) /var/www/discourse/plugins/roauth/plugin.rb:23:inblock in class:RoOauth

Did anything change for this, and if yes, what can I do to fix this error?

This would have been a recent fix; since i update almost daily and we only just noticed.


(Sam Saffron) #2

possibly @tgxworld did change some of the internals, what line is failing? Try adding more logging to see where and why it is failing.


(Carlo Kok) #3

it fails on:

  uid{ raw_info['id'] }

I can’t find where I got this sample from though, to compare with, I wrote this before discourse even did docker (and it’s been working fine since), not sure where raw_info has gone to


(Sam Saffron) #4

So raw_info is nil, look at the base class, is it renamed to something else?


(Carlo Kok) #5

thanks I’ll debug a bit more.


(Carlo Kok) #6

Ended up switching to your sso provider instead, works just as well and doesn’t require a special plugin.


(Alan Tan) #7