Module: JwtAuthCognito::AuthorizationConcern

Extended by:
ActiveSupport::Concern
Defined in:
lib/jwt_auth_cognito/authorization_concern.rb

Overview

Rails Concern that adds granular permission enforcement to controllers.

Usage in ApplicationController (or any controller):

include JwtAuthCognito::AuthorizationConcern

# Provide the validator instance (required):
def jwt_validator
  @jwt_validator ||= JwtAuthCognito::JwtValidator.new
end

# Provide the current user's Cognito sub (required):
# Override jwt_user_id — typically populated by your auth before_action.
def jwt_user_id
  @jwt_user_id ||= request.env['jwt.payload']&.dig('sub')
end

Then in any action or before_action:

before_action -> { authorize_permission!('fleet:vehicles:read') }

# OR require at least one of several permissions:
before_action -> { authorize_any_permission!('fleet:read', 'fleet:vehicles:read') }

appId and orgId are resolved from X-App-Id / X-Organization-Id headers, falling back to params / params.

Instance Method Summary collapse

Instance Method Details

#authorize_any_permission!(*permissions) ⇒ Object

Raises ForbiddenError unless the current user has AT LEAST ONE of the given permissions.



50
51
52
53
54
55
# File 'lib/jwt_auth_cognito/authorization_concern.rb', line 50

def authorize_any_permission!(*permissions)
  return if permissions.flatten.any? { |p| current_user_has_permission?(p) }

  log_permission_denied(permissions)
  raise JwtAuthCognito::ForbiddenError, 'Access denied'
end

#authorize_permission!(*permissions) ⇒ Object

Raises ForbiddenError unless the current user has ALL of the given permissions.



40
41
42
43
44
45
46
47
# File 'lib/jwt_auth_cognito/authorization_concern.rb', line 40

def authorize_permission!(*permissions)
  permissions.flatten.each do |permission|
    next if current_user_has_permission?(permission)

    log_permission_denied(permissions)
    raise JwtAuthCognito::ForbiddenError, 'Access denied'
  end
end

#authorize_resource_permission!(permission, resource_id: params[:id]) ⇒ Object

Raises ForbiddenError unless the user has the given permission over a specific resource. By convention reads the resource ID from params; override with resource_id: keyword arg.

before_action -> { authorize_resource_permission!('fleet:vehicles:write') }, only: [:update]
before_action -> { authorize_resource_permission!('fleet:vehicles:write', resource_id: params[:vehicle_id]) }


67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/jwt_auth_cognito/authorization_concern.rb', line 67

def authorize_resource_permission!(permission, resource_id: params[:id])
  uid = jwt_user_id
  aid = jwt_app_id
  oid = jwt_org_id

  raise JwtAuthCognito::ForbiddenError, 'Access denied' unless uid && aid && oid && resource_id

  return if jwt_validator.check_resource_permission?(uid, aid, oid, resource_id.to_s, permission)

  log_resource_permission_denied(permission, resource_id)
  raise JwtAuthCognito::ForbiddenError, 'Access denied'
end

#current_user_permissionsObject

Returns the full list of effective permissions for the current user/app/org context.



58
59
60
# File 'lib/jwt_auth_cognito/authorization_concern.rb', line 58

def current_user_permissions
  @current_user_permissions ||= fetch_current_user_permissions
end