# frozen_string_literal: true require "auth0" module NulogySSO # This controller adds routes to power SSO authentication when this engine is mounted into a Rails app. class AuthenticationController < ActionController::Base include Auth0::Api::AuthenticationEndpoints include Auth0::Mixins::HTTPProxy def initialize # These instance variables have to be set in order for the HTTPProxy mixin to work. @base_uri = sso_config.base_uri @headers = { content_type: "application/json" } end def login raw_access_token = token_store.fetch authenticator.validate_token( raw_access_token, on_success: method(:on_authentication_success), on_invalid_token: ->(_e) { redirect_to auth0_authorize_path } ) end def verify_authentication_code code = params.require(:code) begin raw_access_token = fetch_token_from_auth0(code) rescue Auth0::Exception => e return sso_error(e) end authenticator.validate_token( raw_access_token, on_success: method(:on_authentication_success), on_invalid_token: ->(e) { sso_error(e) } ) end def logout token_store.forget! query_params = { returnTo: sso_config.redirect_uri, # Yes, this must be camelCased client_id: sso_config.client_id } redirect_to "#{sso_config.base_uri}/v2/logout?#{query_params.to_query}" end private delegate :sso_config, to: :NulogySSO def sso_error(error) NulogySSO.handle_sso_error.call(controller: self, error: error) end def authenticator @authenticator ||= Authenticator.new end def token_store @token_store ||= CookieTokenStore.new(request, response) end def on_authentication_success(access_token) token_store.store!(access_token) redirect_to params["origin"].presence || sso_config.redirect_uri end def fetch_token_from_auth0(code) response = exchange_auth_code_for_tokens( code, redirect_uri: sso_config.login_uri, client_id: sso_config.client_id, client_secret: sso_config.client_secret ) response["access_token"] end def auth0_authorize_path query_params = { audience: sso_config.audience, client_id: sso_config.client_id, response_type: "code", scope: "openid email", redirect_uri: "#{sso_config.login_uri}?origin=#{CGI::escape(session[:previous_request_url])}" } "#{sso_config.base_uri}/authorize?#{query_params.to_query}" end end end