LearnPulse / app /controllers /users /omniauth_callbacks_controller.rb
Nambinintsoa Rovatiana RAMAROSON
first commit
874ae95
Raw
History Blame Contribute Delete
5.92 kB
module Users
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
include Devise::Controllers::Rememberable
skip_before_action :verify_authenticity_token, only: [:developer]
# GET /users/auth/:action/callback
def oauth_callback
@email = email_from_auth_hash
if oauth_origin.present? && oauth_origin[:session_id]
if oauth_origin[:link_data].present?
passthru_oauth_data
elsif @email.blank?
redirect_to(
oauth_error_url(
host: oauth_origin[:fqdn],
error: email_blank_flash
),
allow_other_host: true
)
nil
else
sign_in_at_oauth_origin
end
else
render "oauth_origin_missing", layout: "error"
end
end
alias google_oauth2 oauth_callback
alias facebook oauth_callback
alias github oauth_callback
alias discord oauth_callback
alias developer oauth_callback
def failure
if oauth_origin.present?
message = t(".denied_by", provider: oauth_origin[:provider].capitalize)
redirect_to(
oauth_error_url(host: oauth_origin[:fqdn], error: message),
allow_other_host: true
)
else
flash[:error] = t(".denied")
redirect_to new_user_session_path
end
end
private
def oauth_origin
@oauth_origin ||=
begin
raw_origin_data = read_cookie(:oauth_origin)
# Parse the JSON format that origin information is stored as.
if raw_origin_data.present?
# Make sure the cookie isn't reused.
cookies.delete :oauth_origin
JSON.parse(raw_origin_data, symbolize_names: true)
end
end
end
# This method is called when the user is already signed in, and is trying to link their social account with user.
def passthru_oauth_data
encrypted_token =
EncryptorService.new.encrypt(
{ auth_hash: auth_hash_data, session_id: oauth_origin[:session_id] }
)
token_url_options = {
encrypted_token: Base64.urlsafe_encode64(encrypted_token),
host: oauth_origin[:fqdn]
}
redirect_to(
user_auth_callback_url(**token_url_options),
allow_other_host: true
)
end
# This method is called when the user is not signed in, and is trying to sign in using OAuth.
def sign_in_at_oauth_origin
if user.present?
user.regenerate_login_token
encrypted_token =
EncryptorService.new.encrypt(
{
login_token: user.original_login_token,
auth_hash: auth_hash_data,
session_id: oauth_origin[:session_id]
}
)
token_url_options = {
encrypted_token: Base64.urlsafe_encode64(encrypted_token),
host: oauth_origin[:fqdn]
}
redirect_to(
user_auth_callback_url(token_url_options),
allow_other_host: true
)
else
redirect_to(
oauth_error_url(
host: oauth_origin[:fqdn],
error:
t(
"users.omniauth_callbacks.oauth_callback.email_unregistered",
email: @email
)
),
allow_other_host: true
)
end
end
def user
@user ||=
begin
school =
School
.joins(:domains)
.where(domains: { fqdn: oauth_origin[:fqdn] })
.first
school.users.with_email(@email).first
end
end
# This method is used to pass the auth_hash data to the oauth_origin.
def auth_hash_data
case auth_hash[:provider]
when "google_oauth2", "facebook", "github", "developer"
{}
when "discord"
{
discord: {
uid: auth_hash[:uid],
tag:
"#{auth_hash[:extra][:raw_info][:username]}##{auth_hash[:extra][:raw_info][:discriminator]}",
access_token: auth_hash[:credentials][:token]
}
}
else
raise_unexpected_provider(provider)
end
end
# This is a hack to resolve the issue of flashing message 'You are already signed in' when signing in using OAuth.
# For an unknown reason, the request env variable omniauth.origin defaults to the sign in path when no origin is
# supplied to the omniauth provider login path. This method detects and removes that default.
def origin
supplied_origin = request.env["omniauth.origin"]
supplied_origin.include?('users/sign_in') ? nil : supplied_origin
end
# Omniauth returns authentication details in the 'omniauth.auth' request environment variable after the provider
# redirects back to our website. The format for this return value is documented by Omniauth.
def auth_hash
request.env["omniauth.auth"]
end
# This method validates the format of auth_hash. This ensures that we capture any 'oddities' as crashes, instead of
# letting issues get buried (we used to show a useless 404).
def email_from_auth_hash
raise "Auth hash is blank: #{auth_hash.inspect}" if auth_hash.blank?
auth_hash.dig(:info, :email)
end
def provider_name
params[:action].split("_").first.capitalize
end
def email_blank_flash
message =
t(
"users.omniauth_callbacks.oauth_callback.not_receive_email",
provider_name: provider_name
)
message +=
case provider_name
when "Github"
t("users.omniauth_callbacks.oauth_callback.add_github")
when "Facebook"
t("users.omniauth_callbacks.oauth_callback.add_facebook")
else
t("users.omniauth_callbacks.oauth_callback.add_other")
end
message.html_safe
end
end
end