# 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 = auth_config.base_uri @headers = { content_type: "application/json" } end def login raw_access_token = cookies[NulogySSO.auth_cookie_key] authenticator.validate_token( raw_access_token, on_success: method(:on_authentication_success), on_invalid_token: -> { redirect_to auth_path } ) end def code code = params.require(:code) begin raw_access_token = token_response(code)["access_token"] rescue Auth0::Exception => e return sso_error end authenticator.validate_token( raw_access_token, on_success: method(:on_authentication_success), on_invalid_token: -> { sso_error } ) end def logout cookies.delete(NulogySSO.auth_cookie_key, domain: :all) query_params = { returnTo: auth_config.redirect_uri, # Yes, this must be camelCased client_id: auth_config.client_id } redirect_to "#{auth_config.base_uri}/v2/logout?#{query_params.to_query}" end private delegate :auth_config, to: :NulogySSO def sso_error NulogySSO.handle_sso_error.call(self) end def authenticator @authenticator ||= Authenticator.new end def on_authentication_success(access_token) respond_with_cookies(access_token) redirect_to params["origin"].presence || auth_config.redirect_uri end def token_response(code) exchange_auth_code_for_tokens( code, redirect_uri: auth_config.login_uri, client_id: auth_config.client_id, client_secret: auth_config.client_secret ) end def respond_with_cookies(access_token_value) cookies[NulogySSO.auth_cookie_key] = { value: access_token_value, domain: :all, expires: 36_000.seconds, # TODO: Fetch this value from the JWT httponly: true, secure: request.ssl? } end def auth_path query_params = { audience: auth_config.audience, client_id: auth_config.client_id, response_type: "code", scope: "openid email", redirect_uri: "#{auth_config.login_uri}?origin=#{session[:previous_request_url]}" } "#{auth_config.base_uri}/authorize?#{query_params.to_query}" end end end