foodcoops/foodsoft

View on GitHub
plugins/discourse/app/controllers/discourse_login_controller.rb

Summary

Maintainability
A
25 mins
Test Coverage
class DiscourseLoginController < DiscourseController
  before_action -> { require_config_disabled :discourse_sso }
  skip_before_action :authenticate

  def initiate
    discourse_url = FoodsoftConfig[:discourse_url]

    nonce = SecureRandom.hex
    return_sso_url = url_for(action: :callback, only_path: false)

    session[:discourse_sso_nonce] = nonce
    redirect_to_with_payload "#{discourse_url}/session/sso_provider",
                             nonce: nonce,
                             return_sso_url: return_sso_url
  end

  def callback
    raise I18n.t('discourse.callback.invalid_signature') unless valid_signature?

    payload = parse_payload

    raise I18n.t('discourse.callback.invalid_nonce') if payload[:nonce] != session[:discourse_sso_nonce]

    session[:discourse_sso_nonce] = nil

    id = payload[:external_id].to_i
    user = User.find_or_initialize_by(id: id) do |user|
      user.id = id
      user.password = SecureRandom.random_bytes(25)
    end
    user.nick = payload[:username]
    user.email = payload[:email]
    user.first_name = payload[:name]
    user.last_name = ''
    user.last_login = Time.now
    user.save!

    login_and_redirect_to_return_to user, notice: I18n.t('discourse.callback.logged_in')
  rescue StandardError => e
    redirect_to login_url, alert: e.to_s
  end
end