Skip to content

Scopes & Consent

Scopes control what user data your application can access. When a user logs in through SingleSign, they see a consent screen listing the permissions your app is requesting. Requesting only the scopes you need builds user trust and simplifies your data handling.


How Scopes Work

  1. Your app includes a scope parameter in the authorization request.
  2. SingleSign presents the user with a consent screen describing each requested scope.
  3. The user approves (or denies) access.
  4. The tokens issued to your app are limited to the approved scopes.
  5. The /oauth/userinfo endpoint only returns claims associated with the granted scopes.

Requesting Scopes

Pass scopes as a space-separated string in the scope query parameter:

GET https://api.singlesign.com/oauth/authorize
  ?platform_guid=YOUR_PLATFORM_GUID
  &response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://app.example.com/callback
  &scope=openid+profile+email
  &state=RANDOM_STATE
  &code_challenge=CHALLENGE
  &code_challenge_method=S256

Available Scopes

SingleSign supports the standard OpenID Connect scopes:

openid (Required)

Signals that this is an OpenID Connect request. Always include this scope.

Claims returned: sub, human_guid

{
  "sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "human_guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

profile

Access to the user's basic profile information.

Claims returned: name, family_name, given_name, middle_name, nickname, preferred_username, picture, updated_at

{
  "name": "Jane Doe",
  "given_name": "Jane",
  "family_name": "Doe",
  "nickname": "janedoe",
  "preferred_username": "jane.doe",
  "picture": "https://api.singlesign.com/avatars/jane.jpg",
  "updated_at": 1708099200
}

email

Access to the user's email address and verification status.

Claims returned: email, email_verified

{
  "email": "jane@example.com",
  "email_verified": true
}

phone

Access to the user's phone number and verification status.

Claims returned: phone_number, phone_number_verified

{
  "phone_number": "+1-555-867-5309",
  "phone_number_verified": true
}

address

Access to the user's mailing address.

Claims returned: address (structured object)

{
  "address": {
    "formatted": "123 Main St\nAnytown, CA 90210\nUS",
    "street_address": "123 Main St",
    "locality": "Anytown",
    "region": "CA",
    "postal_code": "90210",
    "country": "US"
  }
}

offline_access

Requests a refresh token so your app can obtain new access tokens without user interaction. Use this for long-lived sessions or background data access.

Effect: A refresh_token is included in the token response.


Scope-to-Data Mapping

ScopeClaimsConsent Description
openidsub, human_guid"Know who you are"
profilename, given_name, family_name, middle_name, nickname, preferred_username, picture, updated_at"View your basic profile"
emailemail, email_verified"View your email address"
phonephone_number, phone_number_verified"View your phone number"
addressaddress"View your mailing address"
offline_access(no claims — issues a refresh token)"Access your data when you're not using the app"

When a user is redirected to SingleSign's authorization endpoint, they see a consent dialog:

┌──────────────────────────────────────────┐
│          Sign in to Acme App             │
│                                          │
│  Acme App is requesting permission to:   │
│                                          │
│  ✓ Know who you are                      │
│  ✓ View your basic profile               │
│  ✓ View your email address               │
│                                          │
│  [Allow]                    [Deny]       │
└──────────────────────────────────────────┘
  • If the user clicks Allow, SingleSign redirects back with an authorization code.
  • If the user clicks Deny, SingleSign redirects back with error=access_denied.

Once a user grants consent for a particular app and set of scopes, SingleSign remembers the decision. The user will not see the consent screen again for the same app and scopes unless:

  • The app requests additional scopes.
  • The user revokes consent.
  • An administrator resets consent for the platform.

The Principle of Least Privilege

Request only the scopes your application genuinely needs:

ScenarioRecommended Scopes
Basic login (know who the user is)openid
Display user's name and avataropenid profile
Send transactional emailsopenid email
Personalized dashboardopenid profile email
Shipping address for ordersopenid profile email address
Background sync / long sessionsopenid profile email offline_access

Why minimize scopes?

  1. User trust — Fewer permissions means users are more likely to approve.
  2. Compliance — Data minimization is a core principle of GDPR, CCPA, and similar regulations.
  3. Attack surface — If tokens are compromised, the attacker gains access to less data.
  4. Simpler code — You don't need to handle data you never requested.

If your app initially requests openid profile email but later needs phone, redirect the user to the authorization endpoint with the new scope set:

scope=openid+profile+email+phone

SingleSign will show a consent screen for only the new scope (phone) if the user already approved the others.


If the user denies consent, your callback will receive an error:

https://app.example.com/callback?error=access_denied&error_description=The+user+denied+the+request

Handle this gracefully:

const error = params.get("error");
if (error === "access_denied") {
  showMessage("You need to grant permission to continue. You can try again anytime.");
  return;
}

Checking Granted Scopes

The token response may include a scope field indicating which scopes were actually granted (in case the user partially approved):

{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid profile email"
}

Always check the returned scope against what you requested and adapt your UI accordingly.


Next Steps

Last updated: 2026-02-16

Related docs