auth0 5.10.0 → 5.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +5 -4
- data/.devcontainer/devcontainer.json +1 -1
- data/.semgrepignore +6 -0
- data/CHANGELOG.md +29 -0
- data/DEVELOPMENT.md +35 -0
- data/EXAMPLES.md +220 -0
- data/Gemfile.lock +58 -66
- data/README.md +67 -253
- data/auth0.gemspec +0 -2
- data/examples/ruby-api/Gemfile.lock +5 -4
- data/examples/ruby-on-rails-api/README.md +0 -2
- data/lib/auth0/api/authentication_endpoints.rb +107 -13
- data/lib/auth0/api/v2/clients.rb +42 -0
- data/lib/auth0/api/v2/users.rb +116 -0
- data/lib/auth0/client_assertion.rb +45 -0
- data/lib/auth0/mixins/httpproxy.rb +5 -2
- data/lib/auth0/mixins/initializer.rb +2 -0
- data/lib/auth0/mixins/token_management.rb +1 -1
- data/lib/auth0/version.rb +1 -1
- data/opslevel.yml +5 -0
- data/spec/lib/auth0/api/authentication_endpoints_spec.rb +722 -0
- data/spec/lib/auth0/api/v2/clients_spec.rb +51 -0
- data/spec/lib/auth0/api/v2/users_spec.rb +218 -0
- data/spec/lib/auth0/mixins/httpproxy_spec.rb +38 -77
- data/spec/lib/auth0/mixins/initializer_spec.rb +79 -25
- data/spec/lib/auth0/mixins/token_management_spec.rb +45 -30
- data/spec/spec_helper.rb +0 -1
- data/spec/support/dummy_class_for_tokens.rb +3 -0
- metadata +9 -31
data/lib/auth0/api/v2/clients.rb
CHANGED
@@ -73,12 +73,54 @@ module Auth0
|
|
73
73
|
patch(path, options)
|
74
74
|
end
|
75
75
|
|
76
|
+
# Creates credentials for a client
|
77
|
+
# @param client_id [string] The Id of the client to update
|
78
|
+
# @param options [hash] The payload to send to the endpoint
|
79
|
+
def create_client_credentials(client_id, options)
|
80
|
+
raise Auth0::MissingClientId, 'Must specify a client id' if client_id.to_s.empty?
|
81
|
+
raise Auth0::MissingParameter, 'Must specify a valid body' if options.to_s.empty?
|
82
|
+
post(client_credentials_path(client_id), options)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Gets the credentials for a client
|
86
|
+
# @param client_id [string] The Id of the client
|
87
|
+
# @return [hash] The client credentials
|
88
|
+
def client_credentials(client_id)
|
89
|
+
raise Auth0::MissingClientId, 'Must specify a client id' if client_id.to_s.empty?
|
90
|
+
get(client_credentials_path(client_id))
|
91
|
+
end
|
92
|
+
alias get_client_credentials client_credentials
|
93
|
+
|
94
|
+
# Gets a client credential by ID
|
95
|
+
# @param client_id [string] The Id of the client
|
96
|
+
# @param credential_id [string] The Id of the credential to retrieve
|
97
|
+
# @return [hash] The credential
|
98
|
+
def client_credential(client_id, credential_id)
|
99
|
+
raise Auth0::MissingClientId, 'Must specify a client id' if client_id.to_s.empty?
|
100
|
+
raise Auth0::MissingParameter, 'Must specify a credential id' if credential_id.to_s.empty?
|
101
|
+
get("#{client_credentials_path(client_id)}/#{credential_id}")
|
102
|
+
end
|
103
|
+
alias get_client_credential client_credential
|
104
|
+
|
105
|
+
# Deletes a credential from the specified client
|
106
|
+
# @param client_id [string] The Id of the client
|
107
|
+
# @param credential_id [string] The Id of the credential to delete
|
108
|
+
def delete_client_credential(client_id, credential_id)
|
109
|
+
raise Auth0::MissingClientId, 'Must specify a client id' if client_id.to_s.empty?
|
110
|
+
raise Auth0::MissingParameter, 'Must specify a credential id' if credential_id.to_s.empty?
|
111
|
+
delete("#{client_credentials_path(client_id)}/#{credential_id}")
|
112
|
+
end
|
113
|
+
|
76
114
|
private
|
77
115
|
|
78
116
|
# Clients API path
|
79
117
|
def clients_path
|
80
118
|
@clients_path ||= '/api/v2/clients'
|
81
119
|
end
|
120
|
+
|
121
|
+
def client_credentials_path(client_id)
|
122
|
+
"#{clients_path}/#{client_id}/credentials"
|
123
|
+
end
|
82
124
|
end
|
83
125
|
end
|
84
126
|
end
|
data/lib/auth0/api/v2/users.rb
CHANGED
@@ -329,6 +329,122 @@ module Auth0
|
|
329
329
|
get "#{users_path}/#{user_id}/organizations"
|
330
330
|
end
|
331
331
|
|
332
|
+
# Get the available authentication methods for a user.
|
333
|
+
#
|
334
|
+
# @param user_id [string] The user ID of the authentication methods to get
|
335
|
+
# @param options [hash] A hash of options for getting permissions
|
336
|
+
# * :per_page [integer] The amount of permissions per page. (optional)
|
337
|
+
# * :page [integer] The page number. Zero based. (optional)
|
338
|
+
# * :include_totals [boolean] True if a query summary must be included in the result. (optional)
|
339
|
+
# @return [json] The user's authentication methods
|
340
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods
|
341
|
+
def user_authentication_methods(user_id, options = {})
|
342
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
343
|
+
|
344
|
+
request_params = {
|
345
|
+
per_page: options.fetch(:per_page, nil),
|
346
|
+
page: options.fetch(:page, nil),
|
347
|
+
include_totals: options.fetch(:include_totals, nil)
|
348
|
+
}
|
349
|
+
|
350
|
+
get "#{users_path}/#{user_id}/authentication-methods", request_params
|
351
|
+
end
|
352
|
+
alias get_user_authentication_methods user_authentication_methods
|
353
|
+
|
354
|
+
# Get a specific authentication method for a user.
|
355
|
+
#
|
356
|
+
# @param user_id [string] The user ID of the authentication methods to get
|
357
|
+
# @param authentication_method_id [string] The ID of the authentication method
|
358
|
+
# @return [json] The user authentication method
|
359
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods_by_authentication_method_id
|
360
|
+
def user_authentication_method(user_id, authentication_method_id)
|
361
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
362
|
+
raise Auth0::MissingParameter, 'Must supply a valid authentication_method_id' if authentication_method_id.to_s.empty?
|
363
|
+
|
364
|
+
get "#{users_path}/#{user_id}/authentication-methods/#{authentication_method_id}"
|
365
|
+
end
|
366
|
+
alias get_user_authentication_method user_authentication_method
|
367
|
+
|
368
|
+
# Create an authentication method for a user
|
369
|
+
#
|
370
|
+
# @param user_id [string] The user ID of the authentication methods to get
|
371
|
+
# @param body [hash] The post body content
|
372
|
+
# * :type [string] "phone" or "email" or "totp" or "webauthn-roaming"
|
373
|
+
# * :name [string] A human-readable label to identify the authentication method (optional)
|
374
|
+
# * :totp_secret [string] Base32 encoded secret for TOTP generation (optional)
|
375
|
+
# * :phone_number [string] Applies to phone authentication methods only. The destination phone number used to send verification codes via text and voice (optional)
|
376
|
+
# * :email [string] Applies to email authentication methods only. The email address used to send verification messages (optional)
|
377
|
+
# * :preferred_authentication_method [string] Preferred phone authentication method (optional)
|
378
|
+
# * :key_id [string] Applies to email webauthn authenticators only. The id of the credential (optional)
|
379
|
+
# * :public_key [string] Applies to email webauthn authenticators only. The public key (optional)
|
380
|
+
# * :relying_party_identifier [string] Applies to email webauthn authenticators only. The relying party identifier (optional)
|
381
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/post_authentication_methods
|
382
|
+
def post_user_authentication_method(user_id, body)
|
383
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
384
|
+
raise Auth0::MissingParameter, 'Must supply a body' if body.to_s.empty?
|
385
|
+
|
386
|
+
post "#{users_path}/#{user_id}/authentication-methods", body
|
387
|
+
end
|
388
|
+
alias create_user_authentication_method post_user_authentication_method
|
389
|
+
|
390
|
+
# Updates all authentication methods by replacing them with the given ones
|
391
|
+
#
|
392
|
+
# @param user_id [string] The user ID of the authentication methods to get
|
393
|
+
# @param body [hash array] The mehods to update
|
394
|
+
# * :type [string] "phone" or "email" or "totp" or "webauthn-roaming"
|
395
|
+
# * :name [string] A human-readable label to identify the authentication method (optional)
|
396
|
+
# * :totp_secret [string] Base32 encoded secret for TOTP generation (optional)
|
397
|
+
# * :phone_number [string] Applies to phone authentication methods only. The destination phone number used to send verification codes via text and voice (optional)
|
398
|
+
# * :email [string] Applies to email authentication methods only. The email address used to send verification messages (optional)
|
399
|
+
# * :preferred_authentication_method [string] Preferred phone authentication method (optional)
|
400
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/put_authentication_methods
|
401
|
+
def put_all_user_authentication_methods(user_id, body)
|
402
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
403
|
+
raise Auth0::MissingParameter, 'Must supply a body' if body.to_s.empty?
|
404
|
+
|
405
|
+
put "#{users_path}/#{user_id}/authentication-methods", body
|
406
|
+
end
|
407
|
+
alias update_all_user_authentication_methods put_all_user_authentication_methods
|
408
|
+
|
409
|
+
# Updates a user authentication method
|
410
|
+
#
|
411
|
+
# @param user_id [string] The user ID of the authentication methods to get
|
412
|
+
# @param body [hash array] The mehods to update
|
413
|
+
# * :name [string] A human-readable label to identify the authentication method (optional)
|
414
|
+
# * :preferred_authentication_method [string] Preferred phone authentication method (optional)
|
415
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/put_authentication_methods
|
416
|
+
def patch_user_authentication_method(user_id, authentication_method_id, body)
|
417
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
418
|
+
raise Auth0::MissingParameter, 'Must supply an authentication_method_id' if authentication_method_id.to_s.empty?
|
419
|
+
raise Auth0::MissingParameter, 'Must supply a body' if body.to_s.empty?
|
420
|
+
|
421
|
+
patch "#{users_path}/#{user_id}/authentication-methods/#{authentication_method_id}", body
|
422
|
+
end
|
423
|
+
alias update_user_authentication_method patch_user_authentication_method
|
424
|
+
|
425
|
+
# Deletes all of the user's authentication methods
|
426
|
+
#
|
427
|
+
# @param user_id [string] The user ID
|
428
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods
|
429
|
+
def delete_user_authentication_methods(user_id)
|
430
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
431
|
+
|
432
|
+
delete "#{users_path}/#{user_id}/authentication-methods"
|
433
|
+
end
|
434
|
+
|
435
|
+
|
436
|
+
# Deletes the user's authentication method specified by authentication_method_id
|
437
|
+
#
|
438
|
+
# @param user_id [string] The user ID
|
439
|
+
# @param authentication_method_id [string] The ID of the authentication method
|
440
|
+
# @see https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods_by_authentication_method_id
|
441
|
+
def delete_user_authentication_method(user_id, authentication_method_id)
|
442
|
+
raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty?
|
443
|
+
raise Auth0::MissingParameter, 'Must supply an authentication_method_id' if authentication_method_id.to_s.empty?
|
444
|
+
|
445
|
+
delete "#{users_path}/#{user_id}/authentication-methods/#{authentication_method_id}"
|
446
|
+
end
|
447
|
+
|
332
448
|
private
|
333
449
|
|
334
450
|
# Users API path
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jwt'
|
4
|
+
|
5
|
+
module Auth0
|
6
|
+
module ClientAssertion
|
7
|
+
CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'.freeze
|
8
|
+
|
9
|
+
# Adds keys into the supplied hash for either the client secret, or client assertion. If `client_assertion_signing_key` is not nil,
|
10
|
+
# it takes precedence over `client_secret`.
|
11
|
+
# @param [hash] The hash to add the keys to
|
12
|
+
# @param client_id [string] The client ID
|
13
|
+
# @param client_secret [string] The client secret
|
14
|
+
# @param client_assertion_signing_key [PKey] The key used to sign the client assertion JWT
|
15
|
+
# @param client_assertion_signing_alg [string] The algorithm used when signing the client assertion JWT
|
16
|
+
def populate_client_assertion_or_secret(hash,
|
17
|
+
domain: @domain,
|
18
|
+
client_id: @client_id,
|
19
|
+
client_secret: @client_secret,
|
20
|
+
client_assertion_signing_key: @client_assertion_signing_key,
|
21
|
+
client_assertion_signing_alg: @client_assertion_signing_alg)
|
22
|
+
|
23
|
+
if !client_assertion_signing_key.nil?
|
24
|
+
# Create JWT
|
25
|
+
now = Time.now.to_i
|
26
|
+
|
27
|
+
payload = {
|
28
|
+
iss: client_id,
|
29
|
+
sub: client_id,
|
30
|
+
aud: "https://#{domain}/",
|
31
|
+
iat: now,
|
32
|
+
exp: now + 180,
|
33
|
+
jti: SecureRandom.uuid
|
34
|
+
}
|
35
|
+
|
36
|
+
jwt = JWT.encode payload, client_assertion_signing_key, client_assertion_signing_alg
|
37
|
+
|
38
|
+
hash[:client_assertion] = jwt
|
39
|
+
hash[:client_assertion_type] = Auth0::ClientAssertion::CLIENT_ASSERTION_TYPE
|
40
|
+
else
|
41
|
+
hash[:client_secret] = client_secret
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -16,7 +16,7 @@ module Auth0
|
|
16
16
|
BASE_DELAY = 100
|
17
17
|
|
18
18
|
# proxying requests from instance methods to HTTP class methods
|
19
|
-
%i(get post post_file put patch delete delete_with_body).each do |method|
|
19
|
+
%i(get post post_file post_form put patch delete delete_with_body).each do |method|
|
20
20
|
define_method(method) do |uri, body = {}, extra_headers = {}|
|
21
21
|
body = body.delete_if { |_, v| v.nil? }
|
22
22
|
token = get_token()
|
@@ -85,9 +85,12 @@ module Auth0
|
|
85
85
|
elsif method == :post_file
|
86
86
|
body.merge!(multipart: true)
|
87
87
|
# Ignore the default Content-Type headers and let the HTTP client define them
|
88
|
-
post_file_headers = headers.
|
88
|
+
post_file_headers = headers.except('Content-Type') if headers != nil
|
89
89
|
# Actual call with the altered headers
|
90
90
|
call(:post, encode_uri(uri), timeout, post_file_headers, body)
|
91
|
+
elsif method == :post_form
|
92
|
+
form_post_headers = headers.except('Content-Type') if headers != nil
|
93
|
+
call(:post, encode_uri(uri), timeout, form_post_headers, body.compact)
|
91
94
|
else
|
92
95
|
call(method, encode_uri(uri), timeout, headers, body.to_json)
|
93
96
|
end
|
@@ -16,6 +16,8 @@ module Auth0
|
|
16
16
|
@headers = client_headers
|
17
17
|
@timeout = options[:timeout] || 10
|
18
18
|
@retry_count = options[:retry_count]
|
19
|
+
@client_assertion_signing_key = options[:client_assertion_signing_key]
|
20
|
+
@client_assertion_signing_alg = options[:client_assertion_signing_alg] || 'RS256';
|
19
21
|
extend Auth0::Api::AuthenticationEndpoints
|
20
22
|
@client_id = options[:client_id]
|
21
23
|
@client_secret = options[:client_secret]
|
@@ -17,7 +17,7 @@ module Auth0
|
|
17
17
|
# pp @token_expires_at
|
18
18
|
has_expired = @token && @token_expires_at ? @token_expires_at < (Time.now.to_i + 10) : false
|
19
19
|
|
20
|
-
if (@token.nil? || has_expired) && @client_id && @client_secret
|
20
|
+
if (@token.nil? || has_expired) && @client_id && (@client_secret || @client_assertion_signing_key)
|
21
21
|
response = api_token(audience: @audience)
|
22
22
|
@token = response.token
|
23
23
|
@token_expires_at = response.expires_in ? Time.now.to_i + response.expires_in : nil
|
data/lib/auth0/version.rb
CHANGED