OAuth2
What is OAuth2?
OAuth 2.0 is the industry-standard protocol for authorization. It allows your app to access specific data in user accounts with explicit user consent, without requiring users to share their passwords.
- Secure Access: Users authorize without sharing passwords
- Granular Permissions: Request only the scopes your app needs
- Token-Based: Access and refresh tokens for secure API calls
- User Consent: Explicit approval for each permission
How OAuth2 Works
OAuth2 uses the authorization code grant flow:
The flow ensures secure, controlled access by:
- Requiring explicit user consent
- Using temporary authorization codes
- Providing time-limited access tokens
- Supporting granular permissions through scopes
Creating an OAuth2 App
Select app type
Choose the appropriate app type:
Organization App
Personal App
Organization App: Generate organization-level access tokens
Use for:
- Contract data reading
- Timesheets management
- Invoice adjustments
- SCIM API integration
- Accounting data access
Provides access to all organization resources based on granted scopes.
OAuth2 Flow Implementation
Step 1: Request Permissions
Redirect users to Deel’s authorization endpoint with the required parameters:
Required Parameters:
Example URL:
Step 2: User Authorizes
The user sees a consent screen showing:
- Your app name and logo
- What permissions (scopes) you’re requesting
- Option to approve or deny
When they approve, they’re redirected to your redirect_uri with an authorization code:
Always verify the state parameter matches what you sent to prevent CSRF attacks.
Step 3: Exchange Code for Access Token
Exchange the authorization code for an access token by making a POST request:
Authentication:
- Use HTTP Basic authentication
- Encode your credentials:
base64(client_id:client_secret)
Example encoding:
Response:
- Access tokens are valid for 30 days (2,592,000 seconds)
- Refresh tokens are valid for 90 days
Step 4: Make Authenticated Requests
Use the access token to make API requests. OAuth2 requests require two headers:
OAuth2 requests require both the Authorization header AND the x-client-id header. Missing either will result in a 401 error.
Token Rotation
Access tokens expire after 30 days. Refresh them before expiration to maintain uninterrupted access.
Refreshing Access Tokens
Make a POST request with your refresh token:
Response includes:
- New access token (valid for another 30 days)
- Token expiration time (2,592,000 seconds)
- New refresh token (use this for next refresh)
- Token type (Bearer)
- Authorized scopes
Proactive rotation: Don’t wait until tokens expire! Set up a scheduled job to refresh tokens every 25 days to avoid disruption. Store the new refresh token for future use.
Best Practices for Token Rotation
Automatic Refresh
Implement automatic token refresh in your application:
- Check token expiration before each request
- Refresh proactively (5 days before expiration)
- Handle refresh failures gracefully
- Store new tokens securely
Handle Expired Tokens
If a request fails with 401:
- Attempt to refresh the token
- Retry the original request with new token
- If refresh fails, prompt user to re-authorize
Secure Token Storage
- Store tokens encrypted at rest
- Never expose tokens in URLs or logs
- Use secure session storage for web apps
- Implement token revocation on logout
Scopes Reference
Request only the scopes your application needs. Each API endpoint specifies which scopes are required - check the API Reference for details.
Scope patterns: Scopes follow the pattern {resource}:read or {resource}:write (e.g., contracts:read, timesheets:write).
Common scope combinations:
Recommended App Types by Use Case
Troubleshooting
401 Unauthorized Error
Common causes:
- Invalid or expired access token
- Missing
x-client-idheader - Token doesn’t have required scopes
Solutions:
- Refresh the access token
- Verify both
Authorizationandx-client-idheaders are present - Check token scopes match endpoint requirements
403 Forbidden Error
Common causes:
- Token lacks required scopes
- User doesn’t have permission to access resource
- App type mismatch (personal app trying to access org resources)
Solutions:
- Review requested scopes during authorization
- Use organization app for org-wide resources
- Verify user has appropriate permissions
Invalid Grant Error
When exchanging code or refreshing token:
- Authorization code already used
- Refresh token expired
redirect_uridoesn’t match
Solutions:
- Authorization codes are single-use only
- Request new authorization if refresh token expired
- Ensure
redirect_uriexactly matches registered URI
State Mismatch
Cause:
- CSRF protection - returned
statedoesn’t match sent state
Solutions:
- Store state value in session before redirect
- Validate returned state matches stored value
- Generate new state for each authorization request
Security Best Practices
Validate State Parameter
Always verify the state parameter to prevent CSRF attacks
Secure Client Secret
Never expose client secret in client-side code or version control
Use HTTPS
Redirect URIs must use HTTPS (except localhost for development)
Minimal Scopes
Request only the permissions your app actually needs
Token Encryption
Store access and refresh tokens encrypted at rest
Implement Logout
Revoke tokens when users disconnect or log out