The authorization page shown when third-party applications request API
access was bare-bones and lacked important context for users to make
informed decisions.
This commit redesigns the page to include:
- Clear title with quoted application name
- Current user indicator (avatar + username)
- Permissions section showing what access is being granted
- Redirect destination displayed prominently
These changes help users better understand what they're authorizing and
where they'll be redirected after approval.
Internal ref - t/171051
**BEFORE**
<img width="1156" height="1012" alt="CleanShot 2025-12-18 at 16 17 05"
src="https://github.com/user-attachments/assets/62a14e36-5ad4-425a-8f56-9723e22bc509"
/>
**AFTER**
<img width="1445" height="1138" alt="2025-12-18 @ 17 17 43"
src="https://github.com/user-attachments/assets/9408c7f5-dbc8-4290-87ec-b88679f75f99"
/>
Users/apps running OpenSSL in FIPS 140-3 mode cannot decrypt user API
key responses because FIPS forbids the legacy PKCS1_PADDING scheme.
Commit 300ece3d added support for a `padding=oaep` parameter to use
PKCS1_OAEP_PADDING instead, but the parameter was only handled in the
POST endpoints. When users go through the authorization UI flow (GET
/user-api-key/new → login → POST /user-api-key), the padding parameter
was lost because it wasn't captured in the controller or passed through
the form's hidden fields.
This fix:
- Captures @padding in the #new and #otp controller actions
- Adds hidden field for padding in new.html.erb and otp.html.erb
- Removes unused ALLOWED_PADDING_MODES constant
- Refactors specs to be more organized and concise
Internal ref - t/170427
Users/apps running OpenSSL in FIPS 140-3 mode cannot decrypt user API
key responses because FIPS forbids the legacy PKCS1_PADDING scheme that
Ruby/Discourse uses by default.
Add a `padding` parameter to the user API key endpoints that accepts
"oaep" to use PKCS1_OAEP_PADDING instead. The default remains PKCS1 for
backwards compatibility with existing clients.
Usage: POST /user-api-key.json?padding=oaep
Internal ref - t/170427
Constants should always be only assigned once. The logical OR assignment
of a constant is a relic of the past before we used zeitwerk for
autoloading and had bugs where a file could be loaded twice resulting in
constant redefinition warnings.
We want to allow admins to make new required fields apply to existing users. In order for this to work we need to have a way to make those users fill up the fields on their next page load. This is very similar to how adding a 2FA requirement post-fact works. Users will be redirected to a page where they can fill up the remaining required fields, and until they do that they won't be able to do anything else.
We're changing the implementation of trust levels to use groups. Part of this is to have site settings that reference trust levels use groups instead. It converts the min_trust_level_for_user_api_key site setting to user_api_key_allowed_groups.
This isn't used by any of our plugins or themes, so very little fallout.
The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense.
This commit aims to:
- Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_`
- Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices
- Copy `site_settings` database records to the new names
- Rename relevant translation keys
- Update relevant translations
This commit does **not** aim to:
- Rename any Ruby classes or methods. This might be done in a future commit
- Change any URLs. This would break existing integrations
- Make any changes to the protocol. This would break existing integrations
- Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately
The risks are:
- There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical.
- If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working.
A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
This reduces chances of errors where consumers of strings mutate inputs
and reduces memory usage of the app.
Test suite passes now, but there may be some stuff left, so we will run
a few sites on a branch prior to merging
This is a possible solution for https://meta.discourse.org/t/user-api-keys-specification/48536/19
This allows for user-api-key requests to not require a redirect url.
Instead, the encypted payload will just be displayed after creation ( which can be copied
pasted into an env for a CLI, for example )
Also: Show instructions when creating user-api-key w/out redirect
This adds a view to show instructions when requesting a user-api-key
without a redirect. It adds a erb template and json format.
Also adds a i18n user_api_key.instructions for server.en.yml
previously we supported blanket read and write for user API, this
change amends it so we can define more limited scopes. A scope only
covers a few routes. You can not grant access to part of the site and
leave a large amount of the information hidden to API consumer.