rodauth-oauth 0.0.3 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec27cf0fcac2e93b6ba08d76a4fa3e165c55722864d87fb78e4f0fc70a15c759
4
- data.tar.gz: 535f0b61b987f38179de2d7011b55d8b9b6e12bdf1293c9da7534c063277c2f3
3
+ metadata.gz: 02d69464053b6809900da774b4c9957d642b003d0a0de7aa076e57a5eb8895bc
4
+ data.tar.gz: e1dd94b69aa4bdf051b1c28d684a0ec2a1435da9f99ca6bf77da9d537474f9a6
5
5
  SHA512:
6
- metadata.gz: d1179a1e5db37dbfdc9932a6ec74fb3fba37c7c863c0ec643f9b1c11fee8ef8b8bf71d0705bb9629135f517dbb3d49dd5e7609014ddc3aae28ad4bd0f45981a1
7
- data.tar.gz: ebc711bc991746fbfa780f81a91c92508c55eca65e3e316a1fc4b23b6e9141f0d97a8871ce12527fdeaf71234d97ddfa0c712aca870c65f73ab89a11fe40839e
6
+ metadata.gz: cfe325a2e8daa96a72b4577566ae84772dcf114411ebbd9d0115f0f33f5b104f7c138a1b1ef7813d46f0fd2226c6560db5d974e51ec92b33ce7e393726005b2d
7
+ data.tar.gz: df5866c1cd089c0d361a00d1ffd1db02df9b6551940dbf70e7390657fa8558ae0fb3c8eb2fcff6ec6fb9fd52406a99615574305d5a3bacdbd20f5fc22bacd63f
@@ -2,7 +2,204 @@
2
2
 
3
3
  ## master
4
4
 
5
- ## 0.0.3 (5/6/2020)
5
+ ### 0.2.0
6
+
7
+ #### Features
8
+
9
+ ##### SAML Assertion Grant Type
10
+
11
+ `rodauth-auth` now supports using a SAML Assertion to request for an Access token.In order to enable, you have to:
12
+
13
+ ```ruby
14
+ plugin :rodauth do
15
+ enable :oauth_saml
16
+ end
17
+ ```
18
+
19
+ For more info about integrating it, [check the wiki](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/wikis/SAML-Assertion-Access-Tokens).
20
+
21
+ ##### Supporting rotating keys
22
+
23
+ At some point, you'll want to replace the pkeys and algorithm used to generate and verify the JWT access tokens, but you want to keep validating previously-distributed JWT tokens, at least until they expire. Now you can, via two new options, `oauth_jwt_legacy_public_key` and `oauth_jwt_legacy_algorithm`, which will be declared in the JWKs URI and used to verify access tokens.
24
+
25
+
26
+ ##### Reuse access tokens
27
+
28
+ If the `oauth_reuse_access_token` is set, if there's already an existing valid access token, any new grant for the same application / account / scope will keep the same access token. This can be helpful in scenarios where one wants the same access token distributed across devices.
29
+
30
+ ##### require_authorizable_account
31
+
32
+ The method used to verify access to the authorize flow is called `require_authorizable_account`. By default, it checks if a user is logged in by using rodauth's own `require_account`. This is the method you'd want to redefine in order to augment these requirements, i.e. request 2fa authentication.
33
+
34
+ #### Improvements
35
+
36
+ Expired and revoked access tokens end up generating a lot of garbage, which will have to be periodically cleaned up. You can mitigate this now by setting a uniqueness index for a group of columns, i.e. if you set a uniqueness index for the `oauth_application_id/account_id/scopes` column, `rodauth-oauth` will transparently reuse the same db entry to store the new access token. If setting some other type of uniqueness index, make sure to update the option `oauth_tokens_unique_columns` (the array of columns from the uniqueness index).
37
+
38
+ #### Bugfixes
39
+
40
+ Calling `before_*_route` callbacks appropriately.
41
+
42
+ Fixed some mishandling of HTTP headers when in in resource-server mode.
43
+
44
+ #### Chore
45
+
46
+ * 97.7% test coverage;
47
+ * `rodauth-oauth` CI tests run against sqlite, postgresql and mysql.
48
+
49
+ ### 0.1.0
50
+
51
+ (31/7/2020)
52
+
53
+ #### Features
54
+
55
+ ##### OpenID
56
+
57
+ `rodauth-oauth` now ships with support for [OpenID Connect](https://openid.net/connect/). In order to enable, you have to:
58
+
59
+ ```ruby
60
+ plugin :rodauth do
61
+ enable :oidc
62
+ end
63
+ ```
64
+
65
+ For more info about integrating it, [check the wiki](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/wikis/home#openid-connect-since-v01).
66
+
67
+ It supports omniauth openID integrations out-of-the-box, [check the OpenID example, which integrates with omniauth_openid_connect](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/tree/master/examples).
68
+
69
+ #### Improvements
70
+
71
+ * JWT: `sub` claim now also handles "pairwise" subjects. For that, you have to set the `oauth_jwt_subject_type` option (`"public"` or `"pairwise"`) and `oauth_jwt_subject_secret` (will be used for salting the `sub` when the type is `"pairwise"`).
72
+ * JWT: `auth_time` claim is now supported; if your application uses the `rodauth` feature `:account_expiration`, it'll use the `last_account_login_at` method, otherwise you can set the `last_account_login_at` option:
73
+
74
+ ```ruby
75
+ last_account_login_at do
76
+ convert_timestamp(db[accounts_table].where(account_id_column => account_id).get(:that_column_where_you_keep_the_data))
77
+ end
78
+ ```
79
+ * JWT: `iss` claim now defaults to `authorization_server_url` when not defined;
80
+ * JWT: `aud` claim now defaults to the token application's client ID (`client_id` claim was removed as a result);
81
+
82
+
83
+
84
+ #### Breaking Changes
85
+
86
+ `rodauth-oauth` URLs no longer have the `oauth-` prefix, so make sure you update your integrations accordingly, i.e. where you used to rely on `/oauth-authorize`, you'll have to use `/authorize`.
87
+
88
+ URI schemes for client applications redirect URIs have to be `https`. In order to override this, set the `oauth_valid_uri_schemes` to an array of your expected URI schemes.
89
+
90
+
91
+ #### Bugfixes
92
+
93
+ * Authorization request submission can receive the `scope` as an array of values now, instead of only dealing with receiving a white-space separated list.
94
+ * fixed trailing "/" in the "issuer" value in server metadata (`https://server.com/` -> `https://server.com`).
95
+
96
+
97
+ ### 0.0.6
98
+
99
+ (6/7/2020)
100
+
101
+ #### Features
102
+
103
+ The `oauth_jwt` feature now supports JWT Secured Authorization Request (JAR) (see https://tools.ietf.org/html/draft-ietf-oauth-jwsreq-20). This means that client applications can send the authorization parameters inside a signed JWT. The client applications keeps the private key, while the authorization server **must** store a public key for the client application. For encrypted JWTs, the client application should use one of the public encryption keys exposed in the JWKs URI, to encrypt the JWT. Remember, **tokens must be signed then encrypted** (or just signed).
104
+
105
+ ###### Options:
106
+
107
+ * `:oauth_application_jws_jwk_column`: db column where the public key is stored; since it's stored in the JWS format, it can be stored either as a String (JSON-encoded), or as an hstore (if you're using postgresql);
108
+ * `:oauth_jwt_jwe_key`: key used to decrypt the request JWT;
109
+ * `:oauth_jwt_jwe_public_key`: key used to encrypt the request JWT, and which will be exposed in the JWKs URI in the JWK format;
110
+
111
+
112
+ #### Improvements
113
+
114
+ * Removing all `_param` options; these defined the URL params, however we're using protocol-defined params, so it's unlikely (and undesired) that these'll change.
115
+ * Hitting the revoke endpoint with a JWT access token returns a 400 error;
116
+
117
+ #### Chore
118
+
119
+ Removed React Javascript from example applications.
120
+
121
+
122
+ ### 0.0.5
123
+
124
+ (26/6/2020)
125
+
126
+ #### Features
127
+
128
+ * new option: `oauth_scope_separator` (default: `" "`), to define how scopes are stored;
129
+
130
+ ##### Resource Server mode
131
+
132
+ `rodauth-oauth` can now be used in a resource server, i.e. only for authorizing access to resources:
133
+
134
+
135
+ ```ruby
136
+ plugin :rodauth do
137
+ enable :oauth
138
+
139
+ is_authorization_server? false
140
+ authorization_server_url "https://auth-server"
141
+ end
142
+ ```
143
+
144
+ It **requires** the authorization to implement the server metadata endpoint (`/.well-known/oauth-authorization-server`), and if using JWS, the JWKs URI endpoint (unless `oauth_jwt_public_key` is defined).
145
+
146
+ #### Improvements
147
+
148
+ * Multiple Redirect URIs are now allowed for client applications out-of-the-box. In order to use it in API mode, you can pass the `redirect_uri` with an array of strings (the URLs) as values; in the new client application form, you can add several input fields with name field as `redirect_uri[]`. **ATTENTION!!** When using multiple redirect URIs, passing the desired redirect URI to the authorize form becomes mandatory.
149
+ * store scopes with whitespace instead of comma; set separator as `oauth_scope_separator` option, to keep backwards-compatibility;
150
+ * client application can now store multiple redirect uris; the POST API parameters can accept the redirect_uri param value both as a string or an array of string; internally, they'll be stored in a whitespace-separated string;
151
+
152
+ #### Bugfixes
153
+
154
+ * Fixed `RETURNING` support in the databases supporting it (such as postgres).
155
+
156
+ #### Chore
157
+
158
+ * option `scopes_param` renamed to `scope_param`;
159
+ *
160
+
161
+ ## 0.0.4
162
+
163
+ (13/6/2020)
164
+
165
+ ### Features
166
+
167
+ #### Token introspection
168
+
169
+ `rodauth-oauth` now ships with an introspection endpoint (`/oauth-introspect`).
170
+
171
+ #### Authorization Server Metadata
172
+
173
+ `rodauth-oauth` now allows to define an authorization metadata endpoint, which has to be defined at the route of the router:
174
+
175
+ ```ruby
176
+ route do |r|
177
+ r.rodauth
178
+ rodauth.oauth_server_metadata
179
+ ...
180
+ ```
181
+
182
+ #### JWKs URI
183
+
184
+ the `oauth_jwt` feature now ships with an endpoint, `/oauth-jwks`, where client applications can retrieve the JWK set to verify generated tokens.
185
+
186
+ #### JWT access tokens as authorization grants
187
+
188
+ The `oauth_jwt` feature now allows the usage of access tokens to authorize the generation of new tokens, [as per the RFC](https://tools.ietf.org/html/rfc7523#section-4);
189
+
190
+ ### Improvements
191
+
192
+ * using `client_secret_basic` authorization where client id/secret params were allowed (i.e. in the token and revoke endpoints, for example);
193
+ * improved JWK usage for both supported jwt libraries;
194
+ * marked `fetch_access_token` as auth_value_method, thereby allowing users to fetch the access token from other sources than the "Authorization" header (i.e. form body, query params, etc...)
195
+
196
+ ### Bugfixes
197
+
198
+ * Fixed scope claim of JWT ("scopes" -> "scope");
199
+
200
+ ## 0.0.3
201
+
202
+ (5/6/2020)
6
203
 
7
204
  ### Features
8
205
 
@@ -34,7 +231,9 @@ end
34
231
  * renamed the existing `use_oauth_implicit_grant_type` to `use_oauth_implicit_grant_type?`;
35
232
  * It's now usable as JSON API (small caveat: POST authorize will still redirect on success...);
36
233
 
37
- ## 0.0.2 (29/5/2020)
234
+ ## 0.0.2
235
+
236
+ (29/5/2020)
38
237
 
39
238
  ### Features
40
239
 
@@ -50,6 +249,8 @@ end
50
249
 
51
250
  * usage of client secret for authorizing the generation of tokens, as the spec mandates (and refraining from them when doing PKCE).
52
251
 
53
- ## 0.0.1 (14/5/2020)
252
+ ## 0.0.1
253
+
254
+ (14/5/2020)
54
255
 
55
256
  Initial implementation of the Oauth 2.0 framework, with an example app done using roda.
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Rodauth::Oauth
2
2
 
3
- [![pipeline status](https://gitlab.com/honeyryderchuck/rodauth-oauth/badges/master/pipeline.svg)](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/commits/master)
4
- [![coverage report](https://gitlab.com/honeyryderchuck/rodauth-oauth/badges/master/coverage.svg)](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/commits/master)
3
+ [![pipeline status](https://gitlab.com/honeyryderchuck/rodauth-oauth/badges/master/pipeline.svg)](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/pipelines?page=1&ref=master)
4
+ [![coverage report](https://gitlab.com/honeyryderchuck/rodauth-oauth/badges/master/coverage.svg)](https://honeyryderchuck.gitlab.io/rodauth-oauth/coverage/#_AllFiles)
5
5
 
6
6
  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.
7
7
 
8
8
  ## Features
9
9
 
10
- This gem implements:
10
+ This gem implements the following RFCs and features of OAuth:
11
11
 
12
12
  * [The OAuth 2.0 protocol framework](https://tools.ietf.org/html/rfc6749):
13
13
  * [Authorization grant flow](https://tools.ietf.org/html/rfc6749#section-1.3);
@@ -15,12 +15,18 @@ This gem implements:
15
15
  * [Access Token refresh](https://tools.ietf.org/html/rfc6749#section-1.5);
16
16
  * [Implicit grant (off by default)[https://tools.ietf.org/html/rfc6749#section-4.2];
17
17
  * [Token revocation](https://tools.ietf.org/html/rfc7009);
18
+ * [Token introspection](https://tools.ietf.org/html/rfc7662);
19
+ * [Authorization Server Metadata](https://tools.ietf.org/html/rfc8414);
18
20
  * [PKCE](https://tools.ietf.org/html/rfc7636);
19
21
  * Access Type (Token refresh online and offline);
20
22
  * [MAC Authentication Scheme](https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-02);
21
23
  * [JWT Acess Tokens](https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-07);
24
+ * [SAML 2.0 Assertion Access Tokens](https://tools.ietf.org/html/draft-ietf-oauth-saml2-bearer-03);
25
+ * [JWT Secured Authorization Requests](https://tools.ietf.org/html/draft-ietf-oauth-jwsreq-20);
22
26
  * OAuth application and token management dashboards;
23
27
 
28
+ It also implements the [OpenID Connect layer](https://openid.net/connect/) on top of the OAuth features it provides.
29
+
24
30
  This gem supports also rails (through [rodauth-rails]((https://github.com/janko/rodauth-rails))).
25
31
 
26
32
 
@@ -40,6 +46,15 @@ Or install it yourself as:
40
46
 
41
47
  $ gem install rodauth-oauth
42
48
 
49
+
50
+ ## Resources
51
+ | | |
52
+ | ------------- | ----------------------------------------------------------- |
53
+ | Website | https://honeyryderchuck.gitlab.io/rodauth-oauth/ |
54
+ | Documentation | https://honeyryderchuck.gitlab.io/rodauth-oauth/rdoc/ |
55
+ | Wiki | https://gitlab.com/honeyryderchuck/rodauth-oauth/wikis/home |
56
+ | CI | https://gitlab.com/honeyryderchuck/rodauth-oauth/pipelines |
57
+
43
58
  ## Usage
44
59
 
45
60
  This tutorial assumes you already read the documentation and know how to set up `rodauth`. After that, integrating `roda-auth` will look like:
@@ -83,11 +98,22 @@ route do |r|
83
98
  end
84
99
  ```
85
100
 
86
- You'll have to do a bit more boilerplate, so here's the instructions.
101
+
102
+ For OpenID, it's very similar to the example above:
103
+
104
+ ```ruby
105
+ plugin :rodauth do
106
+ # enable it in the plugin
107
+ enable :login, :openid
108
+ oauth_application_default_scope %w[openid]
109
+ oauth_application_scopes %w[openid email profile]
110
+ end
111
+ ```
112
+
87
113
 
88
114
  ### Example (TL;DR)
89
115
 
90
- If you're familiar with the technology and want to skip the next paragraphs, just [check our roda example](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/tree/master/examples/roda).
116
+ If you're familiar with the technology and want to skip the next paragraphs, just [check our example applications](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/tree/master/examples/).
91
117
 
92
118
 
93
119
  Generating tokens happens mostly server-to-server, so here's an example using:
@@ -98,7 +124,7 @@ Generating tokens happens mostly server-to-server, so here's an example using:
98
124
 
99
125
  ```ruby
100
126
  require "httpx"
101
- response = HTTPX.post("https://auth_server/oauth-token",json: {
127
+ response = HTTPX.post("https://auth_server/token",json: {
102
128
  client_id: ENV["OAUTH_CLIENT_ID"],
103
129
  client_secret: ENV["OAUTH_CLIENT_SECRET"],
104
130
  grant_type: "authorization_code",
@@ -112,7 +138,7 @@ puts payload #=> {"access_token" => "awr23f3h8f9d2h89...", "refresh_token" => "2
112
138
  ##### cURL
113
139
 
114
140
  ```
115
- > curl --data '{"client_id":"$OAUTH_CLIENT_ID","client_secret":"$OAUTH_CLIENT_SECRET","grant_type":"authorization_code","code":"oiweicnewdh32fhoi3hf3ihfo2ih3f2o3as"}' https://auth_server/oauth-token
141
+ > curl --data '{"client_id":"$OAUTH_CLIENT_ID","client_secret":"$OAUTH_CLIENT_SECRET","grant_type":"authorization_code","code":"oiweicnewdh32fhoi3hf3ihfo2ih3f2o3as"}' https://auth_server/token
116
142
  ```
117
143
 
118
144
  #### Refresh Token
@@ -123,7 +149,7 @@ Refreshing expired tokens also happens mostly server-to-server, here's an exampl
123
149
 
124
150
  ```ruby
125
151
  require "httpx"
126
- response = HTTPX.post("https://auth_server/oauth-token",json: {
152
+ response = HTTPX.post("https://auth_server/token",json: {
127
153
  client_id: ENV["OAUTH_CLIENT_ID"],
128
154
  client_secret: ENV["OAUTH_CLIENT_SECRET"],
129
155
  grant_type: "refresh_token",
@@ -137,7 +163,7 @@ puts payload #=> {"access_token" => "awr23f3h8f9d2h89...", "token_type" => "Bear
137
163
  ##### cURL
138
164
 
139
165
  ```
140
- > curl -H "X-your-auth-scheme: $SERVER_KEY" --data '{"client_id":"$OAUTH_CLIENT_ID","client_secret":"$OAUTH_CLIENT_SECRET","grant_type":"token","token":"2r89hfef4j9f90d2j2390jf390g"}' https://auth_server/oauth-token
166
+ > curl -H "X-your-auth-scheme: $SERVER_KEY" --data '{"client_id":"$OAUTH_CLIENT_ID","client_secret":"$OAUTH_CLIENT_SECRET","grant_type":"token","token":"2r89hfef4j9f90d2j2390jf390g"}' https://auth_server/token
141
167
  ```
142
168
 
143
169
  #### Revoking tokens
@@ -146,10 +172,9 @@ Token revocation can be done both by the idenntity owner or the application owne
146
172
 
147
173
  ```ruby
148
174
  require "httpx"
149
- httpx = HTTPX.plugin(:authorization)
150
- response = httpx.with(headers: { "X-your-auth-scheme" => ENV["SERVER_KEY"] })
151
- .post("https://auth_server/oauth-revoke",json: {
152
- client_id: ENV["OAUTH_CLIENT_ID"],
175
+ httpx = HTTPX.plugin(:basic_authorization)
176
+ response = httpx.basic_authentication(ENV["CLIENT_ID"], ENV["CLIENT_SECRET"])
177
+ .post("https://auth_server/revoke",json: {
153
178
  token_type_hint: "access_token", # can also be "refresh:tokn"
154
179
  token: "2r89hfef4j9f90d2j2390jf390g"
155
180
  })
@@ -161,7 +186,56 @@ puts payload #=> {"access_token" => "awr23f3h8f9d2h89...", "token_type" => "Bear
161
186
  ##### cURL
162
187
 
163
188
  ```
164
- > curl -H "X-your-auth-scheme: $SERVER_KEY" --data '{"client_id":"$OAUTH_CLIENT_ID","token_type_hint":"access_token","token":"2r89hfef4j9f90d2j2390jf390g"}' https://auth_server/oauth-revoke
189
+ > curl -H "X-your-auth-scheme: $SERVER_KEY" --data '{"client_id":"$OAUTH_CLIENT_ID","token_type_hint":"access_token","token":"2r89hfef4j9f90d2j2390jf390g"}' https://auth_server/revoke
190
+ ```
191
+
192
+ #### Token introspection
193
+
194
+ Token revocation can be used to determine the state of a token (whether active, what's the scope...) . Here's an example using server-to-server:
195
+
196
+ ```ruby
197
+ require "httpx"
198
+ httpx = HTTPX.plugin(:basic_authorization)
199
+ response = httpx.basic_authentication(ENV["CLIENT_ID"], ENV["CLIENT_SECRET"])
200
+ .post("https://auth_server/introspect",json: {
201
+ token_type_hint: "access_token", # can also be "refresh:tokn"
202
+ token: "2r89hfef4j9f90d2j2390jf390g"
203
+ })
204
+ response.raise_for_status
205
+ payload = JSON.parse(response.to_s)
206
+ puts payload #=> {"active" => true, "scope" => "read write" ....
207
+ ```
208
+
209
+ ##### cURL
210
+
211
+ ```
212
+ > curl -H "X-your-auth-scheme: $SERVER_KEY" --data '{"client_id":"$OAUTH_CLIENT_ID","token_type_hint":"access_token","token":"2r89hfef4j9f90d2j2390jf390g"}' https://auth_server/revoke
213
+ ```
214
+
215
+ ### Authorization Server Metadata
216
+
217
+ The Authorization Server Metadata endpoint can be used by clients to obtain the information needed to interact with an
218
+ OAuth 2.0 authorization server, i.e. know which endpoint is used to authorize clients.
219
+
220
+ Because this endpoint **must be https://AUTHSERVER/.well-known/oauth-authorization-server**, you'll have to define it at the root-level of your app:
221
+
222
+ ```ruby
223
+ plugin :rodauth do
224
+ # enable it in the plugin
225
+ enable :login, :oauth
226
+ oauth_application_default_scope %w[profile.read]
227
+ oauth_application_scopes %w[profile.read profile.write]
228
+ end
229
+
230
+ # then, inside roda
231
+
232
+ route do |r|
233
+ r.rodauth
234
+ # server metadata endpoint
235
+ rodauth.oauth_server_metadata
236
+
237
+ # now, your oauth and app code...
238
+
165
239
  ```
166
240
 
167
241
  ### Database migrations
@@ -192,10 +266,10 @@ The rodauth default setup expects the roda `render` plugin to be activated; by d
192
266
 
193
267
  Once you set it up, by default, the following endpoints will be available:
194
268
 
195
- * `GET /oauth-authorize`: Loads the OAuth authorization HTML form;
196
- * `POST /oauth-authorize`: Responds to an OAuth authorization request, as [per the spec](https://tools.ietf.org/html/rfc6749#section-4);
197
- * `POST /oauth-token`: Generates OAuth tokens as [per the spec](https://tools.ietf.org/html/rfc6749#section-4.4.2);
198
- * `POST /oauth-revoke`: Revokes OAuth tokens as [per the spec](https://tools.ietf.org/html/rfc7009);
269
+ * `GET /authorize`: Loads the OAuth authorization HTML form;
270
+ * `POST /authorize`: Responds to an OAuth authorization request, as [per the spec](https://tools.ietf.org/html/rfc6749#section-4);
271
+ * `POST /token`: Generates OAuth tokens as [per the spec](https://tools.ietf.org/html/rfc6749#section-4.4.2);
272
+ * `POST /revoke`: Revokes OAuth tokens as [per the spec](https://tools.ietf.org/html/rfc7009);
199
273
 
200
274
  ### OAuth applications
201
275
 
@@ -375,7 +449,7 @@ The "Proof Key for Code Exchange by OAuth Public Clients" (aka PKCE) flow, which
375
449
  ```ruby
376
450
  # with httpx
377
451
  require "httpx"
378
- response = HTTPX.post("https://auth_server/oauth-token",json: {
452
+ response = HTTPX.post("https://auth_server/token",json: {
379
453
  client_id: ENV["OAUTH_CLIENT_ID"],
380
454
  grant_type: "authorization_code",
381
455
  code: "oiweicnewdh32fhoi3hf3ihfo2ih3f2o3as",
@@ -426,14 +500,14 @@ Generating an access token will deliver the following fields:
426
500
  ```ruby
427
501
  # with httpx
428
502
  require "httpx"
429
- response = httpx.post("https://auth_server/oauth-token",json: {
430
- client_id: ENV["OAUTH_CLIENT_ID"],
431
- client_secret: ENV["OAUTH_CLIENT_SECRET"],
503
+ response = httpx.post("https://auth_server/token",json: {
504
+ client_id: env["oauth_client_id"],
505
+ client_secret: env["oauth_client_secret"],
432
506
  grant_type: "authorization_code",
433
507
  code: "oiweicnewdh32fhoi3hf3ihfo2ih3f2o3as"
434
508
  })
435
509
  response.raise_for_status
436
- payload = JSON.parse(response.to_s)
510
+ payload = json.parse(response.to_s)
437
511
  puts payload #=> {
438
512
  # "access_token" => ....
439
513
  # "mac_key" => ....
@@ -469,7 +543,6 @@ This will, by default, use the OAuth application as HMAC signature and "HS256" a
469
543
  ```ruby
470
544
  enable :oauth_jwt
471
545
  oauth_jwt_secret "SECRET"
472
- # or oauth_jwt_secret_path "path/to/file"
473
546
  oauth_jwt_algorithm "HS512"
474
547
  ```
475
548
 
@@ -486,7 +559,7 @@ rsa_public = rsa_private.public_key
486
559
  plugin :rodauth do
487
560
  enable :oauth_jwt
488
561
  oauth_jwt_key rsa_private
489
- oauth_jwt_decoding_secret rsa_public
562
+ oauth_jwt_public_key rsa_public
490
563
  oauth_jwt_algorithm "RS256"
491
564
  end
492
565
  ```
@@ -496,10 +569,14 @@ end
496
569
  One can further encode the JWT token using JSON Web Keys. Here's how you could enable the feature:
497
570
 
498
571
  ```ruby
572
+ rsa_private = OpenSSL::PKey::RSA.generate 2048
573
+ rsa_public = rsa_private.public_key
574
+
499
575
  plugin :rodauth do
500
576
  enable :oauth_jwt
501
- oauth_jwt_jwk_key 2048 # can be key size or the encoded RSA key, which is the only one supported now.
502
- # oauth_jwt_jwk_key "path/to/rsa.pem" if you prefer
577
+ oauth_jwt_jwk_key rsa_private
578
+ oauth_jwt_jwk_public_key rsa_public
579
+ oauth_jwt_jwk_algorithm "RS256"
503
580
  end
504
581
  ```
505
582
 
@@ -520,6 +597,26 @@ end
520
597
 
521
598
  which adds an extra layer of protection.
522
599
 
600
+ #### JWKS URI
601
+
602
+ A route is defined for getting the JWK Set in a JSON format; this is typically used by client applications, who need the JWK set to decode the JWT token. This URL is typically `https://oauth-server/jwks`.
603
+
604
+ #### JWT Bearer as authorization grant
605
+
606
+ One can emit a new access token by using the bearer access token as grant. This can be done emitting a request similar to this:
607
+
608
+ ```ruby
609
+ # with httpx
610
+ require "httpx"
611
+ response = httpx.post("https://auth_server/token",json: {
612
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
613
+ assertion: "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6IkV4YW1wbGUiLCJpYXQiOjE1OTIwMDk1MDEsImNsaWVudF9pZCI6IkNMSUVOVF9JRCIsImV4cCI6MTU5MjAxMzEwMSwiYXVkIjpudWxsLCJzY29wZSI6InVzZXIucmVhZCB1c2VyLndyaXRlIiwianRpIjoiOGM1NTVjMjdiOWRjNDdmOTcyNWRkYzBhMjk0NzA1ZTA4NzFkY2JlN2Q5ZTNlMmVkNGE1ZTBiOGZlNTZlYzcxMSJ9.AlxKRtE3ec0mtyBSDx4VseND4eC6cH5ubtv8gfYxxsc"
614
+ })
615
+ response.raise_for_status
616
+ payload = json.parse(response.to_s)
617
+ puts payload #=> {
618
+ # "access_token" => "ey....
619
+ ```
523
620
 
524
621
  #### DB Schema
525
622