Module: Fluence::Gateway::Auth::GatewayAuthentication

Extended by:
ActiveSupport::Concern
Defined in:
lib/fluence/gateway/auth/gateway_authentication.rb

Overview

Note:

The scope name is captured at include time. Changing Configuration#scope_name afterwards has no effect on already-defined helpers.

Controller concern that reads the gateway identity headers and exposes scope-prefixed authentication helpers.

When the concern is included, five instance methods are defined on the host controller class (via define_method), where <scope> is Configuration#scope_name:

  • current_<scope> — memoised lookup of the user record.
  • <scope>_signed_in?true when current_<scope> is present.
  • authenticate_<scope>! — renders 401 when the user is absent.
  • authenticate_<scope>_or_service! — renders 401 unless the request is either signed-in or a client_credentials service call (see #service_request?).
  • authenticate_<scope>_or_redirect! — like authenticate_<scope>! for HTML navigation: an unauthenticated GET text/html request is redirected to the gateway login with return_to; anything else gets 401. Requires a redirect-capable host (+ActionController::Base+).

The record is looked up via model_class.find_by(subject_column => gateway_user_id). If no record matches and Configuration#on_missing_user is set, it is invoked for just-in-time provisioning.

In Rails, Railtie includes this concern automatically in ActionController::API and ActionController::Base subclasses.

Examples:

Default configuration (user_model = 'User')

class ApplicationController < ActionController::API
  include Fluence::Gateway::Auth::GatewayAuthentication
  before_action :authenticate_user!
end

Custom user model

Fluence::Gateway::Auth.configure { |c| c.user_model = 'Account' }
# helpers become: current_account / account_signed_in? /
#                 authenticate_account! / authenticate_account_or_service! /
#                 authenticate_account_or_redirect!

Constant Summary collapse

GATEWAY_LOGOUT_PATH =

Path of the gateway logout endpoint, used by #gateway_logout_path. Only meaningful for server-rendered tenants where the gateway owns the session cookie.

'/auth/logout'
GATEWAY_LOGIN_PATH =

Path of the gateway OAuth initiation endpoint, used by authenticate_<scope>_or_redirect! to send unauthenticated HTML navigation to login. Only meaningful for server-rendered tenants proxied through the gateway catch-all.

'/auth'

Instance Method Summary collapse

Instance Method Details

#anonymous_request?Boolean

True when the request carries no identity at all — the gateway forwarded it anonymously (no credential presented). Derived from the signed X-Client-Id / X-User-Id headers, not from the informational #gateway_auth header: both identity headers are part of the HMAC payload, so an anonymous request cannot forge an identity.

Mutually exclusive with #service_request? and with a signed-in user: user (+user_id+ present), service (+client_id+ present, user_id blank), anonymous (both blank).

Only meaningful behind the HMAC middleware: without it (or with skip_middleware enabled) absent headers also yield true.

Examples:

Public endpoint with differentiated behaviour

def index
  scope = anonymous_request? ? Project.public_listed : current_user.projects
  render json: scope
end

Returns:

  • (Boolean)

#authenticate_service!void

This method returns an undefined value.

Renders 401 unless the request is a client_credentials service call (see #service_request?). Use as a before_action on endpoints exposed exclusively to backend services.

Examples:

Service-only endpoint

class Api::InternalController < ApplicationController
  before_action :authenticate_service!
end

#gateway_authString?

Raw value of the X-Gateway-Auth header (+'anonymous'+ or 'authenticated'). Informational only: the header is NOT part of the HMAC payload — derive trust from the signed identity headers instead (see #anonymous_request?).

Returns:

  • (String, nil)

#gateway_client_idString?

Raw value of the X-Client-Id header (the Doorkeeper application uid).

Returns:

  • (String, nil)

#gateway_login_path(return_to: nil) ⇒ String

Path of the gateway login (OAuth initiation) endpoint, optionally carrying a return_to so the user lands back where they started. Counterpart of #gateway_logout_path; used internally by authenticate_<scope>_or_redirect!.

Examples:

Login link on a public page

<%= link_to 'Log in', gateway_login_path(return_to: request.fullpath) %>

Parameters:

  • return_to (String, nil) (defaults to: nil)

    path to return to after login

Returns:

#gateway_logout_pathString

Path of the gateway logout endpoint. Only meaningful for server-rendered tenants where the gateway holds the session cookie; SPA tenants drop their token client-side and have no server-side logout to call.

Examples:

In an ERB layout

<%= link_to 'Logout', gateway_logout_path, data: { turbo_method: :delete } %>

Returns:

#gateway_user_emailString?

Raw value of the X-User-Email header.

Returns:

  • (String, nil)

    nil when the gateway did not forward an email (typical of service requests).

#gateway_user_first_nameString?

Raw value of the X-User-First-Name header.

Returns:

  • (String, nil)

#gateway_user_idString?

Raw value of the X-User-Id header (the gateway subject).

Returns:

  • (String, nil)

    nil on anonymous or service requests.

#gateway_user_last_nameString?

Raw value of the X-User-Last-Name header.

Returns:

  • (String, nil)

#gateway_user_scopesString?

Raw value of the X-User-Scopes header (space-separated OAuth scopes, as emitted by Doorkeeper).

Returns:

  • (String, nil)

#service_request?Boolean

True when the request carries a client identity but no user, i.e. it was issued with a client_credentials token.

Returns:

  • (Boolean)