Scopes and consent Developer

Last updated Aug 16, 2026

Scopes and consent

The scopes a user sees on the Swaymoon Account consent page depend on the required / optional scope you configured in the Developer portal, the reasons and privacy policy for required scopes, and the scope actually requested at authorize time (the server merges portal registration; see “Compatibility for older clients” below).

11 August 2026 platform update: scopes are editable, required scopes need a reason and a privacy policy, and every sign-in requires explicit confirmation. See 11 August 2026: scopes and consent platform update under Updates in this directory.

Compatibility

  • Existing production clients do not need code changes or a new release because of this platform update. Portal scope edits and showing the confirmation page on every sign-in are handled on the Swaymoon Account side.
  • New integrations and newly developed clients should follow this page and the latest guides in this directory (request scope as registered in the portal, prepare reasons and a privacy policy URL for required scopes, and design sign-in UX around “the confirmation page always appears”; do not rely on silently skipping it).

Principles

You cannot take all personal profile data with a single profile scope. Basic profile is split into field-level scopes. On the consent page the user can check or refuse optional items separately.

  • If an authorization request still uses the historical scope=openid profile …, the server expands profile into the field scopes below before showing consent.
  • scope on the token reflects the field scopes the user finally checked (plus openid / email and similar), not a bundled profile.
  • UserInfo keeps a stable set of profile claims: granted returns real values (empty string and similar if the user left them blank); not granted returns default placeholders and does not leak real data. See Tokens and user info.

Supported scope

scopeConsent-page copy (summary)UserInfo claims
openidNot shown separately; always requiredsub
emailYour email addressemail, email_verified
nameYour display namename
nicknameYour nicknamenickname
pictureYour avatarpicture
biographyYour biobiography
genderYour gendergender
birthdateYour birthdaybirthdate
regionYour country or regionregion
preferred_usernameYour usernamepreferred_username
localeYour preferred languagelocale

Historical aliases (do not rely on them as a bundle):

AliasBehavior
profileExpanded inbound into all profile fields in the table above; consent shows them separately
name (old meaning)If the token has only the old name and no other field scopes, treated as name + nickname

Developer portal rules:

ScopeCan be required?Notes
openidAlways requiredCannot be unchecked
emailYes (required / optional / not requested)If required, provide a user-visible reason and a privacy policy URL. Users without a bound email must bind one before they can finish authorization
Basic profile fields (name, preferred_username, and others)Yes (required / optional / not requested)Same: required items need a reason and privacy policy URL. Optional items can be refused on the consent page

Select only what the product actually uses. Do not treat profile scopes as an all-required bundle. When you force a scope, the reason should honestly describe the use (for example: needed as a username stored by the relying party).

Becoming a developer: the Swaymoon Account must already have a notification email bound; otherwise you cannot sign in to the Developer portal or call the client-registration API.

  1. After sign-in, the user always reaches the consent / confirmation page (passport.swaymoon.com). Prior consent for the same scopes is not silently reused.
  2. The app name and icon (if any) are shown. If a privacy policy URL is configured, the page offers an entry. Before the jump, the user sees “This domain is not controlled by Swaymoon…”. A privacy policy URL is required when you request required scopes.
  3. Scopes unchanged (relative to that user’s existing consent): Confirm sign-in and a summary of already granted items. The user confirms to continue.
  4. Scopes added or removed: the title indicates Permissions have changed. Sections show new required / new optional (developer-written reasons next to new required items), no longer requested, and still granted. The user must choose new optional items and confirm. After confirm, “no longer requested” scopes are dropped from the consent record.
  5. First authorization: listed in Required and Optional sections; reasons appear next to required items.
  6. Required scopes: checked and cannot be unchecked; labeled Required.
  7. Optional scopes: checked by default; the user can uncheck each; labeled Optional.
  8. If this request will grant email and the account has no bound email: the user must bind and verify an email before codes are issued (required email goes straight to the bind page; optional email can be unchecked to continue).
  9. Only when this request includes email and the account already has a notification email bound does a dropdown appear next to email (default Hide My Email, or Real email). First-party apps do not offer this choice.
  10. Continue grants only the optional scopes finally checked plus all required scopes (excluding “no longer requested”).
  11. Cancel does not complete authorization.

prompt=consent on the authorization request can still be sent, but it is no longer required to force the confirmation page. Production does not need that parameter for “confirm every time”.

Compatibility for older clients

When the app signs in, the URL carries the scopes for this request (for example scope=openid email). Some shipped apps cannot change that string soon.

If you later make a scope required in the portal, or add an optional scope, Swaymoon Account fills them in on the server. Old apps do not have to change code immediately:

  • Required: every required scope registered in the portal is included in this authorization (even if the app URL omitted it).
  • New optional: if the user is signed in and has not granted that item, the confirmation page lists it to check. Already granted items are not treated as “new”.

Example: the portal adds required username and optional avatar. The old app still requests only openid email → the user still sees username (required) and, if not yet granted, avatar (optional).

Fuller explanation and a comparison table: 11 August 2026: scopes and consent platform update under Updates in this directory.

New clients should still list needed scope explicitly in the authorization request and keep it aligned with portal registration.

Data deletion callback

When you register or edit an app you can set a data deletion callback URL (rules and where to register: Registration and configuration, “Data deletion callback URL”). When the user chooses Revoke and request data deletion in the privacy center, Swaymoon Account will:

  1. Revoke authorization for that app;
  2. Email an explanation to the app owner’s bound Swaymoon Account address (the mail notes whether the callback was sent successfully);
  3. If a callback URL is configured: the Swaymoon Account server POSTs JSON to it (type=swaymoon.passport.data_deletion_request), with headers X-Swaymoon-Signature: sha256=<hmac> and X-Swaymoon-Request-Id. The signature is HMAC-SHA256 over the raw request-body bytes (do not parse JSON and re-serialize before verifying).

Signing key (plaintext)

Client typeVerification key
Confidential (confidential)Plaintext client_secret shown only once at creation or rotation
Public (public) / JWT assertionIf a deletion callback is registered, create or rotate issues webhookSecret (once); use that value to verify

Keep that plaintext. Swaymoon Account stores the same plaintext as the webhook signing key. The client_secret used for OAuth client authentication in the database may later be stored as bcrypt or another one-way hash. Do not HMAC with a hash or a {bcrypt}-prefixed stored value. After key rotation, verify with the newly issued plaintext.

The callback URL must be HTTPS, and the host cannot be 127.0.0.1 / localhost. Login Redirect may still use loopback (browser navigation). Deletion callback is server egress; for local testing use an HTTPS tunnel. The receiver must be running when the user taps delete.

Delete local data promptly using subject (and any user identifiers you stored). Runnable walkthrough: “Demo data deletion callback” in the confidential-client section of Minimal Python example.

Therefore, optional scope listed on authorize may not all appear in the token’s scope. After the token exchange, read scope in the response and interpret UserInfo from it (ungranted fields are defaults, not real data).

How requests relate to configuration

  • scope in the authorization request should be a subset of the client’s registered scopes (if registration included profile, the server treats the corresponding field scopes as registered). The server also merges portal required and newly optional scopes as in “Compatibility for older clients”.
  • The authorization request must include openid.
  • Prefer field scopes, for example scope=openid name picture. You may still pass profile for now; the server expands it.
  • After consent, a record is written to the consent ledger. Users can view it on Account Privacy; see the user guide Authorized Apps.

Product notes and email

  • Do not request email if you do not need it.
  • If you need email for registration / account creation, request email: users without a bound email complete binding in the flow; after success UserInfo returns a usable email.
  • The user may choose Hide My Email: you still only receive an address you can mail; the real email is not given to you. Treat it as a normal email.
  • Use sub as the account primary key, and email as a contact method or local account name.

Changing scopes

To add or remove scope:

  1. In the Developer portal open Identifiers, edit the app, adjust optional / required scopes on the wizard Capabilities step, and save (you do not need to recreate the client to change scopes; client type still cannot be switched).
  2. When you make a scope required: write a user-visible reason for that scope and make sure a privacy policy URL is configured.
  3. The next time the user signs in to the same app they reach the authorization page. If scopes were added or removed, they see new / no longer requested / still granted sections and choose new optional items. If scopes did not change, they only confirm sign-in.

Existing production clients do not need code changes for this capability. After you save in the portal, the server merges scope and always shows the confirmation page. Develop new clients against the latest docs.

After you delete an identifier or the user revokes consent, do not keep using old tokens to access user data.