scim_rails 0.2.2 → 0.3.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/README.md +51 -0
- data/app/controllers/scim_rails/application_controller.rb +20 -4
- data/lib/generators/scim_rails/templates/initializer.rb +12 -0
- data/lib/scim_rails/config.rb +5 -0
- data/lib/scim_rails/encoder.rb +25 -0
- data/lib/scim_rails/version.rb +1 -1
- data/lib/scim_rails.rb +1 -0
- data/spec/controllers/scim_rails/scim_users_controller_spec.rb +1 -1
- data/spec/controllers/scim_rails/scim_users_request_spec.rb +23 -1
- data/spec/dummy/config/initializers/scim_rails_config.rb +3 -0
- data/spec/dummy/log/test.log +5180 -0
- data/spec/factories/company.rb +4 -1
- data/spec/lib/scim_rails/encoder_spec.rb +62 -0
- data/spec/support/scim_rails_config.rb +3 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69ddfe751f11e33adf91e96b99ccaaa7258bb1468ea8463511ae0b04eaeca4bf
|
4
|
+
data.tar.gz: ac7a95b8e8f7c5455bdf7b9a64d3b2c88c015974530077f80ab37a1e6751e468
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05d83eb5dee1ecbfa49116f5d1f70e5f4e600393419055d93dfdff8e735e865ef2eeedf15b73c5899543f47168763b7f7cf13b897ba53e80332d7d813b427219
|
7
|
+
data.tar.gz: be1735ff8d1de4d79d5aa70c39b0cffdbc22f26d7adc105e5c03ec2fc61953d00a7ba363b0e59b57adf3aae3f32a880275eac00eaf5874adae789954ea22c3f1
|
data/README.md
CHANGED
@@ -78,6 +78,57 @@ When sending requests to the server the `Content-Type` should be set to `applica
|
|
78
78
|
|
79
79
|
All responses will be sent with a `Content-Type` of `application/scim+json`.
|
80
80
|
|
81
|
+
#### Authentication
|
82
|
+
|
83
|
+
This gem supports both basic and OAuth bearer authentication.
|
84
|
+
|
85
|
+
##### Basic Auth
|
86
|
+
###### Username
|
87
|
+
The config setting `basic_auth_model_searchable_attribute` is the model attribute used to authenticate as the `username`. It defaults to `:subdomain`.
|
88
|
+
|
89
|
+
Ensure it is unique to the model records.
|
90
|
+
|
91
|
+
###### Password
|
92
|
+
The config setting `basic_auth_model_authenticatable_attribute` is the model attribute used to authenticate as `password`. Defaults to `:api_token`.
|
93
|
+
|
94
|
+
Assuming the attribute is `:api_token`, generate the password using:
|
95
|
+
```ruby
|
96
|
+
token = ScimRails::Encoder.encode(company)
|
97
|
+
# use the token as password for requests
|
98
|
+
company.api_token = token # required
|
99
|
+
company.save! # don't forget to persist the company record
|
100
|
+
```
|
101
|
+
|
102
|
+
This is necessary irrespective of your authentication choice(s) - basic auth, oauth bearer or both.
|
103
|
+
|
104
|
+
###### Sample Request
|
105
|
+
|
106
|
+
```bash
|
107
|
+
$ curl -X GET 'http://username:password@localhost:3000/scim/v2/Users'
|
108
|
+
```
|
109
|
+
|
110
|
+
##### OAuth Bearer
|
111
|
+
|
112
|
+
###### Signing Algorithm
|
113
|
+
In the config settings, ensure you set `signing_algorithm` to a valid JWT signing algorithm, e.g "HS256". Defaults to `"none"` when not set.
|
114
|
+
|
115
|
+
###### Signing Secret
|
116
|
+
In the config settings, ensure you set `signing_secret` to a secret key that will be used to encode and decode tokens. Defaults to `nil` when not set.
|
117
|
+
|
118
|
+
If you have already generated the `api_token` in the "Basic Auth" section, then use that as your bearer token and ignore the steps below:
|
119
|
+
```ruby
|
120
|
+
token = ScimRails::Encoder.encode(company)
|
121
|
+
# use the token as bearer token for requests
|
122
|
+
company.api_token = token #required
|
123
|
+
company.save! # don't forget to persist the company record
|
124
|
+
```
|
125
|
+
|
126
|
+
##### Sample Request
|
127
|
+
|
128
|
+
```bash
|
129
|
+
$ curl -H 'Authorization: Bearer xxxxxxx.xxxxxx' -X GET 'http://localhost:3000/scim/v2/Users'
|
130
|
+
```
|
131
|
+
|
81
132
|
### List
|
82
133
|
|
83
134
|
##### All
|
@@ -9,14 +9,30 @@ module ScimRails
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def authorize_request
|
12
|
-
|
12
|
+
send(authentication_strategy) do |searchable_attribute, authentication_attribute|
|
13
13
|
authorization = AuthorizeApiRequest.new(
|
14
|
-
searchable_attribute:
|
15
|
-
authentication_attribute:
|
14
|
+
searchable_attribute: searchable_attribute,
|
15
|
+
authentication_attribute: authentication_attribute
|
16
16
|
)
|
17
17
|
@company = authorization.company
|
18
18
|
end
|
19
|
-
raise
|
19
|
+
raise ScimRails::ExceptionHandler::InvalidCredentials if @company.blank?
|
20
|
+
end
|
21
|
+
|
22
|
+
def authentication_strategy
|
23
|
+
if request.headers["Authorization"]&.include?("Bearer")
|
24
|
+
:authenticate_with_oauth_bearer
|
25
|
+
else
|
26
|
+
:authenticate_with_http_basic
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def authenticate_with_oauth_bearer
|
31
|
+
authentication_attribute = request.headers["Authorization"].split(" ").last
|
32
|
+
payload = ScimRails::Encoder.decode(authentication_attribute).with_indifferent_access
|
33
|
+
searchable_attribute = payload[ScimRails.config.basic_auth_model_searchable_attribute]
|
34
|
+
|
35
|
+
yield searchable_attribute, authentication_attribute
|
20
36
|
end
|
21
37
|
end
|
22
38
|
end
|
@@ -22,6 +22,18 @@ ScimRails.configure do |config|
|
|
22
22
|
# or throws an error (returning 409 Conflict in accordance with SCIM spec)
|
23
23
|
config.scim_user_prevent_update_on_create = false
|
24
24
|
|
25
|
+
# Cryptographic algorithm used for signing the auth tokens.
|
26
|
+
# It supports all algorithms supported by the jwt gem.
|
27
|
+
# See https://github.com/jwt/ruby-jwt#algorithms-and-usage for supported algorithms
|
28
|
+
# It is "none" by default, hence generated tokens are unsigned
|
29
|
+
# The tokens do not need to be signed if you only need basic authentication.
|
30
|
+
# config.signing_algorithm = "HS256"
|
31
|
+
|
32
|
+
# Secret token used to sign authorization tokens
|
33
|
+
# It is `nil` by default, hence generated tokens are unsigned
|
34
|
+
# The tokens do not need to be signed if you only need basic authentication.
|
35
|
+
# config.signing_secret = SECRET_TOKEN
|
36
|
+
|
25
37
|
# Default sort order for pagination is by id. If you
|
26
38
|
# use non sequential ids for user records, uncomment
|
27
39
|
# the below line and configure a determinate order.
|
data/lib/scim_rails/config.rb
CHANGED
@@ -10,6 +10,8 @@ module ScimRails
|
|
10
10
|
end
|
11
11
|
|
12
12
|
class Config
|
13
|
+
ALGO_NONE = "none".freeze
|
14
|
+
|
13
15
|
attr_accessor \
|
14
16
|
:basic_auth_model,
|
15
17
|
:basic_auth_model_authenticatable_attribute,
|
@@ -21,6 +23,8 @@ module ScimRails
|
|
21
23
|
:scim_users_model,
|
22
24
|
:scim_users_scope,
|
23
25
|
:scim_user_prevent_update_on_create,
|
26
|
+
:signing_secret,
|
27
|
+
:signing_algorithm,
|
24
28
|
:user_attributes,
|
25
29
|
:user_deprovision_method,
|
26
30
|
:user_reprovision_method,
|
@@ -30,6 +34,7 @@ module ScimRails
|
|
30
34
|
@basic_auth_model = "Company"
|
31
35
|
@scim_users_list_order = :id
|
32
36
|
@scim_users_model = "User"
|
37
|
+
@signing_algorithm = ALGO_NONE
|
33
38
|
@user_schema = {}
|
34
39
|
@user_attributes = []
|
35
40
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "jwt"
|
2
|
+
|
3
|
+
module ScimRails
|
4
|
+
module Encoder
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def encode(company)
|
8
|
+
payload = {
|
9
|
+
iat: Time.current.to_i,
|
10
|
+
ScimRails.config.basic_auth_model_searchable_attribute =>
|
11
|
+
company.public_send(ScimRails.config.basic_auth_model_searchable_attribute)
|
12
|
+
}
|
13
|
+
|
14
|
+
JWT.encode(payload, ScimRails.config.signing_secret, ScimRails.config.signing_algorithm)
|
15
|
+
end
|
16
|
+
|
17
|
+
def decode(token)
|
18
|
+
verify = ScimRails.config.signing_algorithm != ScimRails::Config::ALGO_NONE
|
19
|
+
|
20
|
+
JWT.decode(token, ScimRails.config.signing_secret, verify, algorithm: ScimRails.config.signing_algorithm).first
|
21
|
+
rescue JWT::VerificationError, JWT::DecodeError
|
22
|
+
raise ScimRails::ExceptionHandler::InvalidCredentials
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/scim_rails/version.rb
CHANGED
data/lib/scim_rails.rb
CHANGED
@@ -537,7 +537,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
537
537
|
expect(user.archived?).to eq true
|
538
538
|
end
|
539
539
|
|
540
|
-
it "
|
540
|
+
it "successfully restores user" do
|
541
541
|
expect(company.users.count).to eq 1
|
542
542
|
user = company.users.first.tap(&:archive!)
|
543
543
|
expect(user.archived?).to eq true
|
@@ -5,7 +5,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :request do
|
|
5
5
|
let(:credentials) { Base64::encode64("#{company.subdomain}:#{company.api_token}") }
|
6
6
|
let(:authorization) { "Basic #{credentials}" }
|
7
7
|
|
8
|
-
def post_request(content_type)
|
8
|
+
def post_request(content_type = "application/scim+json")
|
9
9
|
# params need to be transformed into a string to test if they are being parsed by Rack
|
10
10
|
|
11
11
|
post "/scim_rails/scim/v2/Users",
|
@@ -48,4 +48,26 @@ RSpec.describe ScimRails::ScimUsersController, type: :request do
|
|
48
48
|
expect(company.users.count).to eq 0
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
context "OAuth Bearer Authorization" do
|
53
|
+
context "with valid token" do
|
54
|
+
let(:authorization) { "Bearer #{company.api_token}" }
|
55
|
+
|
56
|
+
it "supports OAuth bearer authorization and succeeds" do
|
57
|
+
expect { post_request }.to change(company.users, :count).from(0).to(1)
|
58
|
+
|
59
|
+
expect(response.status).to eq 201
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with invalid token" do
|
64
|
+
let(:authorization) { "Bearer #{SecureRandom.hex}" }
|
65
|
+
|
66
|
+
it "The request fails" do
|
67
|
+
expect { post_request }.not_to change(company.users, :count)
|
68
|
+
|
69
|
+
expect(response.status).to eq 401
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
51
73
|
end
|
@@ -7,6 +7,9 @@ ScimRails.configure do |config|
|
|
7
7
|
config.scim_users_scope = :users
|
8
8
|
config.scim_users_list_order = :id
|
9
9
|
|
10
|
+
config.signing_algorithm = "HS256"
|
11
|
+
config.signing_secret = "2d6806dd11c2fece2e81b8ca76dcb0062f5b08e28e3264e8ba1c44bbd3578b70"
|
12
|
+
|
10
13
|
config.user_deprovision_method = :archive!
|
11
14
|
config.user_reprovision_method = :unarchive!
|
12
15
|
|