better_auth-oauth-provider 0.1.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7297666c2085bbacc7b4fbdd7d79c7abf8f34d53a1a4e5956a7ba47fc1572692
4
- data.tar.gz: 35108fb4c887ba57d68a782b29abbac8fe6c192c229eebc8958029b37811d0b4
3
+ metadata.gz: 064ea232e262c58fa331b01d271cacace56d0787690411c0c10509573e97575c
4
+ data.tar.gz: fb803328e302b653dcdad4efbf0f40067a798964e0e0a6c3b830933eb297a942
5
5
  SHA512:
6
- metadata.gz: e46b5e993d4df92e9722b9c69f11d9010f4ddb0ba4c9b5a4c5920aef38ebf89906c841669ba690b24ec7c2fb1bb444407d7047ebd47f8f5a08bdafab4a7af365
7
- data.tar.gz: 92627c999ec60244099a2042e1259ddf44896f302db499fd40ebf32c1d317112e04d8f0543d83a336934b7032bbba42249af1931647dbea7832a78eb8f6ca034
6
+ metadata.gz: 531242dbca74547d088b8de6b7181a962e650725b6739743d1ccde257f28357f547b9f6d1c0fce32618dfaa74c94909a5fbeb8b86cb5bcc6e9a32bf585882b14
7
+ data.tar.gz: c3d2ad67c5e0ba91433f410accd11575a8e64f4057962c4217dfa591c14f73112fa87a382f5a2009b4427d45a67b964c2339350bcf8fb7d34613062c03e0c6c1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.3.0 - 2026-04-30
6
+
7
+ - Added upstream-parity support for provider init validation, request URI resolution, prompt handling, consent reference IDs, client references, custom token/id-token claims, scope-specific access-token expiry, M2M token defaults, userinfo JWT verification, and expanded introspection fields.
8
+ - Aligned dynamic registration, admin client creation, authorization, consent, token, refresh, revoke, and userinfo behavior with upstream edge cases.
9
+ - Expanded OAuth provider upstream parity tests across authorization, metadata, client privileges, pairwise endpoints, organization integration, prompts, rate limits, PKCE/token handling, and userinfo.
10
+
11
+ ## 0.2.0 - 2026-04-29
12
+
13
+ - Aligned OAuth provider server behavior with upstream `@better-auth/oauth-provider` v1.6.9: upstream-shaped client and consent CRUD routes, server-only admin client routes, discovery metadata auth-method and signing-alg semantics, canonical access-token and consent schema, dynamic-registration PKCE defaults, refresh replay cascade revocation, rotate-secret response shape, and pairwise sector identifiers.
14
+ - Added upstream-parity OAuth provider behavior for dynamic client registration controls, PKCE enforcement, consent management, client management, token prefixes, refresh rotation, JWT resource access tokens, pairwise subjects, userinfo claims, introspection/revocation hints, end-session, `/oauth2/continue`, metadata cache headers, conditional JWKS metadata, and rate limits.
15
+ - Updated package and docs examples to use executable registration and token exchange flows.
16
+
3
17
  ## 0.1.0
4
18
 
5
19
  - Initial package skeleton for Better Auth OAuth provider.
data/README.md CHANGED
@@ -2,17 +2,166 @@
2
2
 
3
3
  External OAuth provider plugin package for `better_auth`.
4
4
 
5
- Upstream ships OAuth provider as `@better-auth/oauth-provider`, separate from core plugin exports. This gem mirrors that boundary for Ruby.
5
+ Upstream ships OAuth provider as `@better-auth/oauth-provider`, separate from core plugin exports. This gem mirrors that boundary for Ruby while keeping Ruby option names snake_case and upstream-compatible HTTP paths and JSON keys.
6
6
 
7
7
  ```ruby
8
8
  require "better_auth"
9
9
  require "better_auth/oauth_provider"
10
10
 
11
- BetterAuth.auth(
11
+ auth = BetterAuth.auth(
12
+ secret: ENV.fetch("BETTER_AUTH_SECRET"),
13
+ base_url: "https://auth.example.com/api/auth",
12
14
  plugins: [
13
- BetterAuth::Plugins.oauth_provider
15
+ BetterAuth::Plugins.oauth_provider(
16
+ scopes: ["openid", "profile", "email", "offline_access"],
17
+ consent_page: "/oauth2/consent",
18
+ allow_dynamic_client_registration: true
19
+ )
14
20
  ]
15
21
  )
16
22
  ```
17
23
 
24
+ ## Client Registration
25
+
26
+ Dynamic registration is disabled by default. Enable it explicitly and call it with an authenticated session unless unauthenticated registration is also enabled.
27
+
28
+ ```ruby
29
+ client = auth.api.register_o_auth_client(
30
+ headers: {"cookie" => session_cookie},
31
+ body: {
32
+ client_name: "Example Client",
33
+ redirect_uris: ["https://client.example.com/callback"],
34
+ token_endpoint_auth_method: "client_secret_post",
35
+ grant_types: ["authorization_code", "refresh_token"],
36
+ response_types: ["code"],
37
+ scope: "openid profile offline_access"
38
+ }
39
+ )
40
+ ```
41
+
42
+ ## Authorization Code Token Exchange
43
+
44
+ Authorization code clients use S256 PKCE by default.
45
+
46
+ ```ruby
47
+ tokens = auth.api.o_auth2_token(
48
+ body: {
49
+ grant_type: "authorization_code",
50
+ code: params[:code],
51
+ redirect_uri: "https://client.example.com/callback",
52
+ client_id: client[:client_id],
53
+ client_secret: client[:client_secret],
54
+ code_verifier: verifier
55
+ }
56
+ )
57
+ ```
58
+
59
+ When `resource` is present and valid, access tokens are JWTs. Without `resource`, access tokens are opaque and introspectable.
60
+
61
+ ## Routes
62
+
63
+ | Method | Path | Ruby API method |
64
+ | --- | --- | --- |
65
+ | `GET` | `/.well-known/oauth-authorization-server` | `auth.api.get_o_auth_server_config` |
66
+ | `GET` | `/.well-known/openid-configuration` | `auth.api.get_open_id_config` |
67
+ | `POST` | `/oauth2/register` | `auth.api.register_o_auth_client` |
68
+ | `POST` | `/oauth2/create-client` | `auth.api.create_o_auth_client` |
69
+ | `POST` | `/admin/oauth2/create-client` | `auth.api.admin_create_o_auth_client` |
70
+ | `PATCH` | `/admin/oauth2/update-client` | `auth.api.admin_update_o_auth_client` |
71
+ | `GET` | `/oauth2/get-client?client_id=...` | `auth.api.get_o_auth_client` |
72
+ | `GET` | `/oauth2/get-clients` | `auth.api.get_o_auth_clients` |
73
+ | `POST` | `/oauth2/update-client` | `auth.api.update_o_auth_client` |
74
+ | `POST` | `/oauth2/delete-client` | `auth.api.delete_o_auth_client` |
75
+ | `GET` | `/oauth2/public-client?client_id=...` | `auth.api.get_o_auth_client_public` |
76
+ | `POST` | `/oauth2/public-client-prelogin` | `auth.api.get_o_auth_client_public_prelogin` |
77
+ | `POST` | `/oauth2/client/rotate-secret` | `auth.api.rotate_o_auth_client_secret` |
78
+ | `GET` | `/oauth2/authorize` | `auth.api.o_auth2_authorize` |
79
+ | `POST` | `/oauth2/continue` | `auth.api.o_auth2_continue` |
80
+ | `POST` | `/oauth2/consent` | `auth.api.o_auth2_consent` |
81
+ | `GET` | `/oauth2/get-consent?id=...` | `auth.api.get_o_auth_consent` |
82
+ | `GET` | `/oauth2/get-consents` | `auth.api.get_o_auth_consents` |
83
+ | `POST` | `/oauth2/update-consent` | `auth.api.update_o_auth_consent` |
84
+ | `POST` | `/oauth2/delete-consent` | `auth.api.delete_o_auth_consent` |
85
+ | `POST` | `/oauth2/token` | `auth.api.o_auth2_token` |
86
+ | `POST` | `/oauth2/introspect` | `auth.api.o_auth2_introspect` |
87
+ | `POST` | `/oauth2/revoke` | `auth.api.o_auth2_revoke` |
88
+ | `GET` | `/oauth2/userinfo` | `auth.api.o_auth2_user_info` |
89
+ | `GET`, `POST` | `/oauth2/end-session` | `auth.api.o_auth2_end_session` |
90
+
91
+ Deprecated aliases remain for one minor release: `GET /oauth2/client/:id` -> `/oauth2/get-client`, `GET /oauth2/clients` -> `/oauth2/get-clients`, `PATCH /oauth2/client` -> `/oauth2/update-client`, `DELETE /oauth2/client` -> `/oauth2/delete-client`, `GET /oauth2/client` -> `/oauth2/public-client`, and `GET/PATCH/DELETE /oauth2/consent` plus `GET /oauth2/consents` -> the `get/update/delete/get-consents` consent routes.
92
+
93
+ Admin client routes are server-only. They are available through `auth.api.*` and return `403` through the Rack handler.
94
+
95
+ ## Options
96
+
97
+ Common options accepted by `BetterAuth::Plugins.oauth_provider`:
98
+
99
+ - `login_page`
100
+ - `consent_page`
101
+ - `scopes`
102
+ - `claims`
103
+ - `grant_types`
104
+ - `allow_dynamic_client_registration`
105
+ - `allow_unauthenticated_client_registration`
106
+ - `client_registration_default_scopes`
107
+ - `client_registration_allowed_scopes`
108
+ - `store_client_secret`
109
+ - `prefix`
110
+ - `refresh_token_expires_in`
111
+ - `advertised_metadata`
112
+ - `valid_audiences`
113
+ - `custom_token_response_fields`
114
+ - `custom_access_token_claims`
115
+ - `custom_user_info_claims`
116
+ - `pairwise_secret`
117
+ - `signup`
118
+ - `select_account`
119
+ - `post_login`
120
+ - `client_privileges`
121
+ - `rate_limit`
122
+ - `jwks_uri`
123
+ - `disable_jwt_plugin`
124
+ - `store`
125
+
126
+ `rate_limit` accepts per-route overrides:
127
+
128
+ ```ruby
129
+ rate_limit: {
130
+ token: {window: 60, max: 20},
131
+ authorize: {window: 60, max: 30},
132
+ introspect: {window: 60, max: 100},
133
+ revoke: {window: 60, max: 30},
134
+ register: {window: 60, max: 5},
135
+ userinfo: false
136
+ }
137
+ ```
138
+
139
+ Use `false` to disable a route-specific rule.
140
+
141
+ ## Schema Migration
142
+
143
+ `oauthAccessToken` now uses the upstream canonical columns `token`, `expiresAt`, `scopes`, `clientId`, `sessionId`, `userId`, `referenceId`, and `refreshId`. Legacy `access_token`, `refresh_token`, `access_token_expires_at`, and `scope` columns should be copied forward then dropped. `oauthConsent#consent_given` is also removed; a consent row means consent was granted.
144
+
145
+ For non-Rails SQL apps, run the equivalent of:
146
+
147
+ ```sql
148
+ UPDATE better_auth_oauth_access_tokens
149
+ SET token = COALESCE(token, access_token),
150
+ expires_at = COALESCE(expires_at, access_token_expires_at),
151
+ scopes = COALESCE(scopes, scope)
152
+ WHERE token IS NULL OR scopes IS NULL;
153
+
154
+ DELETE FROM better_auth_oauth_consents WHERE consent_given = false;
155
+ ```
156
+
157
+ Then drop the legacy access-token and consent columns. Rails apps using `better_auth-rails` generate migrations from the active plugin schema, so regenerating after this change emits only the canonical columns.
158
+
159
+ ## Ruby Adaptations
160
+
161
+ When the JWT plugin is registered, OIDC metadata advertises its configured `jwks.key_pair_config.alg`, defaulting to `EdDSA` like upstream. If `disable_jwt_plugin: true` is set, Ruby intentionally falls back to HS256 ID tokens signed with the Better Auth secret.
162
+
163
+ Route OpenAPI metadata blocks from upstream TypeScript are intentionally not ported into this package. Use the Ruby `open_api` plugin for generated OpenAPI output.
164
+
165
+ The upstream `@better-auth/oauth-provider/client`, React/Solid client plugins, dashboard UI, and browser helpers are not ported. Ruby apps call the JSON endpoints directly or wrap `auth.api.*`.
166
+
18
167
  OIDC provider remains a core `better_auth` plugin because upstream still exposes it from `better-auth/plugins`. OAuth provider is the newer standalone provider package.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BetterAuth
4
4
  module OAuthProvider
5
- VERSION = "0.1.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end