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.
- checksums.yaml +4 -4
- data/lib/better_auth/plugins/scim.rb +14 -676
- data/lib/better_auth/scim/client.rb +15 -0
- data/lib/better_auth/scim/mappings.rb +47 -0
- data/lib/better_auth/scim/middlewares.rb +30 -0
- data/lib/better_auth/scim/patch_operations.rb +46 -0
- data/lib/better_auth/scim/routes.rb +421 -0
- data/lib/better_auth/scim/scim_error.rb +17 -0
- data/lib/better_auth/scim/scim_filters.rb +21 -0
- data/lib/better_auth/scim/scim_metadata.rb +42 -0
- data/lib/better_auth/scim/scim_resources.rb +26 -0
- data/lib/better_auth/scim/scim_tokens.rb +56 -0
- data/lib/better_auth/scim/user_schemas.rb +61 -0
- data/lib/better_auth/scim/utils.rb +17 -0
- data/lib/better_auth/scim/version.rb +1 -1
- data/lib/better_auth/scim.rb +12 -0
- metadata +13 -1
|
@@ -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
|
data/lib/better_auth/scim.rb
CHANGED
|
@@ -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
|
|
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:
|