Skip to main content

Obtaining Access Token Using Refresh Token in Salesforce Apex

๐Ÿ’ฌ In plain words: The OAuth 2.0 refresh token flow allows integrations to programmatically request a new, short-lived session access token from Salesforce without requiring interactive user re-authentication.

OAuth 2.0 is a widely used authentication protocol that provides secure access to resources on behalf of a user or an application. In this blog post, we will walk through the process of configuring a Connected App in Salesforce, obtaining a refresh token, and using it to acquire an access token using Apex code.

Step 1: Configure Connected App in Salesforce

⚙ Setup Configuration
  1. Log in to your Salesforce org, navigate to Setup, and search for App Manager.
  2. Click New Connected App and configure the following parameters:
    • Connected App Name: RefreshTokenApp
    • API Name: RefreshTokenApp
    • Enable OAuth Settings: Checked
    • Callback URL: https://localhost
    • Selected OAuth Scopes: Access and manage your data (api), Perform requests on your behalf at any time (refresh_token, offline_access)

Step 2: Obtain Refresh Token

The following Apex class handles sending an HTTP POST callout to the Salesforce OAuth 2.0 token endpoint to request a fresh token using your existing refresh token, client ID, and client secret.

public class RefreshTokenExample {
    
    public static String refreshTokenFlow() {
        String refreshToken = 'YOUR_REFRESH_TOKEN'; // Replace with your actual refresh token
        String clientId = 'YOUR_CLIENT_ID';         // Replace with your Connected App Consumer Key
        String clientSecret = 'YOUR_CLIENT_SECRET'; // Replace with your Connected App Consumer Secret
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://login.salesforce.com/services/oauth2/token');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        
        String requestBody = 'grant_type=refresh_token' +
                             '&client_id=' + EncodingUtil.urlEncode(clientId, 'UTF-8') +
                             '&client_secret=' + EncodingUtil.urlEncode(clientSecret, 'UTF-8') +
                             '&refresh_token=' + EncodingUtil.urlEncode(refreshToken, 'UTF-8');
                             
        req.setBody(requestBody);
        
        Http http = new Http();
        HttpResponse res = http.send(req);
        
        return res.getBody();
    }
}

Step 3: Extract Access Token from Response

Once the token endpoint returns the JSON response, deserialize the string using JSON.deserializeUntyped to extract the access_token value.

public class AccessTokenExample {
    
    public static String getAccessToken() {
        String refreshTokenResponse = RefreshTokenExample.refreshTokenFlow();
        Map<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(refreshTokenResponse);
        
        String accessToken = (String) responseMap.get('access_token');
        return accessToken;
    }
}

Step 4: Execution & Expected Debug Output

You can execute the token retrieval in an Anonymous Window or class method to verify the integration:

public class MainTestClass {
    public static void execute() {
        String accessToken = AccessTokenExample.getAccessToken();
        System.debug('Access Token: ' + accessToken);
    }
}

Expected Output in Debug Logs:

USER_DEBUG|[5]|DEBUG|Access Token: 00D5h000000xxxx!AR8AQE...
⚠ SECURITY TRAP: Never hardcode client secrets, consumer keys, or refresh tokens directly in Apex classes! Hardcoded credentials can be exposed in metadata backups or sandbox refreshes. Always store secrets in External Credentials or encrypted Custom Metadata Types / Protected Custom Settings.
๐Ÿง  Key Takeaway: Using `grant_type=refresh_token` in HTTP callouts keeps integration sessions continuously active without requiring manual user re-authorization.
๐Ÿงญ 360 Card — OAuth 2.0 Refresh Token Flow in Apex
  • Rule: Include the refresh_token or offline_access scope when configuring your Connected App to permit background access token renewal.
  • Gain: Enables persistent, unattended automated background integrations between external servers and Salesforce.
  • Price: Managing refresh token lifecycle security requires careful encryption and storage governance.
  • Limits: Subject to standard Apex HTTP callout limits, remote site setting requirements, and Connected App refresh token policy revocations.

Conclusion

Congratulations! You've successfully obtained an access token using a refresh token in Salesforce using Apex code. This authentication mechanism allows integrations to keep sessions active seamlessly without requiring user re-authentication. Make sure to replace placeholders like YOUR_REFRESH_TOKEN, YOUR_CLIENT_ID, and YOUR_CLIENT_SECRET with your actual values before deploying.