Getting information about OAuth access tokens
When working with OAuth access tokens in Zendesk, you can't retrieve the full access token after creation. To protect these sensitive credentials from exposure or misuse, Zendesk shows only the first 10 characters of each token in API responses, allowing you to verify and differentiate tokens without revealing the full secret required for authentication. However, you can view other information about the token, such as its scope and id.
This article explains how to list OAuth access tokens to view their related information.
Listing OAuth access tokens
Listing OAuth tokens lets you see how tokens are being used, such as:
- Auditing active tokens: See which OAuth tokens are currently active in your Zendesk account.
- Reviewing token scopes: View the scopes assigned to each token to see the permissions granted, helping to ensure tokens have the appropriate access.
- Associating tokens with users and applications: Helps you track which users or apps can access these tokens.
You can use this information to detect unused or overly permissive tokens, and then revoke or renew them as necessary.
The List Tokens endpoint returns a list of access tokens for a Zendesk account. Only admins can make the request. This endpoint does not provide full user or client details, token expiration information, or in-depth usage statistics.
curl https://{subdomain}.zendesk.com/api/v2/oauth/tokens.json \-v -u {email_address}/token:{api_token}
Here is an example response:
{"tokens": [{"url": "https://example.zendesk.com/api/v2/oauth/tokens/15022151901588.json","id": 15022151901588,"user_id": 1905826600027,"client_id": 223443,"token": "52d7ef4ee0",..."scopes": ["tickets:read"]},...]}
- id: Unique identifier for the access token, used for revocation or inspection.
- user_id: The Zendesk user id associated with the token.
- client_id: The OAuth client application id that requested the token.
- token: Partial token string (first 10 characters) for identification only.
- scopes: Permissions granted to the token, such as read or write access to tickets.
Python script to list tokens
Here's a short Python script to list all tokens for your account.
import osimport requests# Load Zendesk API credentials and subdomain from environment variablesZENDESK_API_TOKEN = os.getenv('ZENDESK_API_TOKEN')ZENDESK_USER_EMAIL = os.getenv('ZENDESK_USER_EMAIL')ZENDESK_SUBDOMAIN = os.getenv('ZENDESK_SUBDOMAIN')# Exit if any required environment variables are missingif not all([ZENDESK_API_TOKEN, ZENDESK_USER_EMAIL, ZENDESK_SUBDOMAIN]):print('Error: Missing required environment variables.')exit(1)# Set up HTTP Basic Authentication with email/token and API tokenAUTH = f'{ZENDESK_USER_EMAIL}/token', ZENDESK_API_TOKENAPI_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/oauth/tokens.json"response = requests.get(API_URL, auth=AUTH)response.raise_for_status()tokens = response.json().get("tokens", [])for token in tokens:print(f"Token id: {token['id']}, User: {token['user_id']}, Scopes: {token['scopes']}")
Here's an example output:
Token id: 33160940517527, User: 1509756491122, Scopes: ['read', 'write']Token id: 33188809869719, User: 1509756491122, Scopes: ['read', 'write']Token id: 1501173602742, User: 1509756491122, Scopes: ['any_channel:write']
Python script to show more token details
The following script expands the above example to show:
- Who owns each token (user details)
- Which application issued the token (client details)
- Token validity period and revocation status
import osimport requests# Load Zendesk API credentials and subdomain from environment variablesZENDESK_API_TOKEN = os.getenv('ZENDESK_API_TOKEN')ZENDESK_USER_EMAIL = os.getenv('ZENDESK_USER_EMAIL')ZENDESK_SUBDOMAIN = os.getenv('ZENDESK_SUBDOMAIN')# Exit if any required environment variables are missing to prevent unauthorized callsif not all([ZENDESK_API_TOKEN, ZENDESK_USER_EMAIL, ZENDESK_SUBDOMAIN]):print("Error: Missing required environment variables.")exit(1)# Setup HTTP Basic Authentication using API tokenAUTH = f'{ZENDESK_USER_EMAIL}/token', ZENDESK_API_TOKEN# Base API URL constructed using the Zendesk subdomainBASE_API_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2"def get_oauth_tokens():"""Get the list of OAuth access tokens for the Zendesk account."""url = f"{BASE_API_URL}/oauth/tokens.json"response = requests.get(url, auth=AUTH) # Send authenticated GET requestresponse.raise_for_status() # Raise exception on HTTP errorreturn response.json().get('tokens', []) # Return list of tokens or empty listdef get_users(user_ids):"""Retrieve detailed user info.Returns a dictionary mapping user id to user data."""if not user_ids:return {} # Return empty dict if no ids providedusers = {}for user_id in user_ids:url = f'{BASE_API_URL}/api/v2/users/{user_id}'response = requests.get(url, auth=AUTH)user_data = response.json()users[user_data['id']] = user_datareturn usersdef get_oauth_client(client_id):"""Retrieve details for a single OAuth client application by client id.Returns a dictionary of client info or empty dict if not found."""url = f"{BASE_API_URL}/oauth/clients/{client_id}.json"response = requests.get(url, auth=AUTH)if response.status_code == 404:# Client not found or no access, log and return emptyprint(f"OAuth client {client_id} not found or inaccessible.")return {}response.raise_for_status()return response.json().get('client', {})def get_token_details(token_id):"""Retrieve detailed info for a specific OAuth token by token id.Returns a dictionary with token metadata."""url = f"{BASE_API_URL}/oauth/tokens/{token_id}.json"response = requests.get(url, auth=AUTH)response.raise_for_status()return response.json().get('token', {})def main():tokens = get_oauth_tokens() # Get all OAuth tokensprint(f"Found {len(tokens)} OAuth tokens:")user_ids = set() # Colect unique user ids from tokensclient_ids = set() # Collect unique OAuth client ids from tokens# Iterate tokens to display summary info and collect related idsfor token in tokens:print(f"Token id: {token['id']}, Partial token: {token.get('token')}, Scopes: {token.get('scopes')}")user_ids.add(token.get('user_id'))client_ids.add(token.get('client_id'))# Get detailed user information for collected user idsusers = get_users(user_ids)print("\nFetched User Details:")for uid, user in users.items():print(f"User id: {uid}, Email: {user.get('email')}, Name: {user.get('name')}")# Get and display OAuth client details per collected client idprint("\nFetching OAuth Client Details:")for cid in client_ids:client = get_oauth_client(cid)print(f"Client id: {cid}, Name: {client.get('name')}, Redirect URIs: {client.get('redirect_uri')}")# Get detailed token metadata for each token id and displayprint("\nFetching Token Details:")for token in tokens:details = get_token_details(token['id'])print(f"Token id: {token['id']}, Expires At: {details.get('expires_at')}, Status: {details.get('status')}")if __name__ == "__main__":main()
Here's an example output:
Found 3 OAuth tokens:Token id: 33160940517527, Partial token: 5b24bd1adc, Scopes: ['read', 'write']Token id: 33188809869719, Partial token: b916c4b6b5, Scopes: ['read', 'write']Token id: 1501173602742, Partial token: ea604660a1, Scopes: ['any_channel:write']Fetched User Details:User id: 1509756491122, Email: [email protected], Name: Cris P BaconFetching OAuth Client Details:OAuth client 218 not found or inaccessible.Client id: 218, Name: None, Redirect URIs: NoneClient id: 33160833707415, Name: Talk Make test, Redirect URIs: ['https://www.example.com/oauth/cb/zendesk/']Fetching Token Details:Token id: 33160940517527, Expires At: None, Status: NoneToken id: 33188809869719, Expires At: None, Status: NoneToken id: 1501173602742, Expires At: None, Status: None
The example output shows:
- Token ids and partial tokens: Displays each token's unique id and a partial token string to differentiate tokens without exposing the full secrets.
- Scopes: The permissions assigned to each token. Such as
['read', 'write']or['any_channel:write']. - User details: Lists the users associated with the token, including email and name. In this example, the same user is associated with all three tokens.
- OAuth client details: Information about the OAuth client applications that issued the tokens.
- Token details: Metadata about each token, such as expiration date and status. In this example, these fields are empty, meaning the tokens have no expiration configured or the information is unavailable.