When do Salesforce access tokens expire?
Tags: webdev, api, oauth, salesforce
Published: 2021-01-21 23:09:20

If you're building a Salesforce integration into your app, particularly a "Connected App" style of integration, and your integration uses [OAuth to get access to Salesforce's REST APIs](https://help.salesforce.com/articleView?id=remoteaccess_authenticate.htm&type=5), you may be wondering when the access tokens issued by Salesforce expire.

According to the [OAuth 2.0 spec](https://tools.ietf.org/html/rfc6749#section-4.2.2) the `expires_in` parameter is included with the Access Token response and provides the lifetime of the returned token in seconds. And while this parameter is extremely common in OAuth implementations, it is merely *recommended* and not *required*. The Salesforce OAuth implementation does *not* use this parameter.

### Typical Token Expiration

In our experience at [Xkit](https://xkit.co), Salesforce Access Tokens typically expire in 2 hours (7,200 seconds), but this value is not guaranteed to be static—Salesforce could change it at any time with no warning.

> Salesforce Access Tokens typically expire in 2 hours

### How to determine token expiration

So what do you do? You have two options:

1. Use your access token until you receive a `401` HTTP status code, and only refresh it then
2. Use Salesforce's token introspection endpoint to determine when the token expires

### Token Introspection

That's right! While Salesforce does not include an `expires_in` parameter, they do have a special token introspection endpoint as part of the [extension to the OAuth 2.0 spec](https://tools.ietf.org/html/rfc7662). This endpoint ([Salesforce docs here](https://help.salesforce.com/articleView?id=remoteaccess_oidc_token_introspection_endpoint.htm&type=5)) returns a JSON object that includes an `exp` property. This `exp` corresponds to the [`exp` claim of the JWT spec](https://tools.ietf.org/html/rfc7519#section-4.1.4). Unlike the `expires_in` parameter, `exp` is a Unix epoch timestamp.

Here's an example request from the Salesforce docs:

```
POST /services/oauth2/introspect HTTP/1.1
Host: https://mycompany.my.salesforce.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic M01WRzlsS2NQb05JTlZCSVBKamR3MUo5TExNODJIbkZWVlgxOUtZMQp1QTVtdTBRc
UVXaHFLcG9XM3N2RzNYSHJYRGlDUWpLMW1kZ0F2aENzY0E5R0U6MTk1NTI3OTkyNTY3NTI0MTU3MQ==

token=00DR00000009GVP!ARQAQE5XuPV7J4GoOu3wvLZjZI_TxoBpeZpRb6d8AVdII6cz
_BY_uu1PKxGeAjkSvO0LpWoL_qfbQWKlXoz1f2ICNiy.6Ndr&
token_type_hint=access_token
```

And an example response from our own experience:

```
HTTP/1.1 200 OK
Content-Type: application/json

{"active":true,"scope":"api refresh_token openid","client_id":"3MVG9lKcPoNINVBIPJjdw1J9LLM82HnFVVX19KY1uA5mu0QqEWhqKpoW3svG3XHrXDiCQjK1mdgAvhCscA9GE","username":"user@example.com\",\"sub\":\"https://login.salesforce.com/id/000000000000000000/000000000000000000\",\"token_type\":\"access_token\",\"exp\":1610509606,\"iat\":1610502406,\"nbf\":1610502406}
```

### Conclusion

So if you need to know when your Salesforce Access Token expires, call the introspection endpoint and you can figure it out for yourself. And don't forget to add the special `refresh_token` scope so you can refresh your access when it does expire.

Of course, if you want to avoid building (or heck, even learning) all that, you can use [Xkit's Salesforce Connector](https://app.xkit.co/connectors/new/salesforce) and be up and running with always-fresh access tokens in a half hour.