stormpath-sdk 1.1.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -0
  3. data/.ruby-gemset +0 -0
  4. data/.travis.yml +1 -0
  5. data/CHANGES.md +20 -0
  6. data/Gemfile +0 -0
  7. data/README.md +78 -2
  8. data/Rakefile +0 -0
  9. data/lib/stormpath-sdk/api_key.rb +0 -0
  10. data/lib/stormpath-sdk/auth/authentication_result.rb +0 -0
  11. data/lib/stormpath-sdk/auth/basic_authenticator.rb +0 -0
  12. data/lib/stormpath-sdk/auth/basic_login_attempt.rb +0 -0
  13. data/lib/stormpath-sdk/auth/http_basic_authentication.rb +47 -0
  14. data/lib/stormpath-sdk/auth/http_bearer_authentication.rb +27 -0
  15. data/lib/stormpath-sdk/auth/username_password_request.rb +0 -0
  16. data/lib/stormpath-sdk/cache/cache.rb +0 -0
  17. data/lib/stormpath-sdk/cache/cache_entry.rb +0 -0
  18. data/lib/stormpath-sdk/cache/cache_manager.rb +0 -0
  19. data/lib/stormpath-sdk/cache/cache_stats.rb +0 -0
  20. data/lib/stormpath-sdk/cache/disabled_cache_store.rb +0 -0
  21. data/lib/stormpath-sdk/cache/memcached_store.rb +37 -0
  22. data/lib/stormpath-sdk/cache/memory_store.rb +0 -0
  23. data/lib/stormpath-sdk/cache/redis_store.rb +0 -0
  24. data/lib/stormpath-sdk/client.rb +0 -0
  25. data/lib/stormpath-sdk/data_store.rb +1 -0
  26. data/lib/stormpath-sdk/error.rb +5 -5
  27. data/lib/stormpath-sdk/http/authc/sauthc1_signer.rb +0 -0
  28. data/lib/stormpath-sdk/http/http_client_request_executor.rb +2 -3
  29. data/lib/stormpath-sdk/http/request.rb +12 -10
  30. data/lib/stormpath-sdk/http/response.rb +0 -0
  31. data/lib/stormpath-sdk/http/utils.rb +8 -5
  32. data/lib/stormpath-sdk/id_site/id_site_result.rb +0 -0
  33. data/lib/stormpath-sdk/oauth/access_token_authentication_result.rb +0 -0
  34. data/lib/stormpath-sdk/oauth/authenticator.rb +2 -1
  35. data/lib/stormpath-sdk/oauth/error.rb +12 -8
  36. data/lib/stormpath-sdk/oauth/id_site_grant_request.rb +0 -0
  37. data/lib/stormpath-sdk/oauth/local_access_token_verification.rb +45 -0
  38. data/lib/stormpath-sdk/oauth/password_grant.rb +9 -7
  39. data/lib/stormpath-sdk/oauth/password_grant_request.rb +3 -2
  40. data/lib/stormpath-sdk/oauth/refresh_grant_request.rb +0 -0
  41. data/lib/stormpath-sdk/oauth/remote_access_token_verification.rb +28 -0
  42. data/lib/stormpath-sdk/oauth/social_grant.rb +27 -0
  43. data/lib/stormpath-sdk/oauth/social_grant_request.rb +14 -0
  44. data/lib/stormpath-sdk/oauth/stormpath_grant_request.rb +3 -2
  45. data/lib/stormpath-sdk/oauth/verify_access_token.rb +11 -6
  46. data/lib/stormpath-sdk/oauth/{verify_token.rb → verify_token_result.rb} +1 -1
  47. data/lib/stormpath-sdk/provider/account_access.rb +0 -0
  48. data/lib/stormpath-sdk/provider/account_request.rb +0 -0
  49. data/lib/stormpath-sdk/provider/account_resolver.rb +0 -0
  50. data/lib/stormpath-sdk/provider/account_result.rb +0 -0
  51. data/lib/stormpath-sdk/provider/facebook/facebook_provider.rb +0 -0
  52. data/lib/stormpath-sdk/provider/facebook/facebook_provider_data.rb +0 -0
  53. data/lib/stormpath-sdk/provider/github/github_provider.rb +0 -0
  54. data/lib/stormpath-sdk/provider/github/github_provider_data.rb +0 -0
  55. data/lib/stormpath-sdk/provider/google/google_provider.rb +0 -0
  56. data/lib/stormpath-sdk/provider/google/google_provider_data.rb +0 -1
  57. data/lib/stormpath-sdk/provider/linkedin/linkedin_provider.rb +0 -0
  58. data/lib/stormpath-sdk/provider/linkedin/linkedin_provider_data.rb +0 -0
  59. data/lib/stormpath-sdk/provider/provider.rb +0 -0
  60. data/lib/stormpath-sdk/provider/provider_data.rb +0 -0
  61. data/lib/stormpath-sdk/provider/saml/saml_mapping_rules.rb +0 -0
  62. data/lib/stormpath-sdk/provider/saml/saml_provider.rb +0 -0
  63. data/lib/stormpath-sdk/provider/saml/saml_provider_data.rb +0 -0
  64. data/lib/stormpath-sdk/provider/saml/saml_provider_metadata.rb +0 -0
  65. data/lib/stormpath-sdk/provider/stormpath/stormpath_provider.rb +0 -0
  66. data/lib/stormpath-sdk/provider/stormpath/stormpath_provider_data.rb +0 -0
  67. data/lib/stormpath-sdk/resource/access_token.rb +0 -0
  68. data/lib/stormpath-sdk/resource/account_creation_policy.rb +3 -1
  69. data/lib/stormpath-sdk/resource/account_membership.rb +0 -0
  70. data/lib/stormpath-sdk/resource/account_overrides.rb +0 -0
  71. data/lib/stormpath-sdk/resource/account_store.rb +7 -8
  72. data/lib/stormpath-sdk/resource/account_store_mapping.rb +0 -0
  73. data/lib/stormpath-sdk/resource/application.rb +5 -5
  74. data/lib/stormpath-sdk/resource/base.rb +0 -0
  75. data/lib/stormpath-sdk/resource/collection.rb +0 -0
  76. data/lib/stormpath-sdk/resource/custom_data.rb +0 -0
  77. data/lib/stormpath-sdk/resource/custom_data_hash_methods.rb +0 -0
  78. data/lib/stormpath-sdk/resource/custom_data_storage.rb +0 -0
  79. data/lib/stormpath-sdk/resource/directory.rb +1 -0
  80. data/lib/stormpath-sdk/resource/email_template.rb +0 -0
  81. data/lib/stormpath-sdk/resource/email_verification_token.rb +0 -0
  82. data/lib/stormpath-sdk/resource/error.rb +2 -3
  83. data/lib/stormpath-sdk/resource/expansion.rb +0 -0
  84. data/lib/stormpath-sdk/resource/group.rb +0 -0
  85. data/lib/stormpath-sdk/resource/group_membership.rb +0 -0
  86. data/lib/stormpath-sdk/resource/instance.rb +0 -0
  87. data/lib/stormpath-sdk/resource/oauth_policy.rb +0 -0
  88. data/lib/stormpath-sdk/resource/organization.rb +1 -1
  89. data/lib/stormpath-sdk/resource/organization_account_store_mapping.rb +0 -0
  90. data/lib/stormpath-sdk/resource/password_policy.rb +0 -0
  91. data/lib/stormpath-sdk/resource/password_reset_token.rb +0 -0
  92. data/lib/stormpath-sdk/resource/password_strength.rb +0 -0
  93. data/lib/stormpath-sdk/resource/refresh_token.rb +0 -0
  94. data/lib/stormpath-sdk/resource/tenant.rb +0 -0
  95. data/lib/stormpath-sdk/resource/utils.rb +0 -0
  96. data/lib/stormpath-sdk/resource/verification_email.rb +0 -0
  97. data/lib/stormpath-sdk/util/assert.rb +0 -0
  98. data/lib/stormpath-sdk/util/uri_builder.rb +38 -0
  99. data/lib/stormpath-sdk/version.rb +2 -2
  100. data/lib/stormpath-sdk.rb +47 -39
  101. data/spec/api_key_spec.rb +0 -0
  102. data/spec/auth/basic_authenticator_spec.rb +0 -0
  103. data/spec/auth/http_basic_authentication_spec.rb +86 -0
  104. data/spec/auth/http_bearer_authentication_spec.rb +86 -0
  105. data/spec/auth/sauthc1_signer_spec.rb +0 -0
  106. data/spec/cache/cache_entry_spec.rb +0 -0
  107. data/spec/cache/cache_spec.rb +0 -0
  108. data/spec/cache/cache_stats_spec.rb +0 -0
  109. data/spec/client_spec.rb +0 -0
  110. data/spec/data_store_spec.rb +40 -16
  111. data/spec/fixtures/response/create_saml_directory.json +0 -0
  112. data/spec/fixtures/response/create_saml_directory_mapping_rules.json +0 -0
  113. data/spec/fixtures/response/get_saml_directory_provider.json +0 -0
  114. data/spec/fixtures/response/get_saml_directory_provider_metadata.json +0 -0
  115. data/spec/oauth/access_token_authentication_result_spec.rb +8 -0
  116. data/spec/provider/account_resolver_spec.rb +0 -0
  117. data/spec/provider/provider_spec.rb +0 -0
  118. data/spec/resource/account_creation_policy_spec.rb +125 -2
  119. data/spec/resource/account_store_mapping_spec.rb +0 -0
  120. data/spec/resource/account_store_spec.rb +40 -13
  121. data/spec/resource/application_spec.rb +268 -51
  122. data/spec/resource/base_spec.rb +0 -0
  123. data/spec/resource/collection_spec.rb +60 -2
  124. data/spec/resource/custom_data_spec.rb +0 -0
  125. data/spec/resource/directory_spec.rb +82 -1
  126. data/spec/resource/email_template_spec.rb +0 -0
  127. data/spec/resource/expansion_spec.rb +0 -0
  128. data/spec/resource/group_membership_spec.rb +0 -0
  129. data/spec/resource/group_spec.rb +0 -0
  130. data/spec/resource/organization_spec.rb +37 -8
  131. data/spec/resource/password_policy_spec.rb +0 -0
  132. data/spec/resource/password_strength_spec.rb +0 -0
  133. data/spec/resource/status_spec.rb +0 -0
  134. data/spec/resource/tenant_spec.rb +0 -0
  135. data/spec/spec_helper.rb +5 -6
  136. data/spec/support/custom_data_storage_behavior.rb +0 -0
  137. data/spec/support/mocked_provider_accounts.rb +129 -117
  138. data/spec/support/resource_factory.rb +0 -0
  139. data/spec/support/resource_matchers.rb +7 -0
  140. data/spec/support/test_cache_stores.rb +0 -0
  141. data/spec/support/test_request_executor.rb +0 -0
  142. data/spec/util/uri_builder_spec.rb +47 -0
  143. data/stormpath-sdk.gemspec +1 -0
  144. data/support/api.rb +0 -0
  145. metadata +29 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46abd12e70ce4548e31d07ce66c71ba8dab69f2f
4
- data.tar.gz: 78fad31579495fabac7d82f64116ea20bd2bd6dc
3
+ metadata.gz: 23386924f0b6cb041d80e4900d5cba99cc93da80
4
+ data.tar.gz: 7e9d14180ef6f5e6fadfcb11836cf4e3ceca7ba5
5
5
  SHA512:
6
- metadata.gz: 9b73fa8bebef8366861da8e42a728d3a08bb505454d54240656cea0e013d5800e414c585ced352ea9bcb77b8f145277d95ac1fba737b11040c5616224afcd33b
7
- data.tar.gz: ba78d09dfed54133aa832f5853e79258f48216f726d25d4aa3942b7fba1654e4bf7a425f87f3947ca51dc99742061da79fba996970cf44f233a9b51b9e2394b7
6
+ metadata.gz: 15039329aa8f769f5b73bd763e2bb29df905a26f06782f7dcaac8cc17a5140f5244e2fb42d66d19afb4613d4dc833536c1e55994bc1e545e003a8252a858ffea
7
+ data.tar.gz: be5240dbe085d0566b3a1e1fb4a8cc39c0b566d7b7958fa655b373834a7c98be4f4885d7cb74547e9f4158cccc595540d04bcf4859033d840e8186caa8638e5f
data/.gitignore CHANGED
File without changes
data/.ruby-gemset CHANGED
File without changes
data/.travis.yml CHANGED
@@ -4,6 +4,7 @@ rvm:
4
4
  - 2.3.1
5
5
  services:
6
6
  - redis-server
7
+ - memcached
7
8
  before_install:
8
9
  - gem install bundler
9
10
  env:
data/CHANGES.md CHANGED
@@ -1,6 +1,26 @@
1
1
  stormpath-sdk-ruby Changelog
2
2
  ============================
3
3
 
4
+ Version 1.2.0
5
+ -------------
6
+
7
+ Released on October 27, 2016
8
+
9
+ - Add memcached store as option for the cache store
10
+ - Implement http basic and bearer access token validation
11
+ - Add get and create method on organizations accounts collection
12
+ - Implement option to verify access_token locally and adjust current interface for it
13
+ - Fix bug with searching accounts by custom data attributes
14
+ - Fix bug when loading application that has a forward slash in client_id or client_secret
15
+ - Add organizations endpoint on directory
16
+ - Add option to exchange stormpath_token for an access_token with the registered status
17
+ - Add support for organizationNameKey for oauth token exchange
18
+ - Create social grant request as a new type of grant requests
19
+ - Add request id to error resources
20
+ - Support blacklisting/whitelisting domains in account creation policies for directories
21
+ - Add 'Organization' as a valid type of account store
22
+
23
+
4
24
  Version 1.1.5
5
25
  -------------
6
26
 
data/Gemfile CHANGED
File without changes
data/README.md CHANGED
@@ -10,7 +10,7 @@ application.
10
10
  ## Install
11
11
 
12
12
  ```sh
13
- $ gem install stormpath-sdk --pre
13
+ $ gem install stormpath-sdk
14
14
  ```
15
15
 
16
16
  ## Provision Your Stormpath Account
@@ -193,6 +193,25 @@ in the hash of values passed on Client initialization:
193
193
  client = application.client
194
194
  ```
195
195
 
196
+ To change the base_url for the Enterprise product, pass the following option to `Stormpath::Client.new()` :
197
+
198
+ ```ruby
199
+ client = Stormpath::Client.new(
200
+ api_key_file_location: '/some/path/to/apiKey.properties',
201
+ base_url: 'https://enterprise.stormpath.io/v1'
202
+ )
203
+ ```
204
+
205
+ * By passing a composite application url to `Application.load`:
206
+
207
+ ```ruby
208
+ composite_url = "http://#{api_key_id}:#{api_key_secret}@api.stormpath.com/v1/applications/#{application_id}"
209
+
210
+ application = Stormpath::Resource::Application.load composite_url
211
+ client = application.client
212
+ ```
213
+
214
+
196
215
  ### Accessing Resources
197
216
 
198
217
  Most of the work you do with Stormpath is done through the applications
@@ -378,6 +397,22 @@ Again, with all these methods, You will want your application to link to an inte
378
397
  > NOTE:
379
398
  > A JWT will expire after 60 seconds of creation.
380
399
 
400
+ #### Fetch Stormpath Access Token with username and password
401
+ Stormpath can generate a brand new Access Token using the password grant type: User's credentials.
402
+
403
+ To fetch the oauth token use the following snippet
404
+ ```ruby
405
+ grant_request = Stormpath::Oauth::PasswordGrantRequest.new(email, password)
406
+ response = application.authenticate_oauth(grant_request)
407
+ ```
408
+
409
+ Just like with logging-in a user, it is possible to generate a token against a particular Application’s Account Store or Organization. To do so, specify the Account Store’s href or Organization’s nameKey as a parameter in the request:
410
+
411
+ ```ruby
412
+ grant_request = Stormpath::Oauth::PasswordGrantRequest.new(email, password, organization_name_key: 'my-stormpath-organization')
413
+ response = application.authenticate_oauth(grant_request)
414
+ ```
415
+
381
416
  #### Exchange ID Site token for a Stormpath Access Token
382
417
  After the user has been authenticated via ID Site, a developer may want to control their authorization with an OAuth 2.0 Token.
383
418
  This is done by passing the JWT similar to the way we passed the user’s credentials as described in [Generating an OAuth 2.0 Access Token][generate-oauth-access-token].
@@ -414,6 +449,45 @@ puts authentication_result.access_token
414
449
  puts authentication_result.refresh_token
415
450
  ```
416
451
 
452
+ ### Exchange ID site token for a Stormpath Access Token
453
+
454
+ As a developer, I want to authenticate the user on ID Site but get an access token that I can store on the client to use to access my API.
455
+ The oauth token endpoint will validate that:
456
+ * the JWT is not tampered
457
+ * has not expired
458
+ * the account is still associated with the application and will return an access token
459
+ * the status claim is either AUTHENTICATED or REGISTERED
460
+
461
+ If you want to create a stormpath grant request with status <code>authenticated</code> you need to pass the account, application and api key id:
462
+
463
+ ```ruby
464
+ stormpath_grant_request = Stormpath::Oauth::StormpathGrantRequest.new(
465
+ account,
466
+ application,
467
+ api_key_id
468
+ )
469
+ ```
470
+
471
+ If you have the status attribute set to <code>registered</code> then create the request like so:
472
+
473
+ ```ruby
474
+ stormpath_grant_request = Stormpath::Oauth::StormpathGrantRequest.new(
475
+ account,
476
+ application,
477
+ api_key_id,
478
+ :registered
479
+ )
480
+ ```
481
+
482
+ And lastly authenticate with the created request instance:
483
+
484
+ ```ruby
485
+ authentication_result = application.authenticate_oauth(stormpath_grant_request)
486
+
487
+ puts authentication_result.access_token
488
+ puts authentication_result.refresh_token
489
+ ```
490
+
417
491
  ### Registering Accounts
418
492
 
419
493
  Accounts are created on a directory instance. They can be created in two
@@ -478,8 +552,9 @@ end
478
552
  If you are moving from an existing user repository to Stormpath, you may have existing password hashes that you want to reuse to provide a seamless upgrade path for your end users.
479
553
  More info about this feature can be found [here][mcf-hash-password-doc]
480
554
 
481
- Example of creating an account with existing SHA-512 password hash. For details on other hashing algorithms chech the [documentation][stormpaht-hash-algorithm]
555
+ Example of creating an account with existing SHA-512 password hash. For details on other hashing algorithms check the [documentation][stormpath-hash-algorithm]
482
556
 
557
+ ```ruby
483
558
  directory.accounts.create({
484
559
  username: "jlucpicard",
485
560
  email: "captain@enterprise.com",
@@ -487,6 +562,7 @@ directory.accounts.create({
487
562
  surname: "Picard",
488
563
  password: "$stormpath2$SHA-512$1$ZFhBRmpFSnEwVEx2ekhKS0JTMDJBNTNmcg==$Q+sGFg9e+pe9QsUdfnbJUMDtrQNf27ezTnnGllBVkQpMRc9bqH6WkyE3y0svD/7cBk8uJW9Wb3dolWwDtDLFjg=="
489
564
  }, password_format: 'mcf')
565
+ ```
490
566
 
491
567
  ### Authentication
492
568
 
data/Rakefile CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,47 @@
1
+ module Stormpath
2
+ module Authentication
3
+ class HttpBasicAuthentication
4
+ BASIC_PATTERN = /^Basic /
5
+ attr_reader :application, :authorization_header
6
+
7
+ def initialize(application, authorization_header)
8
+ @application = application
9
+ @authorization_header = authorization_header
10
+ raise Stormpath::Error if authorization_header.nil?
11
+ end
12
+
13
+ def authenticate!
14
+ raise Stormpath::Error if fetched_api_key.nil?
15
+ raise Stormpath::Error if fetched_api_key.secret != api_key_secret
16
+ fetched_api_key
17
+ end
18
+
19
+ private
20
+
21
+ def fetched_api_key
22
+ @fetched_api_key ||= application.api_keys.search(id: api_key_id).first
23
+ end
24
+
25
+ def api_key_id
26
+ decoded_authorization_header.first
27
+ end
28
+
29
+ def api_key_secret
30
+ decoded_authorization_header.last
31
+ end
32
+
33
+ def decoded_authorization_header
34
+ @decoded_authorization_header ||= begin
35
+ api_key_and_secret = Base64.decode64(basic_authorization_header).split(':')
36
+ raise Stormpath::Error if api_key_and_secret.count != 2
37
+ api_key_and_secret
38
+ end
39
+ end
40
+
41
+ def basic_authorization_header
42
+ raise Stormpath::Error unless authorization_header =~ BASIC_PATTERN
43
+ authorization_header.gsub(BASIC_PATTERN, '')
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ module Stormpath
2
+ module Authentication
3
+ class HttpBearerAuthentication
4
+ BEARER_PATTERN = /^Bearer /
5
+ attr_reader :application, :authorization_header, :local
6
+
7
+ def initialize(application, authorization_header, options = {})
8
+ @application = application
9
+ @authorization_header = authorization_header
10
+ @local = options[:local] || false
11
+ raise Stormpath::Error if authorization_header.nil?
12
+ end
13
+
14
+ def authenticate!
15
+ Stormpath::Oauth::VerifyAccessToken.new(application, local: local)
16
+ .verify(bearer_access_token)
17
+ end
18
+
19
+ private
20
+
21
+ def bearer_access_token
22
+ raise Stormpath::Error unless authorization_header =~ BEARER_PATTERN
23
+ authorization_header.gsub(BEARER_PATTERN, '')
24
+ end
25
+ end
26
+ end
27
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,37 @@
1
+ require 'memcached'
2
+
3
+ module Stormpath
4
+ module Cache
5
+ class MemcachedStore
6
+ def initialize(opts = {})
7
+ options = nil if opts.blank?
8
+ @memcached = Memcached.new(options)
9
+ end
10
+
11
+ def get(key)
12
+ begin
13
+ entry = @memcached.get(key)
14
+ entry && Stormpath::Cache::CacheEntry.from_h(MultiJson.load(entry))
15
+ rescue Memcached::NotFound
16
+ nil
17
+ end
18
+ end
19
+
20
+ def put(key, entry)
21
+ @memcached.set(key, MultiJson.dump(entry.to_h))
22
+ end
23
+
24
+ def delete(key)
25
+ @memcached.delete(key)
26
+ end
27
+
28
+ def clear
29
+ @memcached.flush
30
+ end
31
+
32
+ def size
33
+ @memcached.stats[:curr_items]
34
+ end
35
+ end
36
+ end
37
+ end
File without changes
File without changes
File without changes
@@ -63,6 +63,7 @@ class Stormpath::DataStore
63
63
  def create(parent_href, resource, return_type, options = {})
64
64
  #TODO assuming there is no ? in url
65
65
  parent_href = "#{parent_href}?#{URI.encode_www_form(options)}" unless options.empty?
66
+
66
67
  save_resource(parent_href, resource, return_type).tap do |returned_resource|
67
68
  if resource.kind_of? return_type
68
69
  resource.set_properties returned_resource.properties
@@ -15,15 +15,15 @@
15
15
  #
16
16
  module Stormpath
17
17
  class Error < RuntimeError
18
+ attr_reader :status, :code, :developer_message, :more_info, :request_id
18
19
 
19
- attr_reader :status, :code, :developer_message, :more_info
20
-
21
- def initialize error = NilError.new
20
+ def initialize(error = NilError.new)
22
21
  super error.message
23
22
  @status = error.status
24
23
  @code = error.code
25
24
  @developer_message = error.developer_message
26
25
  @more_info = error.more_info
26
+ @request_id = error.request_id
27
27
  end
28
28
 
29
29
  private
@@ -34,7 +34,7 @@ module Stormpath
34
34
  def code; -1 end
35
35
  def developer_message; end
36
36
  def more_info; end
37
+ def request_id; end
37
38
  end
38
-
39
39
  end
40
- end
40
+ end
File without changes
@@ -36,8 +36,8 @@ module Stormpath
36
36
  else
37
37
  request.href
38
38
  end
39
-
40
- if request.http_headers["Content-Type"] == "application/x-www-form-urlencoded"
39
+
40
+ if request.http_headers["Content-Type"] == "application/x-www-form-urlencoded"
41
41
  @http_client.set_auth(request.href, request.api_key.id, request.api_key.secret)
42
42
  end
43
43
 
@@ -60,4 +60,3 @@ module Stormpath
60
60
  end
61
61
  end
62
62
  end
63
-
@@ -21,12 +21,11 @@ module Stormpath
21
21
  attr_accessor :http_method, :href, :query_string, :http_headers, :body, :api_key
22
22
 
23
23
  def initialize(http_method, href, query_string, http_headers, body, api_key)
24
-
25
24
  splitted = href.split '?'
26
25
 
27
26
  @query_string = query_string || {}
28
27
 
29
- if splitted and splitted.length > 1
28
+ if splitted && splitted.length > 1
30
29
  @href = splitted[0]
31
30
  query_string_str = splitted[1]
32
31
  query_string_arr = query_string_str.split '&'
@@ -43,33 +42,36 @@ module Stormpath
43
42
  @body = body
44
43
  @api_key = api_key
45
44
 
46
- if body
47
- @http_headers.store 'Content-Length', @body.bytesize
48
- end
49
-
45
+ @http_headers.store 'Content-Length', @body.bytesize if body
50
46
  end
51
47
 
52
48
  def resource_uri
53
49
  URI href
54
50
  end
55
51
 
56
- def to_s_query_string canonical
52
+ def to_s_query_string(canonical)
57
53
  result = ''
58
54
 
59
55
  unless @query_string.empty?
60
- Hash[@query_string.sort].each do |key, value|
61
-
56
+ Hash[@query_string.sort_by(&:to_s)].each do |key, value|
62
57
  enc_key = encode_url key, false, canonical
63
58
  enc_value = encode_url value, false, canonical
64
59
 
65
60
  result << '&' unless result.empty?
66
- result << enc_key.camelize(:lower) << '='<< enc_value
61
+ result << camelize(enc_key) << '=' << enc_value
67
62
  end
68
63
  end
69
64
 
70
65
  result
71
66
  end
72
67
 
68
+ def camelize(key)
69
+ custom_data_params?(key) ? key : key.camelize(:lower)
70
+ end
71
+
72
+ def custom_data_params?(key)
73
+ key.starts_with?('customData.')
74
+ end
73
75
  end
74
76
  end
75
77
  end
File without changes
@@ -16,24 +16,27 @@
16
16
  module Stormpath
17
17
  module Http
18
18
  module Utils
19
-
20
19
  def default_port?(uri)
21
20
  scheme = uri.scheme.downcase
22
21
  port = uri.port
23
- port <= 0 || (port == 80 && scheme.eql?("http")) || (port == 443 && scheme.eql?("https"))
22
+ port <= 0 || (port == 80 && scheme.eql?('http')) || (port == 443 && scheme.eql?('https'))
24
23
  end
25
24
 
26
25
  def encode_url(value, path, canonical)
27
- return URI.escape(value.to_s) if path
26
+ value = value.to_s
27
+ return encoded_chars?(value) ? URI.encode(URI.decode(value)) : URI.encode(value) if path
28
28
 
29
29
  CGI.escape(value.to_s).tap do |encoded|
30
- str_map = {'+' => '%20', '%7E' => '~' }
30
+ str_map = { '+' => '%20', '%7E' => '~' }
31
31
  str_map.each do |key, str_value|
32
32
  encoded.gsub!(key, str_value) if encoded.include? key
33
33
  end
34
34
  end
35
35
  end
36
36
 
37
+ def encoded_chars?(string)
38
+ string.include?('%2E')
39
+ end
37
40
  end
38
41
  end
39
- end
42
+ end
File without changes
@@ -23,7 +23,8 @@ module Stormpath
23
23
  refresh_token: RefreshToken,
24
24
  id_site_token: IdSiteGrant,
25
25
  stormpath_token: StormpathTokenGrant,
26
- client_credentials: ClientCredentialsGrant
26
+ client_credentials: ClientCredentialsGrant,
27
+ stormpath_social: SocialGrant
27
28
  }.freeze
28
29
  end
29
30
  end
@@ -1,13 +1,14 @@
1
1
  module Stormpath
2
2
  module Oauth
3
3
  class Error < Stormpath::Error
4
- attr_accessor :status, :code, :message, :developer_message, :more_info
4
+ attr_accessor :status, :code, :message, :developer_message, :more_info, :request_id
5
5
 
6
6
  def initialize(type)
7
7
  @status = errors[type][:status]
8
8
  @code = errors[type][:code]
9
9
  @message = errors[type][:message]
10
10
  @developer_message = errors[type][:developer_message]
11
+ @request_id = errors[type][:request_id]
11
12
  super(self)
12
13
  end
13
14
 
@@ -18,21 +19,24 @@ module Stormpath
18
19
  jwt_cb_uri_incorrect: {
19
20
  status: 400,
20
21
  code: 400,
21
- message: "The specified callback URI (cb_uri) is not valid",
22
- developer_message: "The specified callback URI (cb_uri) is not valid. Make "\
23
- "sure the callback URI specified in your ID Site configuration matches the value specified."
22
+ message: 'The specified callback URI (cb_uri) is not valid',
23
+ developer_message: 'The specified callback URI (cb_uri) is not valid. Make '\
24
+ 'sure the callback URI specified in your ID Site configuration matches the value specified.',
25
+ request_id: 'Oauth error UUID'
24
26
  },
25
27
  jwt_expired: {
26
28
  status: 400,
27
29
  code: 10011,
28
- message: "Token is invalid",
29
- developer_message: "Token is no longer valid because it has expired"
30
+ message: 'Token is invalid',
31
+ developer_message: 'Token is no longer valid because it has expired',
32
+ request_id: 'Oauth error UUID'
30
33
  },
31
34
  jwt_invalid: {
32
35
  status: 400,
33
36
  code: 10012,
34
- message: "Token is invalid",
35
- developer_message: "Token is invalid because the issued at time (iat) is after the current time"
37
+ message: 'Token is invalid',
38
+ developer_message: 'Token is invalid because the issued at time (iat) is after the current time',
39
+ request_id: 'Oauth error UUID'
36
40
  }
37
41
  }
38
42
  end
File without changes
@@ -0,0 +1,45 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class LocalAccessTokenVerification
4
+ attr_reader :application, :access_token
5
+
6
+ def initialize(application, access_token)
7
+ @application = application
8
+ @access_token = access_token
9
+ end
10
+
11
+ def verify
12
+ validate_jwt_is_an_access_token
13
+ validate_jwt_has_a_valid_issuer
14
+ LocalAccessTokenVerificationResult.new(application, decoded_jwt)
15
+ end
16
+
17
+ private
18
+
19
+ def decoded_jwt
20
+ begin
21
+ @decoded_jwt ||= JWT.decode(access_token, application.client.data_store.api_key.secret)
22
+ rescue JWT::ExpiredSignature
23
+ raise Stormpath::Oauth::Error, :jwt_expired
24
+ end
25
+ end
26
+
27
+ def validate_jwt_is_an_access_token
28
+ return if decoded_jwt.second['stt'] == 'access'
29
+ raise ArgumentError, 'Token is not an access token'
30
+ end
31
+
32
+ def validate_jwt_has_a_valid_issuer
33
+ return if decoded_jwt.first['iss'] == application.href
34
+ raise ArgumentError, 'Token issuer is invalid'
35
+ end
36
+ end
37
+
38
+ class LocalAccessTokenVerificationResult
39
+ attr_reader :account
40
+ def initialize(application, decoded_jwt)
41
+ @account = application.client.accounts.get(decoded_jwt.first['sub'])
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,20 +1,22 @@
1
1
  module Stormpath
2
2
  module Oauth
3
3
  class PasswordGrant < Stormpath::Resource::Base
4
- prop_accessor :grant_type, :username, :password
4
+ prop_accessor :grant_type, :username, :password, :organization_name_key
5
5
 
6
6
  def form_properties
7
- {
8
- grant_type: grant_type,
9
- username: username,
10
- password: password
11
- }
7
+ {}.tap do |form|
8
+ form[:grant_type] = grant_type
9
+ form[:username] = username
10
+ form[:password] = password
11
+ form[:organizationNameKey] = organization_name_key if organization_name_key.present?
12
+ end
12
13
  end
13
14
 
14
15
  def set_options(request)
16
+ set_property :grant_type, request.grant_type
15
17
  set_property :username, request.username
16
18
  set_property :password, request.password
17
- set_property :grant_type, request.grant_type
19
+ set_property :organization_name_key, request.organization_name_key
18
20
  end
19
21
 
20
22
  def form_data?
@@ -1,12 +1,13 @@
1
1
  module Stormpath
2
2
  module Oauth
3
3
  class PasswordGrantRequest
4
- attr_accessor :grant_type, :username, :password
4
+ attr_accessor :grant_type, :username, :password, :organization_name_key
5
5
 
6
- def initialize(username, password)
6
+ def initialize(username, password, options = {})
7
7
  @username = username
8
8
  @password = password
9
9
  @grant_type = "password"
10
+ @organization_name_key = options[:organization_name_key]
10
11
  end
11
12
  end
12
13
  end
File without changes