rodauth-oauth 0.9.0 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/doc/release_notes/0_9_1.md +9 -0
- data/doc/release_notes/0_9_2.md +10 -0
- data/doc/release_notes/0_9_3.md +9 -0
- data/lib/generators/rodauth/oauth/templates/db/migrate/create_rodauth_oauth.rb +1 -0
- data/lib/rodauth/features/oauth_application_management.rb +1 -1
- data/lib/rodauth/features/oauth_base.rb +53 -57
- data/lib/rodauth/features/oauth_jwt.rb +23 -34
- data/lib/rodauth/features/oauth_jwt_bearer_grant.rb +1 -0
- data/lib/rodauth/features/oauth_management_base.rb +4 -0
- data/lib/rodauth/features/oidc.rb +10 -9
- data/lib/rodauth/oauth/version.rb +1 -1
- data/locales/en.yml +1 -1
- data/templates/jwks_field.str +1 -1
- data/templates/jwt_public_key_field.str +1 -1
- data/templates/new_oauth_application.str +1 -1
- data/templates/scope_field.str +3 -2
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79fa7abfcf7ea1c0a2594f92bfd7a59e53769dec5a7221a22f740b37471e6e07
|
4
|
+
data.tar.gz: 9f7e8ce4370d44d985940d46d569e3192c35e53cb6e3841094517e64258b2b1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 520a85416c418f93615a471133201c7ec6dd5c16ff9d697a6ca87b609084b58c7b9799c5d3c7a8d02a4fc68ca9750c9ef41dd07dde17c1e1153f0cec8e58f3c1
|
7
|
+
data.tar.gz: 8e7ebc28ba158f43b5226a2de98fc76de8c81e8a8c87dbaa95a69050eed96793e487666389b60be6694437c298fdf23f183a1df098983eeec5f5549df0321c7c
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Rodauth::Oauth
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rodauth-oauth.svg)](http://rubygems.org/gems/rodauth-oauth)
|
4
|
+
[![pipeline status](https://gitlab.com/honeyryderchuck/rodauth-oauth/badges/master/pipeline.svg)](https://gitlab.com/honeyryderchuck/rodauth-oauth/pipelines?page=1&scope=all&ref=master)
|
4
5
|
[![coverage report](https://gitlab.com/honeyryderchuck/rodauth-oauth/badges/master/coverage.svg?job=coverage)](https://honeyryderchuck.gitlab.io/rodauth-oauth/coverage/#_AllFiles)
|
5
6
|
|
6
7
|
This is an extension to the `rodauth` gem which implements the [OAuth 2.0 framework](https://tools.ietf.org/html/rfc6749) for an authorization server.
|
@@ -73,7 +74,7 @@ Or install it yourself as:
|
|
73
74
|
|
74
75
|
## Usage
|
75
76
|
|
76
|
-
This tutorial assumes you already read the documentation and know how to set up `rodauth`. After that, integrating `
|
77
|
+
This tutorial assumes you already read the documentation and know how to set up `rodauth`. After that, integrating `rodauth-oauth` will look like:
|
77
78
|
|
78
79
|
```ruby
|
79
80
|
plugin :rodauth do
|
@@ -0,0 +1,9 @@
|
|
1
|
+
### 0.9.1 (08/05/2022)
|
2
|
+
|
3
|
+
#### Improvements
|
4
|
+
|
5
|
+
Using `return_response`, introduced in `rodauth` v2.23, which accomplishes better integration with rails response logging mechanism when used under `rodauth-rails`.
|
6
|
+
|
7
|
+
#### Bugfixes
|
8
|
+
|
9
|
+
* Fixing namespacing issue which required anyone to have to `require "rodauth-oauth"` before loading it (no need to anymore).
|
@@ -0,0 +1,10 @@
|
|
1
|
+
### 0.9.2 (11/05/2022)
|
2
|
+
|
3
|
+
#### Bugfixes
|
4
|
+
|
5
|
+
* Fixed remaining namespacing fix issues requiring usage of `require "rodauth-oauth"`.
|
6
|
+
* Fixed wrong expectation of database for resource-server mode when `:oauth_management_base` plugin was used.
|
7
|
+
* oidc: fixed incorrect grant creation flow whenn using `nonce` param.
|
8
|
+
* oidc: fixed jwt encoding regression when not setting encryption method/algorithmm for client applications.
|
9
|
+
* templates: added missing jwks field to the "New oauth application" form.
|
10
|
+
* Several fixes on the example OIDC applications, mostly around CSRF breakage when using latest version of `omniauth`.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
### 0.9.2 (30/05/2022)
|
2
|
+
|
3
|
+
#### Bugfixes
|
4
|
+
|
5
|
+
* `oauth_jwt`: new access tokens generated via the `"refresh_token"` grant type are now JWT (it was falling back to non JWT behaviour);
|
6
|
+
* `oidc`: a new `id_token` is now generated via the `"refresh_token"` grant type with "rotation" policy (it was being omitted from the response);
|
7
|
+
* `oidc`: fixing calculation of `"auth_time"` claim, which (as per RFC) needs to stay the same across first authentication and subsequent `"refresh_token"` requests;
|
8
|
+
* it requires a new db column (default: `"auth_time"`, datetime) in the `"oauth_tokens"` database;
|
9
|
+
* hash-column `"refresh_token"` will now expose the refresh token (instead of the hash column version) in the `"refresh_token"` grant type response payload (only happened in "non-rotation" refresh token mode).
|
@@ -33,7 +33,7 @@ module Rodauth
|
|
33
33
|
|
34
34
|
translatable_method :oauth_applications_name_label, "Name"
|
35
35
|
translatable_method :oauth_applications_description_label, "Description"
|
36
|
-
translatable_method :oauth_applications_scopes_label, "
|
36
|
+
translatable_method :oauth_applications_scopes_label, "Default scopes"
|
37
37
|
translatable_method :oauth_applications_contacts_label, "Contacts"
|
38
38
|
translatable_method :oauth_applications_tos_uri_label, "Terms of service"
|
39
39
|
translatable_method :oauth_applications_policy_uri_label, "Policy"
|
@@ -4,6 +4,8 @@ require "time"
|
|
4
4
|
require "base64"
|
5
5
|
require "securerandom"
|
6
6
|
require "net/http"
|
7
|
+
require "rodauth/version"
|
8
|
+
require "rodauth/oauth/version"
|
7
9
|
require "rodauth/oauth/ttl_store"
|
8
10
|
require "rodauth/oauth/database_extensions"
|
9
11
|
require "rodauth/oauth/refinements"
|
@@ -424,32 +426,40 @@ module Rodauth
|
|
424
426
|
}.merge(params)
|
425
427
|
|
426
428
|
rescue_from_uniqueness_error do
|
427
|
-
|
429
|
+
access_token = _generate_access_token(create_params)
|
430
|
+
refresh_token = _generate_refresh_token(create_params) if should_generate_refresh_token
|
431
|
+
oauth_token = _store_oauth_token(create_params)
|
432
|
+
oauth_token[oauth_tokens_token_column] = access_token
|
433
|
+
oauth_token[oauth_tokens_refresh_token_column] = refresh_token if refresh_token
|
434
|
+
oauth_token
|
435
|
+
end
|
436
|
+
end
|
428
437
|
|
429
|
-
|
430
|
-
|
431
|
-
else
|
432
|
-
create_params[oauth_tokens_token_column] = token
|
433
|
-
end
|
438
|
+
def _generate_access_token(params = {})
|
439
|
+
token = oauth_unique_id_generator
|
434
440
|
|
435
|
-
|
436
|
-
|
437
|
-
|
441
|
+
if oauth_tokens_token_hash_column
|
442
|
+
params[oauth_tokens_token_hash_column] = generate_token_hash(token)
|
443
|
+
else
|
444
|
+
params[oauth_tokens_token_column] = token
|
445
|
+
end
|
438
446
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
447
|
+
token
|
448
|
+
end
|
449
|
+
|
450
|
+
def _generate_refresh_token(params)
|
451
|
+
token = oauth_unique_id_generator
|
452
|
+
|
453
|
+
if oauth_tokens_refresh_token_hash_column
|
454
|
+
params[oauth_tokens_refresh_token_hash_column] = generate_token_hash(token)
|
455
|
+
else
|
456
|
+
params[oauth_tokens_refresh_token_column] = token
|
449
457
|
end
|
458
|
+
|
459
|
+
token
|
450
460
|
end
|
451
461
|
|
452
|
-
def
|
462
|
+
def _store_oauth_token(params = {})
|
453
463
|
ds = db[oauth_tokens_table]
|
454
464
|
|
455
465
|
if __one_oauth_token_per_account
|
@@ -575,43 +585,24 @@ module Rodauth
|
|
575
585
|
|
576
586
|
rescue_from_uniqueness_error do
|
577
587
|
oauth_tokens_ds = db[oauth_tokens_table]
|
578
|
-
|
588
|
+
access_token = _generate_access_token(update_params)
|
579
589
|
|
580
|
-
if
|
581
|
-
update_params
|
590
|
+
if oauth_refresh_token_protection_policy == "rotation"
|
591
|
+
update_params = {
|
592
|
+
**update_params,
|
593
|
+
oauth_tokens_oauth_token_id_column => oauth_token[oauth_tokens_id_column],
|
594
|
+
oauth_tokens_account_id_column => oauth_token[oauth_tokens_account_id_column],
|
595
|
+
oauth_tokens_scopes_column => oauth_token[oauth_tokens_scopes_column]
|
596
|
+
}
|
597
|
+
|
598
|
+
refresh_token = _generate_refresh_token(update_params)
|
582
599
|
else
|
583
|
-
|
600
|
+
refresh_token = param("refresh_token")
|
584
601
|
end
|
602
|
+
oauth_token = __update_and_return__(oauth_tokens_ds, update_params)
|
585
603
|
|
586
|
-
oauth_token =
|
587
|
-
|
588
|
-
**update_params,
|
589
|
-
oauth_tokens_oauth_token_id_column => oauth_token[oauth_tokens_id_column],
|
590
|
-
oauth_tokens_scopes_column => oauth_token[oauth_tokens_scopes_column]
|
591
|
-
}
|
592
|
-
|
593
|
-
refresh_token = oauth_unique_id_generator
|
594
|
-
|
595
|
-
if oauth_tokens_refresh_token_hash_column
|
596
|
-
insert_params[oauth_tokens_refresh_token_hash_column] = generate_token_hash(refresh_token)
|
597
|
-
else
|
598
|
-
insert_params[oauth_tokens_refresh_token_column] = refresh_token
|
599
|
-
end
|
600
|
-
|
601
|
-
# revoke the refresh token
|
602
|
-
oauth_tokens_ds.where(oauth_tokens_id_column => oauth_token[oauth_tokens_id_column])
|
603
|
-
.update(oauth_tokens_revoked_at_column => Sequel::CURRENT_TIMESTAMP)
|
604
|
-
|
605
|
-
insert_params[oauth_tokens_oauth_token_id_column] = oauth_token[oauth_tokens_id_column]
|
606
|
-
__insert_and_return__(oauth_tokens_ds, oauth_tokens_id_column, insert_params)
|
607
|
-
else
|
608
|
-
# includes none
|
609
|
-
ds = oauth_tokens_ds.where(oauth_tokens_id_column => oauth_token[oauth_tokens_id_column])
|
610
|
-
__update_and_return__(ds, update_params)
|
611
|
-
end
|
612
|
-
|
613
|
-
oauth_token[oauth_tokens_token_column] = token
|
614
|
-
oauth_token[oauth_tokens_refresh_token_column] = refresh_token if refresh_token
|
604
|
+
oauth_token[oauth_tokens_token_column] = access_token
|
605
|
+
oauth_token[oauth_tokens_refresh_token_column] = refresh_token
|
615
606
|
oauth_token
|
616
607
|
end
|
617
608
|
end
|
@@ -687,8 +678,7 @@ module Rodauth
|
|
687
678
|
response["Pragma"] = "no-cache"
|
688
679
|
end
|
689
680
|
json_payload = _json_response_body(body)
|
690
|
-
|
691
|
-
request.halt
|
681
|
+
return_response(json_payload)
|
692
682
|
end
|
693
683
|
|
694
684
|
def throw_json_response_error(status, error_code, message = nil)
|
@@ -703,8 +693,7 @@ module Rodauth
|
|
703
693
|
json_payload = _json_response_body(payload)
|
704
694
|
response["Content-Type"] ||= json_response_content_type
|
705
695
|
response["WWW-Authenticate"] = oauth_token_type.upcase if status == 401
|
706
|
-
|
707
|
-
request.halt
|
696
|
+
return_response(json_payload)
|
708
697
|
end
|
709
698
|
|
710
699
|
unless method_defined?(:_json_response_body)
|
@@ -717,6 +706,13 @@ module Rodauth
|
|
717
706
|
end
|
718
707
|
end
|
719
708
|
|
709
|
+
if Gem::Version.new(Rodauth.version) < Gem::Version.new("2.23")
|
710
|
+
def return_response(body = nil)
|
711
|
+
response.write(body) if body
|
712
|
+
request.halt
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
720
716
|
def authorization_required
|
721
717
|
if accepts_json?
|
722
718
|
throw_json_response_error(authorization_required_error_status, "invalid_client")
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
+
require "rodauth/oauth/version"
|
3
4
|
require "rodauth/oauth/ttl_store"
|
4
5
|
|
5
6
|
module Rodauth
|
@@ -38,6 +39,9 @@ module Rodauth
|
|
38
39
|
|
39
40
|
translatable_method :oauth_applications_jwt_public_key_label, "Public key"
|
40
41
|
|
42
|
+
auth_value_method :oauth_application_jwt_public_key_param, "jwt_public_key"
|
43
|
+
auth_value_method :oauth_application_jwks_param, "jwks"
|
44
|
+
|
41
45
|
auth_value_method :oauth_jwt_keys, {}
|
42
46
|
auth_value_method :oauth_jwt_key, nil
|
43
47
|
auth_value_method :oauth_jwt_public_key, nil
|
@@ -62,7 +66,6 @@ module Rodauth
|
|
62
66
|
:jwt_encode,
|
63
67
|
:jwt_decode,
|
64
68
|
:jwks_set,
|
65
|
-
:last_account_login_at,
|
66
69
|
:generate_jti
|
67
70
|
)
|
68
71
|
|
@@ -95,12 +98,6 @@ module Rodauth
|
|
95
98
|
|
96
99
|
private
|
97
100
|
|
98
|
-
unless method_defined?(:last_account_login_at)
|
99
|
-
def last_account_login_at
|
100
|
-
nil
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
101
|
def issuer
|
105
102
|
@issuer ||= oauth_jwt_token_issuer || authorization_server_url
|
106
103
|
end
|
@@ -171,41 +168,38 @@ module Rodauth
|
|
171
168
|
|
172
169
|
# /token
|
173
170
|
|
174
|
-
def
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
if should_generate_refresh_token
|
181
|
-
refresh_token = oauth_unique_id_generator
|
182
|
-
|
183
|
-
if oauth_tokens_refresh_token_hash_column
|
184
|
-
create_params[oauth_tokens_refresh_token_hash_column] = generate_token_hash(refresh_token)
|
185
|
-
else
|
186
|
-
create_params[oauth_tokens_refresh_token_column] = refresh_token
|
187
|
-
end
|
188
|
-
end
|
171
|
+
def create_oauth_token_from_token(oauth_token, update_params)
|
172
|
+
otoken = super
|
173
|
+
access_token = _generate_jwt_access_token(otoken)
|
174
|
+
otoken[oauth_tokens_token_column] = access_token
|
175
|
+
otoken
|
176
|
+
end
|
189
177
|
|
190
|
-
|
191
|
-
|
178
|
+
def generate_oauth_token(params = {}, should_generate_refresh_token = true)
|
179
|
+
oauth_token = super
|
180
|
+
access_token = _generate_jwt_access_token(oauth_token)
|
181
|
+
oauth_token[oauth_tokens_token_column] = access_token
|
182
|
+
oauth_token
|
183
|
+
end
|
192
184
|
|
185
|
+
def _generate_jwt_access_token(oauth_token)
|
193
186
|
claims = jwt_claims(oauth_token)
|
194
187
|
|
195
188
|
# one of the points of using jwt is avoiding database lookups, so we put here all relevant
|
196
189
|
# token data.
|
197
190
|
claims[:scope] = oauth_token[oauth_tokens_scopes_column]
|
198
191
|
|
199
|
-
|
192
|
+
jwt_encode(claims)
|
193
|
+
end
|
200
194
|
|
201
|
-
|
202
|
-
|
195
|
+
def _generate_access_token(*)
|
196
|
+
# no op
|
203
197
|
end
|
204
198
|
|
205
199
|
def jwt_claims(oauth_token)
|
206
200
|
issued_at = Time.now.to_i
|
207
201
|
|
208
|
-
|
202
|
+
{
|
209
203
|
iss: issuer, # issuer
|
210
204
|
iat: issued_at, # issued at
|
211
205
|
#
|
@@ -223,10 +217,6 @@ module Rodauth
|
|
223
217
|
exp: issued_at + oauth_token_expires_in,
|
224
218
|
aud: (oauth_jwt_audience || oauth_application[oauth_applications_client_id_column])
|
225
219
|
}
|
226
|
-
|
227
|
-
claims[:auth_time] = last_account_login_at.to_i if last_account_login_at
|
228
|
-
|
229
|
-
claims
|
230
220
|
end
|
231
221
|
|
232
222
|
def jwt_subject(oauth_token)
|
@@ -714,8 +704,7 @@ module Rodauth
|
|
714
704
|
response["Cache-Control"] = "no-store"
|
715
705
|
response["Pragma"] = "no-cache"
|
716
706
|
end
|
717
|
-
|
718
|
-
request.halt
|
707
|
+
return_response(jwt)
|
719
708
|
end
|
720
709
|
end
|
721
710
|
end
|
@@ -74,6 +74,7 @@ module Rodauth
|
|
74
74
|
|
75
75
|
auth_value_method :oauth_grants_nonce_column, :nonce
|
76
76
|
auth_value_method :oauth_tokens_nonce_column, :nonce
|
77
|
+
auth_value_method :oauth_tokens_auth_time_column, :auth_time
|
77
78
|
|
78
79
|
translatable_method :invalid_scope_message, "The Access Token expired"
|
79
80
|
|
@@ -120,7 +121,8 @@ module Rodauth
|
|
120
121
|
jwks: oauth_application_jwks,
|
121
122
|
encryption_algorithm: @oauth_application[oauth_applications_userinfo_encrypted_response_alg_column],
|
122
123
|
encryption_method: @oauth_application[oauth_applications_userinfo_encrypted_response_enc_column]
|
123
|
-
}
|
124
|
+
}.compact
|
125
|
+
|
124
126
|
jwt = jwt_encode(
|
125
127
|
oidc_claims,
|
126
128
|
signing_algorithm: algo,
|
@@ -234,8 +236,7 @@ module Rodauth
|
|
234
236
|
href: authorization_server_url
|
235
237
|
}]
|
236
238
|
})
|
237
|
-
|
238
|
-
request.halt
|
239
|
+
return_response(json_payload)
|
239
240
|
end
|
240
241
|
end
|
241
242
|
end
|
@@ -316,7 +317,7 @@ module Rodauth
|
|
316
317
|
def create_oauth_grant(create_params = {})
|
317
318
|
return super unless (nonce = param_or_nil("nonce"))
|
318
319
|
|
319
|
-
super(oauth_grants_nonce_column => nonce)
|
320
|
+
super(create_params.merge(oauth_grants_nonce_column => nonce))
|
320
321
|
end
|
321
322
|
|
322
323
|
def create_oauth_token_from_authorization_code(oauth_grant, create_params)
|
@@ -341,8 +342,7 @@ module Rodauth
|
|
341
342
|
|
342
343
|
# Time when the End-User authentication occurred.
|
343
344
|
#
|
344
|
-
|
345
|
-
id_token_claims[:auth_time] = id_token_claims[:iat]
|
345
|
+
id_token_claims[:auth_time] = oauth_token[oauth_tokens_auth_time_column].to_i
|
346
346
|
|
347
347
|
account = db[accounts_table].where(account_id_column => oauth_token[oauth_tokens_account_id_column]).first
|
348
348
|
|
@@ -358,7 +358,8 @@ module Rodauth
|
|
358
358
|
signing_algorithm: oauth_application[oauth_applications_id_token_signed_response_alg_column] || oauth_jwt_algorithm,
|
359
359
|
encryption_algorithm: oauth_application[oauth_applications_id_token_encrypted_response_alg_column],
|
360
360
|
encryption_method: oauth_application[oauth_applications_id_token_encrypted_response_enc_column]
|
361
|
-
}
|
361
|
+
}.compact
|
362
|
+
|
362
363
|
oauth_token[:id_token] = jwt_encode(id_token_claims, **params)
|
363
364
|
end
|
364
365
|
|
@@ -487,7 +488,7 @@ module Rodauth
|
|
487
488
|
end
|
488
489
|
end
|
489
490
|
|
490
|
-
scope_claims.unshift("auth_time")
|
491
|
+
scope_claims.unshift("auth_time")
|
491
492
|
|
492
493
|
response_types_supported = metadata[:response_types_supported]
|
493
494
|
|
@@ -533,7 +534,7 @@ module Rodauth
|
|
533
534
|
response["Access-Control-Allow-Methods"] = "GET, OPTIONS"
|
534
535
|
response["Access-Control-Max-Age"] = "3600"
|
535
536
|
response.status = 200
|
536
|
-
|
537
|
+
return_response
|
537
538
|
end
|
538
539
|
end
|
539
540
|
end
|
data/locales/en.yml
CHANGED
@@ -19,7 +19,7 @@ en:
|
|
19
19
|
oauth_management_pagination_next_button: "Next"
|
20
20
|
oauth_applications_name_label: "Name"
|
21
21
|
oauth_applications_description_label: "Description"
|
22
|
-
oauth_applications_scopes_label: "
|
22
|
+
oauth_applications_scopes_label: "Default scopes"
|
23
23
|
oauth_applications_contacts_label: "Contacts"
|
24
24
|
oauth_applications_homepage_url_label: "Homepage URL"
|
25
25
|
oauth_applications_tos_uri_label: "Terms of Service URL"
|
data/templates/jwks_field.str
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
<div class="form-group">
|
2
2
|
<label for="name">#{rodauth.oauth_applications_jwks_label}#{rodauth.input_field_label_suffix}</label>
|
3
|
-
|
3
|
+
<textarea id="jwks" class="form-control" name="#{rodauth.oauth_application_jwks_param}" rows="3"></textarea>
|
4
4
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
1
|
<div class="form-group">
|
2
2
|
<label for="name">#{rodauth.oauth_applications_jwt_public_key_label}#{rodauth.input_field_label_suffix}</label>
|
3
|
-
#{rodauth.input_field_string(rodauth.oauth_application_jwt_public_key_param, "jwt_public_key", :type=>"text")}
|
3
|
+
#{rodauth.input_field_string(rodauth.oauth_application_jwt_public_key_param, "jwt_public_key", :type=>"text", :required=>false)}
|
4
4
|
</div>
|
data/templates/scope_field.str
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
<fieldset class="form-group">
|
2
|
+
<legend>#{rodauth.oauth_applications_scopes_label}</legend>
|
2
3
|
#{
|
3
4
|
rodauth.oauth_application_scopes.map do |scope|
|
4
|
-
"<div class=\"form-check
|
5
|
-
"<input id=\"#{scope}\" type=\"checkbox\" name=\"#{rodauth.oauth_application_scopes_param}[]\" value=\"#{scope}\">" +
|
5
|
+
"<div class=\"form-group form-check\">" +
|
6
|
+
"<input id=\"#{scope}\" type=\"checkbox\" class=\"form-check-input\" name=\"#{rodauth.oauth_application_scopes_param}[]\" value=\"#{scope}\">" +
|
6
7
|
"<label for=\"#{scope}\">#{scope}</label>" +
|
7
8
|
"</div>"
|
8
9
|
end.join
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth-oauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rodauth
|
@@ -57,6 +57,9 @@ extra_rdoc_files:
|
|
57
57
|
- doc/release_notes/0_7_4.md
|
58
58
|
- doc/release_notes/0_8_0.md
|
59
59
|
- doc/release_notes/0_9_0.md
|
60
|
+
- doc/release_notes/0_9_1.md
|
61
|
+
- doc/release_notes/0_9_2.md
|
62
|
+
- doc/release_notes/0_9_3.md
|
60
63
|
files:
|
61
64
|
- CHANGELOG.md
|
62
65
|
- LICENSE.txt
|
@@ -85,6 +88,9 @@ files:
|
|
85
88
|
- doc/release_notes/0_7_4.md
|
86
89
|
- doc/release_notes/0_8_0.md
|
87
90
|
- doc/release_notes/0_9_0.md
|
91
|
+
- doc/release_notes/0_9_1.md
|
92
|
+
- doc/release_notes/0_9_2.md
|
93
|
+
- doc/release_notes/0_9_3.md
|
88
94
|
- lib/generators/rodauth/oauth/install_generator.rb
|
89
95
|
- lib/generators/rodauth/oauth/templates/app/models/oauth_application.rb
|
90
96
|
- lib/generators/rodauth/oauth/templates/app/models/oauth_grant.rb
|