Class: KeycloakApiRails::Helper

Inherits:
Object
  • Object
show all
Defined in:
lib/keycloak-api-rails/helper.rb

Constant Summary collapse

CURRENT_USER_ID_KEY =
"keycloak:keycloak_id"
CURRENT_AUTHORIZED_PARTY_KEY =
"keycloak:authorized_party"
CURRENT_USER_EMAIL_KEY =
"keycloak:email"
CURRENT_USER_LOCALE_KEY =
"keycloak:locale"
CURRENT_USER_ATTRIBUTES =
"keycloak:attributes"
ROLES_KEY =
"keycloak:roles"
RESOURCE_ROLES_KEY =
"keycloak:resource_roles"
TOKEN_KEY =
"keycloak:token"
QUERY_STRING_TOKEN_KEY =
"authorizationToken"
BEARER_PREFIX =

RFC 7235 makes the authentication scheme case-insensitive.

/\ABearer[[:space:]]+/i.freeze

Class Method Summary collapse

Class Method Details

.assign_current_authorized_party(env, token) ⇒ Object



46
47
48
# File 'lib/keycloak-api-rails/helper.rb', line 46

def self.assign_current_authorized_party(env, token)
  env[CURRENT_AUTHORIZED_PARTY_KEY] = token["azp"]
end

.assign_current_user_custom_attributes(env, token, attribute_names) ⇒ Object



85
86
87
88
# File 'lib/keycloak-api-rails/helper.rb', line 85

def self.assign_current_user_custom_attributes(env, token, attribute_names)
  names = Array(attribute_names)
  env[CURRENT_USER_ATTRIBUTES] = token.select { |key, _value| names.include?(key) }
end

.assign_current_user_email(env, token) ⇒ Object



54
55
56
# File 'lib/keycloak-api-rails/helper.rb', line 54

def self.assign_current_user_email(env, token)
  env[CURRENT_USER_EMAIL_KEY] = token["email"]
end

.assign_current_user_id(env, token) ⇒ Object



30
31
32
# File 'lib/keycloak-api-rails/helper.rb', line 30

def self.assign_current_user_id(env, token)
  env[CURRENT_USER_ID_KEY] = token["sub"]
end

.assign_current_user_locale(env, token) ⇒ Object



62
63
64
# File 'lib/keycloak-api-rails/helper.rb', line 62

def self.assign_current_user_locale(env, token)
  env[CURRENT_USER_LOCALE_KEY] = token["locale"]
end

.assign_keycloak_token(env, token) ⇒ Object



38
39
40
# File 'lib/keycloak-api-rails/helper.rb', line 38

def self.assign_keycloak_token(env, token)
  env[TOKEN_KEY] = token
end

.assign_realm_roles(env, token) ⇒ Object



70
71
72
# File 'lib/keycloak-api-rails/helper.rb', line 70

def self.assign_realm_roles(env, token)
  env[ROLES_KEY] = token.dig("realm_access", "roles")
end

.assign_resource_roles(env, token) ⇒ Object



78
79
80
81
82
83
# File 'lib/keycloak-api-rails/helper.rb', line 78

def self.assign_resource_roles(env, token)
  env[RESOURCE_ROLES_KEY] = token.fetch("resource_access", {}).inject({}) do |resource_roles, (name, resource_attributes)|
    resource_roles[name] = resource_attributes.fetch("roles", [])
    resource_roles
  end
end

.assign_token(env, token, custom_attribute_names) ⇒ Object



15
16
17
18
19
20
21
22
23
24
# File 'lib/keycloak-api-rails/helper.rb', line 15

def self.assign_token(env, token, custom_attribute_names)
  assign_current_user_id(env, token)
  assign_current_authorized_party(env, token)
  assign_current_user_email(env, token)
  assign_current_user_locale(env, token)
  assign_current_user_custom_attributes(env, token, custom_attribute_names)
  assign_realm_roles(env, token)
  assign_resource_roles(env, token)
  assign_keycloak_token(env, token)
end

.create_url_with_token(uri, token) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/keycloak-api-rails/helper.rb', line 118

def self.create_url_with_token(uri, token)
  uri       = URI(uri)
  params    = URI.decode_www_form(uri.query || "").reject { |query_string| query_string.first == QUERY_STRING_TOKEN_KEY }
  params    << [QUERY_STRING_TOKEN_KEY, token]
  uri.query = URI.encode_www_form(params)
  uri.to_s
end

.current_authorized_party(env) ⇒ Object



42
43
44
# File 'lib/keycloak-api-rails/helper.rb', line 42

def self.current_authorized_party(env)
  env[CURRENT_AUTHORIZED_PARTY_KEY]
end

.current_resource_roles(env) ⇒ Object



74
75
76
# File 'lib/keycloak-api-rails/helper.rb', line 74

def self.current_resource_roles(env)
  env[RESOURCE_ROLES_KEY]
end

.current_user_custom_attributes(env) ⇒ Object



90
91
92
# File 'lib/keycloak-api-rails/helper.rb', line 90

def self.current_user_custom_attributes(env)
  env[CURRENT_USER_ATTRIBUTES]
end

.current_user_email(env) ⇒ Object



50
51
52
# File 'lib/keycloak-api-rails/helper.rb', line 50

def self.current_user_email(env)
  env[CURRENT_USER_EMAIL_KEY]
end

.current_user_id(env) ⇒ Object



26
27
28
# File 'lib/keycloak-api-rails/helper.rb', line 26

def self.current_user_id(env)
  env[CURRENT_USER_ID_KEY]
end

.current_user_locale(env) ⇒ Object



58
59
60
# File 'lib/keycloak-api-rails/helper.rb', line 58

def self.current_user_locale(env)
  env[CURRENT_USER_LOCALE_KEY]
end

.current_user_roles(env) ⇒ Object



66
67
68
# File 'lib/keycloak-api-rails/helper.rb', line 66

def self.current_user_roles(env)
  env[ROLES_KEY]
end

.keycloak_token(env) ⇒ Object



34
35
36
# File 'lib/keycloak-api-rails/helper.rb', line 34

def self.keycloak_token(env)
  env[TOKEN_KEY]
end

.read_token_from_headers(headers) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/keycloak-api-rails/helper.rb', line 126

def self.read_token_from_headers(headers)
  authorization = headers["HTTP_AUTHORIZATION"]
  if authorization.nil?
    ""
  else
    authorization.sub(BEARER_PREFIX, "")
  end
end

.read_token_from_query_string(uri) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/keycloak-api-rails/helper.rb', line 105

def self.read_token_from_query_string(uri)
  if uri && !uri.strip.empty?
    parsed_uri         = URI.parse(uri)
    query              = URI.decode_www_form(parsed_uri.query || "")
    query_string_token = query.detect { |param| param.first == QUERY_STRING_TOKEN_KEY }
    query_string_token&.at(1)
  else
    ""
  end
rescue URI::InvalidURIError, ArgumentError
  nil
end

.request_uri(env) ⇒ Object



94
95
96
97
98
99
100
101
102
103
# File 'lib/keycloak-api-rails/helper.rb', line 94

def self.request_uri(env)
  # 'REQUEST_URI' is not part of the Rack spec: Puma and Unicorn do set it
  if env["REQUEST_URI"].nil?
    query_string = env["QUERY_STRING"]
    path         = env["PATH_INFO"].to_s
    query_string.nil? || query_string.empty? ? path : "#{path}?#{query_string}"
  else
    env["REQUEST_URI"]
  end
end