Asset management scheduled jobs fail due to API token expiry

We’re experiencing intermittent failures with our scheduled asset management jobs in D365 F&O 10.0.41. The jobs run perfectly for about 50-55 minutes, then suddenly fail with authentication errors. Our integration uses OAuth2 tokens to update asset maintenance schedules via REST API, and we’re seeing token expiry issues.

Error pattern we’re observing:


HTTP 401: Unauthorized - Token expired
at AssetMaintenanceScheduler.updateAsset()
Timestamp: 3600 seconds after job start

The OAuth2 token lifecycle seems to be the culprit - tokens expire after 1 hour but our batch processes can run longer. We haven’t implemented proper refresh token handling in our API job configuration. How should we handle token refresh for long-running asset management operations? Any guidance on best practices for API job configuration with OAuth2 would be appreciated.

Let me provide a comprehensive solution covering all the OAuth2 token lifecycle aspects:

Token Lifecycle Management Strategy:

Implement token management at your middleware/integration layer, not in D365 batch jobs. This keeps your OAuth2 logic centralized and reusable across multiple jobs.

Refresh Token Implementation:

Create a TokenManager class that handles the complete OAuth2 token lifecycle:


// Pseudocode - Token Manager Pattern:
1. Store access token, refresh token, and expiry timestamp
2. Before each API call, check if token expires in <5 minutes
3. If expiring soon, use refresh token to get new access token
4. Update stored tokens and reset expiry timestamp
5. If refresh fails, fall back to full re-authentication
6. Implement retry logic with exponential backoff (2s, 4s, 8s)

API Job Configuration Best Practices:

For your asset management scheduled jobs:

  1. Token Acquisition: Obtain initial OAuth2 token before job execution starts, not during first API call

  2. Proactive Refresh: Set refresh trigger at 50 minutes (3000 seconds) to stay well ahead of 60-minute expiry

  3. Error Handling: Wrap all API calls in try-catch that specifically handles 401 errors. On 401, immediately attempt token refresh before retrying the failed operation

  4. Logging Strategy: Log these events separately:

    • Initial token acquisition
    • Proactive refresh operations
    • Failed API calls due to auth
    • Refresh token failures
    • Fallback to full re-authentication
  5. Configuration Parameters: Make these configurable:

    • Token refresh threshold (default 3000s)
    • Maximum retry attempts (default 3)
    • Backoff multiplier (default 2s base)

Azure AD Considerations:

Verify your Azure AD token lifetime policies:

  • Access token lifetime: typically 60-90 minutes
  • Refresh token lifetime: 90 days inactive, 180 days active use
  • Ensure your app registration has offline_access scope for refresh tokens

Implementation for Long-Running Jobs:

For asset management operations exceeding 1 hour:


// Pseudocode - Job Execution Pattern:
1. Acquire initial OAuth2 token with refresh token scope
2. Process assets in batches (e.g., 100 assets per batch)
3. Before each batch, check token expiry
4. If <5 min remaining, refresh proactively
5. Execute batch with current valid token
6. Log batch completion with token status

Monitoring and Diagnostics:

Implement these metrics:

  • Token refresh frequency per job
  • Failed refresh attempts
  • API calls rejected due to auth (should approach zero)
  • Average job duration vs token lifetime

This approach ensures your scheduled jobs handle OAuth2 token lifecycle properly, implement robust refresh token logic, and configure API jobs to prevent authentication failures. The key is proactive refresh rather than reactive error handling.

One final note: test your implementation with jobs that deliberately exceed 60 minutes to verify the refresh mechanism works correctly under real conditions.


This draft is based on general Microsoft Dynamics 365 knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

Classic token expiry issue. Your jobs are hitting the 3600-second token lifetime. You need to implement proactive token refresh before expiry. Check your OAuth2 provider settings - most support refresh tokens. In your job configuration, add a token refresh check every 45-50 minutes to stay ahead of the expiry window.

Thanks for the quick response. We do have refresh tokens available from Azure AD. The challenge is our current implementation doesn’t check token validity during execution. Should we wrap each API call with token validation, or is there a better approach? Also concerned about performance overhead if we’re checking token status too frequently.

Tested this on D365 F&O 10.0.38 with Azure AD OAuth2 — the TokenManager refresh buffer of 5 minutes eliminated all asset management batch job failures caused by mid-execution token expiry.

Don’t validate on every call - that’s overkill. Instead, implement a token manager service that tracks token issuance time and proactively refreshes at 50-55 minute mark. Store the token expiry timestamp when you first acquire it, then check elapsed time before each batch of operations. This way you refresh once per hour maximum, not on every API call. We use this pattern across multiple D365 integrations and it’s rock solid.

Also worth noting - make sure your refresh token itself doesn’t expire. Azure AD refresh tokens can have different lifetimes depending on your tenant configuration. We got burned by this when our refresh tokens expired after 90 days of inactivity. Check your Azure AD token lifetime policies and consider implementing a fallback to full re-authentication if refresh fails. The token lifecycle management needs to account for both access and refresh token expiry scenarios.

One thing to add regarding API job configuration - consider implementing exponential backoff for token refresh failures. We’ve seen scenarios where Azure AD is temporarily unavailable or rate-limited, and aggressive retry logic made things worse. Also, log token refresh events separately from job execution logs so you can monitor OAuth2 token lifecycle patterns over time. This helps identify if you’re hitting other Azure AD limits or if there are network issues affecting token acquisition.

This is all very helpful. Let me clarify the refresh token implementation - should this be handled at the D365 batch job level or in our middleware layer?