module Keycard::ControllerMethods

Mixin for conveniences in controllers.

These methods depend on a `notary` method in your controller that returns a configured {Keycard::Notary} instance.

Constants

DEFAULT_SESSION_TIMEOUT

The default session timeout is 24 hours, in seconds.

Public Instance Methods

authenticate!() click to toggle source

Require that some authentication method successfully identifies a user/account, raising an exception if there is a failure for active credentials or no applicable credentials are presented.

@raise [AuthenticationFailed] if credentials for an attempted

authentication method are incorrect

@raise [AuthenticationRequired] if all authentication methods are skipped

and authentication could not be attempted

@return nil

# File lib/keycard/controller_methods.rb, line 55
def authenticate!
  raise AuthenticationFailed if authentication.failed?
  raise AuthenticationRequired unless authentication.authenticated?
end
auto_login(account) click to toggle source

Log an account in without checking any credentials, starting a session.

@param account [User|Account] the user/account object to consider current;

must have an #id property.
# File lib/keycard/controller_methods.rb, line 76
def auto_login(account)
  request.env["keycard.authentication"] = notary.waive(account)
  setup_session
end
current_user() click to toggle source

Retrieve the user/account to which the current request is attributed.

@return [User/Account] the user/account that has been authenticated; nil

if no one is logged in
# File lib/keycard/controller_methods.rb, line 25
def current_user
  authentication.account
end
logged_in?() click to toggle source

Check whether the current request is authenticated as coming from a known person or account.

@return [Boolean] true if any of the {Notary}'s configured authentication

methods succeeds
# File lib/keycard/controller_methods.rb, line 17
def logged_in?
  authentication.authenticated?
end
login(**credentials) click to toggle source

Attempt to authenticate, optionally with user-supplied credentials, and establish a session.

@param credentials [Hash|kwargs] user-supplied credentials that will be

passed to each authentication method

@return [Boolean] whether the login attempt was successful

# File lib/keycard/controller_methods.rb, line 66
def login(**credentials)
  authentication(credentials).authenticated?.tap do |success|
    setup_session if success
  end
end
logout() click to toggle source

Clear authentication status and terminate any open session.

# File lib/keycard/controller_methods.rb, line 82
def logout
  request.env["keycard.authentication"] = notary.reject
  reset_session
end
validate_session() click to toggle source

Validate the session, resetting it if expired.

This should be called as a before_action before {#authenticate!} when working with session-based logins. It preserves a CSRF token, if present, so login forms and the like will pass forgery protection.

# File lib/keycard/controller_methods.rb, line 34
def validate_session
  csrf_token = session[:_csrf_token]
  elapsed = begin
              Time.now - Time.at(session[:timestamp] || 0)
            rescue StandardError
              session_timeout
            end
  reset_session if elapsed >= session_timeout
  session[:_csrf_token] = csrf_token
  session[:timestamp] = Time.now.to_i if session.key?(:timestamp)
end

Private Instance Methods

authentication(**credentials) click to toggle source
# File lib/keycard/controller_methods.rb, line 89
def authentication(**credentials)
  request.env["keycard.authentication"] ||=
    notary.authenticate(request, session, credentials)
end
session_timeout() click to toggle source

The session timeout, in seconds. Sessions will be cleared before any further authentication unless there is a timestamp younger than this many seconds old. The default is 24 hours.

@return [Integer] session timeout, in seconds

# File lib/keycard/controller_methods.rb, line 99
def session_timeout
  DEFAULT_SESSION_TIMEOUT
end
setup_session() click to toggle source
# File lib/keycard/controller_methods.rb, line 103
def setup_session
  return_url = session[:return_to]
  reset_session
  session[:return_to] = return_url
  session[:user_id] = current_user.id
  session[:timestamp] = Time.now.to_i
end