Repository navigation
chore: update version and changelog - #566
Open
github-actions[bot] wants to merge 1 commit into
Open
github-actions[bot] wants to merge 1 commit into
github-actions[bot] wants to merge 1 commit into
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
3 times, most recently
from
November 3, 2026 02:26
17326d7 to
206da56
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
5 times, most recently
from
November 6, 2026 03:46
6867679 to
80a4e8b
Compare
This was referenced Nov 6, 2026
github-actions
Bot
force-pushed
the
changeset-release/main
branch
3 times, most recently
from
November 6, 2026 06:06
fd284c9 to
6326942
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
November 6, 2026 06:08
6326942 to
0185063
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
seamless-auth-api@0.23.0
Minor Changes
bcab4d1: Back-channel logout now reaches an application whose grant ends while the first-party session goes on (feat(oidc): send back-channel logout when one application's grant ends #543). When the provider service deletes a
Grant(the user chooses "only sign out of this app", or the grant is revoked), the API sends that application a logout token for thesidit was given, with the same sender and the sameoidc_backchannel_logout_sentandoidc_backchannel_logout_failedevents as a session logout. Other applications on the session are not told, and nothing is sent while another live grant still signs the application in on that session. Applications that register abackchannel_logout_urishould expect a logout token for a partial logout as well as a full one.bcab4d1:
GET /oidc/payloads/DeviceCode/:idnow returns a device code for 10 minutes after it expires, with itsexp, instead of 404, and the purge job keeps it that long (fix(oidc): answer expired_token for an expired device code #542). The provider service hands that record to its library, which answers a client polling with an expired codeexpired_token(RFC 8628 section 3.5) rather thaninvalid_grant. A code that never existed, one past that window, the by-user-code lookup and every other model still answer 404 once expired, and an expired code can never be consumed.bcab4d1: External delivery now requires the service token in
x-seamless-service-tokento carry subjectseamless-auth-external-delivery(Harden secret responses, external delivery tokens and provider fetches outside production #556). Any other valid service token, such as an adapter's proxy token, no longer unlocks codes, links or account notices in the response; the API sends them through its own transport instead. The Node, Go, Python and Rust adapters already sign their delivery requests with that subject, so adopters on current adapters need no change. A caller that hand-mints its own service token for external delivery must setsubtoseamless-auth-external-delivery.25c4cc6: Application notice text can no longer carry its own links (Keep application notice text from carrying its own links and attribution #554).
POST /applications/account-noticesrefuses with400atextthat contains a URL, awww.address, a domain name or an email address, since mail and SMS clients turn all of them into links;actionUrl, checked against the application's origins, is the only link a notice carries. TheSent by <application> through <instance>.attribution is now the first line of the message, ahead of the text, rather than a footer the text could imitate. Adapters that render notices from external delivery receive the new layout intext.f82ec0c: A confidential OpenID Provider application can send account notices for the public applications it acts for (ADR 0002, N4 and N5). An admin links them with
PUT /admin/applications/:id/links/:linkedId, lists links withGET /admin/applications/:id/linksand removes one withDELETE, each write with step-up and audited asadmin_oidc_application_link_addedoradmin_oidc_application_link_removed. A link needs a confidential acting application and a different public linked one, both first-party or both third-party.POST /applications/account-noticestakes an optionalclientId: the caller must be linked to it, the grant check uses it and the template names it, and a client the caller is not linked to answers the same404 notice_unknown_useras an unknown user. Applications gainnoticeActionOrigins, barehttpsorigins that a notice's action link may point at besides thehttpsredirect origins, and every application response listsnoticeActionOrigins,linksandlinkedFrom. A new migration adds theoidc_client_linkstable and the column. ADR 0001 D14 is amended to match.bed4994: A backend can authorize per organization from the access token alone (feat: organization-scoped roles and permissions in the access token #416, ADR 0004). Inside an active organization, tokens gain
org_rolesandorg_permissionsbesideorg_id, andGET /users/meandGET /users/me/permissionsreport the same. Organization roles never appear inroles, so a guard onadmindoes not pass for an organization admin. Organization roles are now a catalogue, managed withPOST /admin/organization-rolesandPATCHandDELETE /admin/organization-roles/:roleName, listed byGET /admin/roles, and mapped to permissions withPUT /admin/roles/organization/:roleName/permissions. A new migration seeds it with the built-inowner,adminandmemberand every value memberships already hold, and rewrites no membership. Behavior changes: assigning a role outside the catalogue now answers 400.PATCH /organizations/:id/members/:userIdnow needs step-up. Only an owner or an instanceadmin:writecan grant or removeowner, or remove an owner from an organization, and any other manager can only grant a role whose permissions they hold, so an organization admin can no longer make themselves owner. Adding, changing and removing members is audited asorganization_member_added,organization_member_updatedandorganization_member_removed, and a refused change asorganization_member_role_grant_refused. Fixes: removing a member now reaches the token. Previously every refresh copiedorg_idfrom the session until it ended. Now the next token drops the organization claims and the session stops naming the organization. Recovery tokens carry no organization claims.25c4cc6: Passkey hardware assurance now comes from the registered credential rather than the assertion (Derive hardware-bound passkey assurance from the registered credential #552). Sign-in and step-up refuse an assertion whose backup eligibility flag differs from the one stored at registration (
401, audited aswebauthn_login_failedorstep_up_failedwith reasonBackup eligibility differs from registration). A passkey counts as device-bound, and earnsacr=phrhandamr=hwk, only when it was registered device-bound with attestation verified against the FIDO Metadata Service. Deployments that use the defaultnoneattestation, and credentials registered before attestation was recorded, now getphrandswkinstead ofphrhandhwk.da66738: Roles can now grant permissions, and access tokens carry them (feat: permissions mapped to roles #415, ADR 0004). An admin manages the catalogue with
GETandPOST /admin/permissionsandPATCHandDELETE /admin/permissions/:permissionName, reads roles withGET /admin/roles, and replaces what a role grants withPUT /admin/roles/:kind/:roleName/permissions. Each write needs step-up and is audited. Deleting a permission a role still grants answers 409 with those roles. Instance roles stay inavailable_roles, and removing one also removes its mappings, so adding the name back later does not restore old grants. Access tokens gain apermissionsclaim, matched exactly with no wildcards or implied grants, which is empty on a recovery session. When the permission claims would pass 1 KiB, which keeps an adapter's session cookie under the browser limit, the token instead carriespermissions_omitted: trueand a guard readsGET /users/me/permissions, which answers from the database on every call.GET /users/megainsuser.permissions. Changes reach a token when it is next issued, within the access token lifetime. New migration adds thepermissionsandrole_permissionstables.2f1c3db:
GET /system-config/publiccan now tell a native admin tool how to sign in through the OpenID Provider (ADR 0003). A new system config key,oidc_cli_client_id(seeded fromOIDC_CLI_CLIENT_ID, or set throughPATCH /system-config/admin), names the application. The response gains an optionaloidcProvider: { issuer, cliClientId }, present only when the provider is on, the issuer and key are set, and that application is active and eligible for session exchange with it turned on. Setting the key to an unknown or ineligible application answers 400; later disabling the application or turning its exchange off makes the advertisement disappear. Also fixesPATCH /system-config/adminanswering 500 when it set a nullable key such asoidc_issuer,hosted_uiormax_concurrent_sessionstonull: the row is now removed, which reads back asnull. No migration is needed. Needs the@seamless-auth/typesrelease that adds these fields.25c4cc6: Owner notices that a delivery-owning adapter does not advertise are now sent directly instead of dropped (Send owner notice kinds the adapter does not deliver #557). Under external delivery with a service token, a notice whose kind is missing from
x-seamless-auth-delivery-kinds(for example the SMS notice on/recovery/verifywhen the adapter lists onlyaccount_notice_email) goes out through the API's own email or SMS transport when one is configured, and is recorded assentorfailedrather thannot_sent_external_delivery. The same applies to the recovery completed and recovery code used notices and toPOST /applications/account-notices. A recovery that previously answered503 recovery_notice_failedfor an adapter listing no notice kinds now proceeds when the API can notify the owner itself. Admin identity-change notices are unchanged.52ff3c3: A first-party native client signed in through the OpenID Provider can now reach the admin API, by exchanging the sign-in for a first-party session of its own (ADR 0003). An admin turns
sessionExchangeEnabledon for a first-party public native application, with step-up, audited asadmin_oidc_application_session_exchange_updated. Such a client can ask for a 60 second access token for<oidc_issuer>/seamlesswith the single scopesession:exchange, and/oidc/signrecords each one.POST /sessions/exchange(adapter: false, RFC 8693 parameter names) consumes that token once and returns the/refreshbody plusissued_token_type, for a new session linked to the provider sign-in. A second presentation answers400 invalid_requestwithtoken_already_usedand revokes the session the first one created, audited assession_exchange_replayed. A successful exchange is audited assession_exchanged.The new session has its own refresh chain and step-up state, ends whenever its parent ends, never outlives it, and refreshing it counts as activity on the parent. It copies the parent's auth context and step-up for an authorization code grant, and nothing for a device grant. A device-grant session answers
403 step_up_requireduntil it has a fresh step-up, on every route behindrequireAdminand every/organizationsroute exceptPOST /organizations/:id/switch, reads included, and on/totp/enroll/*,/totp/disable,/webauthn/register/*,POST /recovery-codes,DELETE /users/credentials,/registration/phone,/registration/phone/verifyandDELETE /recovery/requests/:id, so a device sign-in with no TOTP cannot enroll one and the user does it from a browser. It can step up with TOTP or a real passkey assertion on the relying party's domain. OpenAPI now documents this 403 on those routes and on admin reads. It does not count againstmax_concurrent_sessions. Disabling or deleting the application, or turning the flag off, revokes the sessions it exchanged for. Session responses gainparentSessionId,exchangeClientIdandexchangeGrantTypeon such a session, and application responses gainsessionExchangeEnabled. A new migration adds the columns. ADR 0001 D11 is amended to match.25c4cc6:
third_party_clients_enablednow gates existing third-party OpenID Provider clients, not only creating and updating them (Enforce third_party_clients_enabled when serving and signing for existing clients #555). While it is off, a client that is not first-party is treated like a disabled one:/oidc/clients/:idanswers404, its shared secret does not verify,/oidc/signrefuses withclient_inactive, its notice tokens are refused and back-channel logout skips it. An instance that turned the flag off after registering third-party clients stops serving them on upgrade; turn the flag back on, or mark the applications first-party, to keep them working.Patch Changes
Cache-Control: no-storeunless its route sets its own caching (the JWKS and the admin dashboard's hashed assets do), so tokens, client secrets from create and rotate, recovery codes and delivery payloads are never stored by a cache. Provider requests (OAuth token, userinfo and discovery, and back-channel logout) now go through the address guard in every mode: outside production,httpand private or loopback addresses are still allowed, but link-local169.254.0.0/16and unspecified0.0.0.0/8addresses are refused whether named directly or reached through DNS.POST /applications/account-noticesnow folds theuserIdto lower case before counting (Key the application notice per-user limit on the canonical user id #553). Upper-case variants of one UUID no longer each get their own allowance of 10 notices an hour.oauth_login_failedevent with reasonstart_failedcarries adetailofredirect_not_allowedorprovider_unusable, and the error is logged. A refused redirect is logged by scheme and host only. The answer to the client is unchanged.system_configrow, or warns that an admin change is being reverted, when the stored value only orders its keys differently. Postgres JSONB does not keep key order, so object values such aslockout_policyandflow_rate_limitslooked changed on every boot.