better_auth-scim 0.2.0 → 0.6.2

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.
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+
5
+ module BetterAuth
6
+ module Plugins
7
+ module_function
8
+
9
+ def scim_store_token(ctx, config, token)
10
+ storage = config[:store_scim_token]
11
+ if storage == "hashed"
12
+ Crypto.sha256(token, encoding: :base64url)
13
+ elsif storage == "encrypted"
14
+ Crypto.symmetric_encrypt(key: ctx.context.secret, data: token)
15
+ elsif storage.is_a?(Hash) && storage[:hash].respond_to?(:call)
16
+ storage[:hash].call(token)
17
+ elsif storage.is_a?(Hash) && storage[:encrypt].respond_to?(:call)
18
+ storage[:encrypt].call(token)
19
+ else
20
+ token
21
+ end
22
+ end
23
+
24
+ def scim_token_matches?(ctx, config, token, stored)
25
+ storage = config[:store_scim_token]
26
+ return Crypto.symmetric_decrypt(key: ctx.context.secret, data: stored) == token if storage == "encrypted"
27
+ return storage[:decrypt].call(stored) == token if storage.is_a?(Hash) && storage[:decrypt].respond_to?(:call)
28
+
29
+ !token.to_s.empty? && scim_store_token(ctx, config, token) == stored
30
+ end
31
+
32
+ def scim_decode_token(encoded)
33
+ decoded = Base64.urlsafe_decode64(encoded.to_s)
34
+ token, provider_id, *organization_parts = decoded.split(":")
35
+ raise scim_error("UNAUTHORIZED", "Invalid SCIM token") if token.to_s.empty? || provider_id.to_s.empty?
36
+
37
+ [token, provider_id, organization_parts.join(":").then { |value| value.empty? ? nil : value }]
38
+ rescue ArgumentError
39
+ raise scim_error("UNAUTHORIZED", "Invalid SCIM token")
40
+ end
41
+
42
+ def scim_default_provider(config, provider_id, organization_id)
43
+ Array(config[:default_scim]).find do |provider|
44
+ candidate = normalize_hash(provider)
45
+ next true if candidate[:provider_id].to_s == provider_id.to_s && organization_id.to_s.empty?
46
+
47
+ candidate[:provider_id].to_s == provider_id.to_s &&
48
+ !organization_id.to_s.empty? &&
49
+ candidate[:organization_id].to_s == organization_id.to_s
50
+ end&.then do |provider|
51
+ data = normalize_hash(provider)
52
+ {"providerId" => data[:provider_id], "scimToken" => data[:scim_token], "organizationId" => data[:organization_id]}
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module Plugins
5
+ module_function
6
+
7
+ def scim_user_schema(base_url = nil)
8
+ {
9
+ id: SCIM_USER_SCHEMA_ID,
10
+ schemas: ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
11
+ name: "User",
12
+ description: "User Account",
13
+ attributes: [
14
+ {name: "id", type: "string", multiValued: false, description: "Unique opaque identifier for the User", required: false, caseExact: true, mutability: "readOnly", returned: "default", uniqueness: "server"},
15
+ {name: "userName", type: "string", multiValued: false, description: "Unique identifier for the User, typically used by the user to directly authenticate to the service provider", required: true, caseExact: false, mutability: "readWrite", returned: "default", uniqueness: "server"},
16
+ {name: "displayName", type: "string", multiValued: false, description: "The name of the User, suitable for display to end-users. The name SHOULD be the full name of the User being described, if known.", required: false, caseExact: true, mutability: "readOnly", returned: "default", uniqueness: "none"},
17
+ {name: "active", type: "boolean", multiValued: false, description: "A Boolean value indicating the User's administrative status.", required: false, mutability: "readOnly", returned: "default"},
18
+ {
19
+ name: "name",
20
+ type: "complex",
21
+ multiValued: false,
22
+ description: "The components of the user's real name.",
23
+ required: false,
24
+ subAttributes: [
25
+ {name: "formatted", type: "string", multiValued: false, description: "The full name, including all middlenames, titles, and suffixes as appropriate, formatted for display(e.g., 'Ms. Barbara J Jensen, III').", required: false, caseExact: false, mutability: "readWrite", returned: "default", uniqueness: "none"},
26
+ {name: "familyName", type: "string", multiValued: false, description: "The family name of the User, or last name in most Western languages (e.g., 'Jensen' given the fullname 'Ms. Barbara J Jensen, III').", required: false, caseExact: false, mutability: "readWrite", returned: "default", uniqueness: "none"},
27
+ {name: "givenName", type: "string", multiValued: false, description: "The given name of the User, or first name in most Western languages (e.g., 'Barbara' given the full name 'Ms. Barbara J Jensen, III').", required: false, caseExact: false, mutability: "readWrite", returned: "default", uniqueness: "none"}
28
+ ]
29
+ },
30
+ {
31
+ name: "emails",
32
+ type: "complex",
33
+ multiValued: true,
34
+ description: "Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g., 'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'. Canonical type values of 'work', 'home', and 'other'.",
35
+ required: false,
36
+ mutability: "readWrite",
37
+ returned: "default",
38
+ uniqueness: "none",
39
+ subAttributes: [
40
+ {name: "value", type: "string", multiValued: false, description: "Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g., 'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'. Canonical type values of 'work', 'home', and 'other'.", required: false, caseExact: false, mutability: "readWrite", returned: "default", uniqueness: "server"},
41
+ {name: "primary", type: "boolean", multiValued: false, description: "A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the preferred mailing address or primary email address. The primary attribute value 'true' MUST appear no more than once.", required: false, mutability: "readWrite", returned: "default"}
42
+ ]
43
+ }
44
+ ],
45
+ meta: {resourceType: "Schema", location: scim_resource_url(base_url, "/scim/v2/Schemas/#{SCIM_USER_SCHEMA_ID}")}
46
+ }
47
+ end
48
+
49
+ def scim_user_resource_type(base_url = nil)
50
+ {
51
+ schemas: ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"],
52
+ id: "User",
53
+ name: "User",
54
+ endpoint: "/Users",
55
+ description: "User Account",
56
+ schema: SCIM_USER_SCHEMA_ID,
57
+ meta: {resourceType: "ResourceType", location: scim_resource_url(base_url, "/scim/v2/ResourceTypes/User")}
58
+ }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module Plugins
5
+ module_function
6
+
7
+ def scim_param(ctx, key)
8
+ ctx.params[key] || ctx.params[key.to_s] || ctx.params[Schema.storage_key(key)] || ctx.params[Schema.storage_key(key).to_sym]
9
+ end
10
+
11
+ def scim_resource_url(base_url, path)
12
+ return path unless base_url
13
+
14
+ "#{base_url}#{path}"
15
+ end
16
+ end
17
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BetterAuth
4
4
  module SCIM
5
- VERSION = "0.2.0"
5
+ VERSION = "0.6.2"
6
6
  end
7
7
  end
@@ -2,6 +2,18 @@
2
2
 
3
3
  require "better_auth"
4
4
  require_relative "scim/version"
5
+ require_relative "scim/scim_metadata"
6
+ require_relative "scim/scim_error"
7
+ require_relative "scim/utils"
8
+ require_relative "scim/client"
9
+ require_relative "scim/user_schemas"
10
+ require_relative "scim/scim_resources"
11
+ require_relative "scim/mappings"
12
+ require_relative "scim/scim_filters"
13
+ require_relative "scim/patch_operations"
14
+ require_relative "scim/scim_tokens"
15
+ require_relative "scim/middlewares"
16
+ require_relative "scim/routes"
5
17
  require_relative "plugins/scim"
6
18
 
7
19
  module BetterAuth
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_auth-scim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Sala
@@ -111,6 +111,18 @@ files:
111
111
  - README.md
112
112
  - lib/better_auth/plugins/scim.rb
113
113
  - lib/better_auth/scim.rb
114
+ - lib/better_auth/scim/client.rb
115
+ - lib/better_auth/scim/mappings.rb
116
+ - lib/better_auth/scim/middlewares.rb
117
+ - lib/better_auth/scim/patch_operations.rb
118
+ - lib/better_auth/scim/routes.rb
119
+ - lib/better_auth/scim/scim_error.rb
120
+ - lib/better_auth/scim/scim_filters.rb
121
+ - lib/better_auth/scim/scim_metadata.rb
122
+ - lib/better_auth/scim/scim_resources.rb
123
+ - lib/better_auth/scim/scim_tokens.rb
124
+ - lib/better_auth/scim/user_schemas.rb
125
+ - lib/better_auth/scim/utils.rb
114
126
  - lib/better_auth/scim/version.rb
115
127
  homepage: https://github.com/sebasxsala/better-auth
116
128
  licenses: