Programmatically Authenticate Named / External Credentials through Apex
Fri May 17 2024 08:14:24 GMT+0000 (Coordinated Universal Time)
Saved by @Justus
/** * Method to authenticate an external credential using the external credential using the * Auth URL. */ String externalCredential = 'TDX_DC_ORG'; String principalName = 'NAMED_PRINCIPAL'; System.debug(getAuthUrlFromConnectApi(externalCredential, principalName)); String getAuthUrlFromConnectApi(String externalCredential, String principalName){ String body = JSON.serialize( new Map<String,String>{ 'externalCredential'=> externalCredential, 'principalName' => principalName, 'principalType' => 'NamedPrincipal' } ); // Create a new request HttpRequest req = new HttpRequest(); req.setMethod('POST'); req.setEndpoint(Url.getOrgDomainUrl().toExternalForm() + '/services/data/v60.0/named-credentials/credential/auth-url/o-auth'); req.setHeader('Authorization','Bearer ' + UserInfo.getSessionId()); req.setHeader('Content-Length', String.ValueOf(body.length())); req.setBody(body); System.debug(body); // Execute request and fetch response HttpResponse res = new Http().send(req); // Throw an error if the status code for the final call is not equal to 200 if(res.getStatusCode() != 200){ throw new StringException('Unexpected status code in connect api callout. Response: ' + res.getBody()); } // Parse the response into a Connect API class ConnectApi.OAuthCredentialAuthUrl ocau = (ConnectApi.OAuthCredentialAuthUrl) JSON.deserializeStrict( res.getBody(), ConnectApi.OAuthCredentialAuthUrl.class ); // Return the authentication from the Connect API response return ocau.authenticationUrl; } // This comes from your Apex API Call Integer statusCode = 400; Boolean statusIsAuthError = true; // Configuration for String authUrl = 'https://dc-mgmt-dev-ed.develop.my.salesforce.com/services/auth/xds/TDX_DC_ORG?startURL=/0puQy0000000AQn'; // Run this logic when if(statusCode == 400 && statusIsAuthError){ // Start the flow by calling the external credential auth URL and validate that the response is as we expect RedirectResponse initialResponse = validateRedirectResponse( callout( authUrl, null ) ); // Handle the first redirect and validate that the response is as we expect RedirectResponse firstRedirectResponse = validateRedirectResponse( callout( initialResponse.location, initialResponse.cookie ) ); // Handle the second redirect and validate that the response is as we expect // !! Use the cookie from the initial request !! HttpResponse finalResponse = callout( firstRedirectResponse.location, initialResponse.cookie ); // Throw an error if the status code for the final call is not equal to 200 if(finalResponse.getStatusCode() != 200){ throw new StringException('Unexpected status code in final callout. Response: ' + finalResponse.getBody()); } } /** * Method to do a get callout with a cookie header setter */ HttpResponse callout(String endpoint, String cookie){ HttpRequest req = new HttpRequest(); req.setEndpoint(endpoint); req.setMethod('GET'); // Set the cookie if not blank if(!String.isBlank(cookie)){ secondRedirectRequest.setHeader('Cookie',cookie); } HttpResponse res = new Http().send(req); } /** * Basic validation that the response is as we expect */ RedirectResponse validateRedirectResponse(HttpResponse res){ // Check it is a status 302 if(res.getStatusCode() != 302){ throw new StringException('Unexpected response code, expected the response status code to be 302'); } // Return a redirect response object return new RedirectResponse( res.getHeader('Location') res.getHeader('Set-Cookie'); ); } /** * Simple redirect response object to make the code more readable */ class RedirectResponse{ public String location; public String cookie; RedirectResponse(String location, String cookie){ this.location = location; this.cookie = cookie; } }
Comments