lib/prx_auth/rails/ext/controller.rb in prx_auth-rails-1.7.0 vs lib/prx_auth/rails/ext/controller.rb in prx_auth-rails-1.8.0
- old
+ new
@@ -2,19 +2,28 @@
require 'open-uri'
module PrxAuth
module Rails
module Controller
+ class SessionTokenExpiredError < RuntimeError; end
- PRX_ACCOUNT_NAME_MAPPING_KEY = 'prx.account.name.mapping'.freeze
- PRX_TOKEN_SESSION_KEY = 'prx.auth'.freeze
+ PRX_AUTH_ENV_KEY = 'prx.auth'.freeze
+ PRX_JWT_SESSION_KEY = 'prx.auth.jwt'.freeze
+ PRX_JWT_REFRESH_TTL = 300.freeze
+ PRX_ACCOUNT_MAPPING_SESSION_KEY = 'prx.auth.account.mapping'.freeze
+ PRX_REFRESH_BACK_KEY = 'prx.auth.back'.freeze
def prx_auth_token
- rack_auth_token = env_prx_auth_token
- return rack_auth_token if rack_auth_token.present?
+ env_token || session_token
+ rescue SessionTokenExpiredError
+ reset_session
+ session[PRX_REFRESH_BACK_KEY] = request.fullpath
+ redirect_to PrxAuth::Rails::Engine.routes.url_helpers.new_sessions_path
+ end
- session[PRX_TOKEN_SESSION_KEY] && Rack::PrxAuth::TokenData.new(session[PRX_TOKEN_SESSION_KEY])
+ def prx_jwt
+ session[PRX_JWT_SESSION_KEY]
end
def prx_authenticated?
!!prx_auth_token
end
@@ -24,72 +33,87 @@
redirect_to PrxAuth::Rails::Engine.routes.url_helpers.new_sessions_path
end
def current_user
- return if prx_auth_token.nil?
+ prx_auth_token
+ end
- PrxAuth::Rails::Token.new(prx_auth_token)
+ def sign_in_user(token)
+ session[PRX_JWT_SESSION_KEY] = token
+ accounts_for(current_user.resources)
end
- def lookup_and_register_accounts_names
- session[PRX_ACCOUNT_NAME_MAPPING_KEY] =
- lookup_account_names_mapping
+ def after_sign_in_user_redirect
+ session.delete(PRX_REFRESH_BACK_KEY)
end
- def account_name_for(id)
- id = id.to_i
+ def sign_out_user
+ reset_session
+ end
- session[PRX_ACCOUNT_NAME_MAPPING_KEY] ||= {}
-
- name =
- if session[PRX_ACCOUNT_NAME_MAPPING_KEY].has_key?(id)
- session[PRX_ACCOUNT_NAME_MAPPING_KEY][id]
- else
- session[PRX_ACCOUNT_NAME_MAPPING_KEY][id] = lookup_account_name_for(id)
- end
-
- name = "[#{id}] Unknown Account Name" unless name.present?
-
- name
+ def account_name_for(account_id)
+ account_for(account_id)[:name]
end
- def sign_in_user(token)
- session[PRX_TOKEN_SESSION_KEY] = token
+ def account_for(account_id)
+ lookup_accounts([account_id]).first
end
- def sign_out_user
- session.delete(PRX_TOKEN_SESSION_KEY)
+ def accounts_for(account_ids)
+ lookup_accounts(account_ids)
end
private
- def lookup_account_name_for(id)
- id = id.to_i
+ def lookup_accounts(ids)
+ session[PRX_ACCOUNT_MAPPING_SESSION_KEY] ||= {}
- res = lookup_account_names_mapping([id])
- res[id]
+ # fetch any accounts we don't have yet
+ missing = ids - session[PRX_ACCOUNT_MAPPING_SESSION_KEY].keys
+ if missing.present?
+ fetch_accounts(missing).each do |account|
+ session[PRX_ACCOUNT_MAPPING_SESSION_KEY][account['id']] = account.with_indifferent_access
+ end
+ end
+
+ ids.map { |id| session[PRX_ACCOUNT_MAPPING_SESSION_KEY][id] }
end
- def lookup_account_names_mapping(ids=current_user.resources)
+ def fetch_accounts(ids)
id_host = PrxAuth::Rails.configuration.id_host
ids_param = ids.map(&:to_s).join(',')
options = {}
options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if ::Rails.env.development?
accounts = URI.open("https://#{id_host}/api/v1/accounts?account_ids=#{ids_param}", options).read
- mapping = JSON.parse(accounts)['accounts'].map { |acct| [acct['id'], acct['display_name']] }.to_h
+ JSON.parse(accounts)['accounts']
+ end
- mapping
+ # token from data set by prx_auth rack middleware
+ def env_token
+ @env_token_data ||= if request.env[PRX_AUTH_ENV_KEY]
+ token_data = request.env[PRX_AUTH_ENV_KEY]
+ PrxAuth::Rails::Token.new(token_data)
+ end
end
- def env_prx_auth_token
- if !defined? @_prx_auth_token
- @_prx_auth_token = request.env['prx.auth'] && PrxAuth::Rails::Token.new(request.env['prx.auth'])
- else
- @_prx_auth_token
+ # token from jwt stored in session
+ def session_token
+ @session_prx_auth_token ||= if prx_jwt
+ # NOTE: we already validated this jwt - so just decode it
+ validator = Rack::PrxAuth::AuthValidator.new(prx_jwt)
+
+ # try to refresh auth session on GET requests
+ if request.get? && validator.time_to_live < PRX_JWT_REFRESH_TTL
+ raise SessionTokenExpiredError.new
+ end
+
+ # create new data/token from access claims
+ token_data = Rack::PrxAuth::TokenData.new(validator.claims)
+ PrxAuth::Rails::Token.new(token_data)
end
end
end
end
end