Skip to content

Scopes and Permissions

When an app requests permission to access or modify some of the user's data, it needs to define what permissions it actually wants for that specific request. This is accomplished through scopes — special string values that represent permissions for actions that an app is authorized to perform on the user's behalf.

As an app developer, when creating your app or editing its settings, you define what scopes it is allowed to request.

Note

Since a scope represents a permission granted to the app by the user, the app can never get more access to the system than the user does.

Suppose that Alice, a moderator, grants the AutoModerationBot app the permission to a hypothetical rp:moderation scope so it can automatically delete stories that look like spam or violate the content policy. If Alice later resigns as a moderator, becoming a regular user, the app will lose its access to moderation functions as well.

List of requestable scopes

Identity API

idp:character:?.read
Requests access to character ownership information for one character of the user's choice via the Character API.
idp:character:<lodestoneId>.read

Requests access to character ownership information for the character with the specified Lodestone ID (example: idp:character:40869035.read) via the Character API. Cannot be granted if the user doesn't have a verified character with that Lodestone ID.

This scope is enabled for your app if you enable idp:character:?.read in app settings.

idp:character:<World>/<Firstname_Lastname>.read

Requests access to character ownership information for the character with the specified world and name, with spaces replaced by underscores (example: idp:character:Omega/Sunset_Star.read) via the Character API. Cannot be granted if the user doesn't have a verified character with that name.

This scope is enabled for your app if you enable idp:character:?.read in app settings.

idp:character:all.read
Requests access to character ownership information for all of the user's verified characters via the Character API. Note that the user can approve this request without actually granting access to all characters.
idp:user.read
Requests access to basic user information, including the user's unique ID, via the User API.
idp:user:email.read
Requests access to user email via the User API. An authorization request containing this scope must also request user.read, otherwise the request will be immediately rejected.

Roleplay API

rp:character-profile:all.write
Requests permission to edit roleplay profiles of all of the user's characters via the character roleplay profiles API.

Both APIs

offline_access
If a request including this scope is granted, the app is issued a long-lived refresh token in addition to a short-lived access token. The user cannot deny this scope without denying the whole request.

Once the authorization server accepts your app's authorization request, it presents the user with the consent page, where the user can review the permissions your app is requesting.

Code flow consent

The user has three options:

  • Approve all permissions the app is requesting.
  • Approve only some of the permissions the app is requesting.
  • Deny the request entirely.

Granted scopes

The app may receive fewer permissions than it bargained for, though never more. The scopes in the authorization request specify what permissions the app wants, but it is the user who decides what permissions, if any, the app actually gets.

This is unusual for OAuth 2.0 implementations, but is explicitly permitted by the spec. That said, there are some guarantees that ensure the app won't end up with a completely unusable access token:

  • The user has to either approve at least one resource scope (that is, any scope other than offline_access), or deny the request entirely. So if your app requests only one resource scope (plus optionally offline_access), it is guaranteed to be either granted that scope or have the request denied entirely.
  • The user cannot deny the offline_access scope without denying the entire request. Therefore, if your app's authorization request that includes the offline_access scope is approved, you can be certain that the token response will include a refresh token.
  • If the app requests idp:character:all.read, the user has two options: to either grant the app access to all current and future characters (granting that specific scope), or to grant access to one or more current characters and no future ones (in which case the scopes for those specific characters will be granted). Therefore, if your app requests idp:character:all.read and nothing else, and the request is approved, it can be certain that it was granted access to at least one verified character. The app should act as if the characters accessible via the returned access token are all characters available to it.
  • If user:email.read is granted, then user.read is necessarily granted as well.
  • The wildcard scope idp:character:?.read can be requested, but will never be returned in the list of granted scopes. Instead, the authorization server will reply with idp:character:<lodestoneId>.read with the Lodestone ID of the character the user selects. This ensures that issued single-character access tokens are always bound to specific characters.
  • Character name scopes of the form idp:character:<World>/<Firstname_Lastname>.read can be requested, but will never be returned in the list of granted scopes. Instead, if the user indeed owns a verified character with that name, the authorization server will reply with idp:character:<lodestoneId>.read with the Lodestone ID of that character.

These rules are in place to ensure that apps won't ask for more permissions than strictly necessary. Most apps will only need one resource scope per authorization request (plus maybe offline_access), as they'll be interested in either the Character API, the User API, or the Roleplay API. If you ask for only one thing, you won't have to settle for less, because there's no "less" to settle for.

That said, apps that do request multiple resource scopes and get less than they requested still shouldn't break. For example, an app that requests idp:user.read and idp:user:email.read for user registration, but is granted only the former, should still proceed with user registration, but ask for the user's email address itself if it needs one, instead of obtaining it from Central Archives.

Scopes are request-specific

Scopes granted to apps are specific to individual requests and to the access tokens issued for these requests. For example, imagine this scenario:

  • An app makes a request for the idp:character:all.read scope. The user approves it, and the app is issued access token T1.
  • The same app makes a request for the user.read scope from the same user. The user approves it, and the app is issued access token T2.

In this case, the app can use token T1 to access the Character API, and token T2 to access the User API, but not the other way round.