This document explains how the Webex SDK handles OAuth authorization in browser environments, covering the complete flow from initialization to token management.
- Browser Webex Initialization
- Browser OAuth Flow Trigger
- Authorization Code Processing
- Token Generation and Exchange
- Refresh Token Management
- Browser Ready and Authorization Events
Browser applications initialize the Webex SDK with OAuth parameters:
// Basic browser initialization
const webex = Webex.init({
credentials: {
client_id: 'your-client-id',
redirect_uri: 'https://your-app.com/callback',
scope: 'spark:all spark:kms',
clientType: 'public' // or 'confidential'
}
});Parameters:
- client_id: Your registered application ID
- redirect_uri: Where to send the user after authentication
- scope: Requested permissions (e.g., 'spark:all spark:kms')
- clientType: 'public' (default) or 'confidential'
Reference: See docs/samples/browser-auth/app.js for a working example
The browser plugin automatically selects OAuth flow based on clientType:
// Public client (default) - uses response_type=token
const webex = Webex.init({
credentials: {
client_id: 'your-client-id',
clientType: 'public' // or omit (defaults to public)
}
});
// Calls initiateImplicitGrant() -> response_type=token
// Confidential client - uses response_type=code
const webex = Webex.init({
credentials: {
client_id: 'your-client-id',
clientType: 'confidential'
}
});
// Calls initiateAuthorizationCodeGrant() -> response_type=codeFlow selection:
- Public Client (
clientType: 'public'or undefined): Uses Implicit Grant withresponse_type=token - Confidential Client (
clientType: 'confidential'): Uses Authorization Code Grant withresponse_type=code
Reference: initiateLogin() method in packages/@webex/plugin-authorization-browser/src/authorization.js
Webex ID Broker supports several OAuth 2.0 grant types. The browser SDK implements them as follows:
Webex ID Broker: Returns authorization code after user authentication
Browser SDK: Uses response_type=code, then exchanges code for tokens
// SDK automatically handles this flow
const webex = Webex.init({
credentials: { clientType: 'confidential', /* other config */ }
});
webex.authorization.initiateLogin(); // Uses response_type=codeWebex ID Broker: Returns access token directly after user authentication
Browser SDK: Uses response_type=token, receives token in URL hash
// SDK automatically handles this flow
const webex = Webex.init({
credentials: { clientType: 'public', /* other config */ }
});
webex.authorization.initiateLogin(); // Uses response_type=tokenWebex ID Broker: Exchanges refresh token for new access token
Browser SDK: Automatically uses grant_type=refresh_token when tokens expire
// SDK handles refresh automatically, or manually:
webex.credentials.supertoken.refresh(); // Uses grant_type=refresh_tokenWebex ID Broker: Application-to-application authentication
Browser SDK: Not supported (requires client secret)
Note: Client credentials grant is only available in Node.js SDK since it requires a client secret that cannot be safely stored in browsers.
- Security: Tokens exposed in browser URL (less secure)
- Client Secret: No client secret required
- Token Location: Access token in URL hash fragment
- Redirect: Single redirect with token
- Best For: Single-page applications, mobile apps
- Security: More secure, tokens never exposed to browser
- Client Secret: Requires client secret
- Token Location: Authorization code in URL, exchanged server-side
- Redirect: Two-step process (code → token exchange)
- Best For: Web applications with backend
During browser initialization, the plugin automatically:
- Parses current URL for OAuth tokens/codes
- Checks for OAuth errors in URL parameters
- Validates CSRF tokens for security
- Cleans the URL by removing sensitive parameters
Reference: initialize() method in packages/@webex/plugin-authorization-browser/src/authorization.js
The initiateLogin() method redirects users to Webex's identity broker for authentication. It does NOT accept email/password directly.
// Basic login - redirects to Webex login page
webex.authorization.initiateLogin()
// Login with custom state data
webex.authorization.initiateLogin({
state: {
returnUrl: '/dashboard',
userId: 'user123'
}
})
// Login in popup window (default dimensions: 600x800)
webex.authorization.initiateLogin({
separateWindow: true
})
// Login in popup with custom dimensions
webex.authorization.initiateLogin({
separateWindow: {
width: 800,
height: 600
}
})Parameters:
- options.state (Object, optional): Custom data included in OAuth state
- options.separateWindow (Boolean|Object, optional): Open in popup window
Process:
- Generates CSRF token for security
- Determines flow type based on client configuration
- Builds OAuth URL with required parameters
- Redirects user to Webex identity broker
Reference: initiateLogin() method in browser authorization plugin
Browser-specific CSRF protection:
- Generates UUID token using
uuid.v4() - Stores in sessionStorage for later verification
- Includes in state parameter of OAuth request
Reference: _generateSecurityToken() method in browser plugin
Browser supports multiple redirection methods:
- Same window: Default behavior (full page redirect)
- Popup window: Optional separate window with configurable dimensions
Reference: initiateImplicitGrant() and initiateAuthorizationCodeGrant() methods
User experience at Webex identity broker:
- User enters credentials (username/password, SSO, etc.)
- Identity verification occurs
- Consent screen may appear for scope approval
- Authorization decision is made
After successful authentication:
- Implicit Grant: User redirected with access token in URL hash
- Authorization Code Grant: User redirected with authorization code in query parameters
Browser SDK processes the return URL automatically:
- URL parsing during plugin initialization
- Error checking for OAuth errors
- Token/code extraction from URL parameters
- State validation for CSRF protection
Reference: initialize() and _parseHash() methods in browser plugin
Browser security validation:
- Extract state parameter from redirect URL
- Decode Base64 state object
- Compare CSRF tokens (URL vs sessionStorage)
- Throw error if tokens don't match
Reference: _verifySecurityToken() method in browser plugin
For browser implicit grant, access token comes directly in URL hash:
- access_token
- token_type (Bearer)
- expires_in
- scope
Note: Refresh tokens are generally not provided in implicit grant flows due to security reasons. Most OAuth providers, including Webex, do not issue refresh tokens for implicit grant to prevent long-lived tokens from being exposed in browser environments. Applications using implicit grant should expect to obtain new access tokens by re-authenticating the user when the current token expires.
Reference: Token parsing in _parseHash() method
For browser confidential clients, code exchange happens:
- Client-side: Code captured from URL
- Server-side: Code exchanged for tokens using client secret
Browser JWT authentication for guest users:
// Create JWT token
webex.authorization.createJwt({
issuer: 'your-guest-issuer-id',
secretId: 'your-base64-encoded-secret',
displayName: 'Guest User Name',
expiresIn: '12h'
}).then(({jwt}) => {
console.log('Created JWT:', jwt);
// Exchange JWT for access token
return webex.authorization.requestAccessTokenFromJwt({jwt});
}).then(() => {
console.log('Guest user authenticated');
}).catch(error => {
console.error('JWT authentication failed:', error);
});Process:
- Create JWT token with issuer, secret, display name
- Exchange JWT for access token via API call
Reference: createJwt() and requestAccessTokenFromJwt() methods in browser plugin
Browser token storage:
- Stored in credentials object via
webex.credentials.set() - Persisted in browser storage (localStorage/sessionStorage)
- Monitored for expiration by interceptors
Browser monitors token validity through:
// Check if token is expired
if (webex.credentials.supertoken.isExpired) {
console.log('Token is expired');
// SDK will automatically refresh if refresh token available
}
// Check if token can be refreshed
if (webex.credentials.supertoken.canRefresh) {
console.log('Token can be refreshed');
} else {
console.log('User needs to re-authenticate');
webex.authorization.initiateLogin();
}
// Manual token refresh
webex.credentials.supertoken.refresh().then((newToken) => {
console.log('Token refreshed successfully');
}).catch((error) => {
console.error('Token refresh failed:', error);
webex.authorization.initiateLogin();
});Detection mechanisms:
- HTTP interceptors checking responses
- Automatic refresh triggers before expiration
- Error handling for 401 Unauthorized responses
Browser refresh token process using refreshCallback:
// Configure refresh callback during initialization
const webex = Webex.init({
credentials: {
client_id: 'your-client-id',
redirect_uri: 'https://your-app.com/callback',
scope: 'spark:all spark:kms',
refreshCallback: (webex, token) => {
// Custom refresh logic for browser
return webex.request({
method: 'POST',
uri: 'https://webexapis.com/v1/access_token',
form: {
grant_type: 'refresh_token',
refresh_token: token.refresh_token,
client_id: token.config.client_id
}
}).then(response => response.body);
}
}
});Refresh process:
- POST request to
/access_tokenendpoint - grant_type: "refresh_token"
- Current refresh token as parameter
- Client ID for identification
- New tokens returned and stored automatically
SDK automatically handles token refresh:
// SDK automatically refreshes tokens before API calls
webex.people.get('me').then(person => {
// Token was automatically refreshed if needed
console.log('Current user:', person.displayName);
}).catch(error => {
if (error.message.includes('unauthorized')) {
// Refresh failed, user needs to re-authenticate
webex.authorization.initiateLogin();
}
});
// Listen for token refresh events
webex.credentials.on('change:supertoken', () => {
console.log('Token was refreshed');
});Browser JWT refresh using callback:
// Configure JWT refresh callback
const webex = Webex.init({
credentials: {
jwtRefreshCallback: async (webex) => {
// Get new JWT from your backend
const response = await fetch('/api/jwt-refresh', {
method: 'POST',
credentials: 'include'
});
const { jwt } = await response.json();
return jwt;
}
}
});
// SDK automatically uses jwtRefreshCallback when JWT expiresReference: JWT refresh implementation in browser authorization plugin
Browser SDK initialization phases:
- Construction: Basic object creation
- Plugin Loading: Authorization and other plugins initialize
- Storage Loading: Browser storage data retrieval
- Authentication Check: Token validation and refresh
- Ready State: All systems operational
Browser-specific events:
// Listen for SDK ready event
webex.once('ready', () => {
console.log('Webex SDK is ready and authenticated');
});
// Listen for unauthorized event
webex.on('unauthorized', () => {
console.log('User authentication lost - redirect to login');
webex.authorization.initiateLogin();
});
// Listen for logout event
webex.on('client:logout', () => {
console.log('User has logged out');
});Events:
- ready: SDK fully initialized and authenticated
- unauthorized: User authentication lost
- client:logout: User has logged out
Check browser authentication status:
// Check if user can make authenticated requests
if (webex.canAuthorize) {
console.log('User is authenticated');
// Make API calls
} else {
console.log('User needs to login');
webex.authorization.initiateLogin();
}
// Check if authorization is in progress
if (webex.authorization.isAuthorizing) {
console.log('Authorization in progress...');
}
// Check if SDK is fully ready
if (webex.ready) {
console.log('SDK is fully initialized');
}Status Properties:
webex.canAuthorize: Boolean for authenticated requests capabilitywebex.authorization.isAuthorizing: Boolean for authorization in progresswebex.ready: Boolean for SDK fully initialized
Browser ready state depends on:
- Credentials loaded from browser storage
- All plugins initialized
- Services catalog loaded
- Authentication state established
- Main Browser Plugin:
packages/@webex/plugin-authorization-browser/src/authorization.js - Browser Auth Sample:
docs/samples/browser-auth/app.js - Browser Plugin Docs:
packages/@webex/plugin-authorization-browser/README.md
This package is maintained by Cisco Webex for Developers.
Pull requests welcome. Please see CONTRIBUTING.md for more details.
© 2016-2025 Cisco and/or its affiliates. All Rights Reserved.