Created
August 15, 2022 09:23
-
-
Save aidan-harding/245cf32799f6ba043e5ddaa97535623a to your computer and use it in GitHub Desktop.
Auth. Provider for Client Credentials OAuth flow in Salesforce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author [email protected] | |
* @date 21/10/2020 | |
* @description For implementing the Client Credentials OAuth Flow using Named Credentials to store the client id | |
* and client secret. The initiate method is a dummy one, going straight to the callback, which does a callout to the | |
* token endpoint. Refreshing is also a dummy, simply obtaining a new token with the original client id and secret. | |
*/ | |
public with sharing class ClientCredentialsAuthProvider extends Auth.AuthProviderPluginClass { | |
@TestVisible | |
private static final String CALLBACK_URL = Client_Credentials_Auth_Provider__mdt.Callback_URL__c.getDescribe().getName(); | |
@TestVisible | |
private static final String NAMED_CREDENTIAL_FOR_TOKEN = Client_Credentials_Auth_Provider__mdt.Named_Credential_For_Token__c.getDescribe().getName(); | |
public String getCustomMetadataType() { | |
return Client_Credentials_Auth_Provider__mdt.SObjectType.getDescribe().getName(); | |
} | |
public PageReference initiate(Map<String, String> config, String stateToPropagate) { | |
PageReference result = new PageReference(config.get(CALLBACK_URL)); | |
result.getParameters().put('state', stateToPropagate); | |
return result; | |
} | |
public Auth.AuthProviderTokenResponse handleCallback(Map<String, String> config, Auth.AuthProviderCallbackState callbackState) { | |
return new Auth.AuthProviderTokenResponse( | |
config.get(NAMED_CREDENTIAL_FOR_TOKEN), | |
retrieveToken(config.get(NAMED_CREDENTIAL_FOR_TOKEN)), | |
'dummy_refresh_token', | |
callbackState.queryParameters.get('state')); | |
} | |
public Auth.UserData getUserInfo(Map<String, String> config, Auth.AuthProviderTokenResponse response) { | |
// email field is used to display who is logged in on the OAuth Named Credential (not the token Named Credential) | |
return new Auth.UserData('fakeId', 'first', 'last', 'full', config.get(NAMED_CREDENTIAL_FOR_TOKEN), 'link', null, null, null, null, null); | |
} | |
public override Auth.OAuthRefreshResult refresh(Map<String, String> config, String refreshToken) { | |
return new Auth.OAuthRefreshResult(retrieveToken(config.get(NAMED_CREDENTIAL_FOR_TOKEN)), refreshToken, null); | |
} | |
private String retrieveToken(String tokenNamedCredential) { | |
HttpRequest request = new HttpRequest(); | |
request.setEndpoint('callout:' + tokenNamedCredential); | |
request.setHeader('Content-Type','application/json'); | |
request.setHeader('Accept','application/json'); | |
request.setMethod('POST'); | |
request.setBody(JSON.serialize(new Map<String, String> { | |
'grant_type' => 'client_credentials', | |
'client_id' => '{!$Credential.UserName}', | |
'client_secret' => '{!$Credential.Password}' | |
})); | |
HttpResponse response = new Http().send(request); | |
AuthResponse parsedResponse = (AuthResponse)JSON.deserialize(response.getBody(), AuthResponse.class); | |
return parsedResponse.access_token; | |
} | |
private class AuthResponse { | |
@SuppressWarnings('PMD.VariableNamingConventions') // Has to match the JSON | |
public String access_token; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment