Initiate an oAuth flow via an Auth Provider

The flow can be invoked from a user-facing process. Here are the parameters:

  • /services/auth/xds/{org_id}/{authprovider_developer_name} - this issues the logout,
  • &startURL=/0XA... - this ID tells SF which Named Credential to link the grant against,
  • &scope=full... - list of scopes/privileges presented to the user at the Allow screen,

Apex code to return such a URL from a VF page action or button:

public PageReference authorizeNamedCredential(String authProvider, String namedCredential)
{
    AuthProvider provider = [
        SELECT Id
        FROM AuthProvider
        WHERE DeveloperName = :authProvider
    ];

    NamedCredential credential = [
        SELECT Id
        FROM NamedCredential
        WHERE DeveloperName = :namedCredential
    ];

    String oid = UserInfo.getOrganizationId();
    String domain = Url.getOrgDomainUrl().toExternalForm();
    String path = '/services/auth/xds/' + oid + '/' + authProvider;
    String startUrl = '/' + String.valueOf(credential.Id).left(15);

    PageReference redirect = new PageReference(domain + path);
    redirect.getParameters().put('startURL', startUrl);
    redirect.getParameters().put('scope', 'full refresh_token');
    return redirect;
}

After logging back in, the user must manually click Allow:

named credential grant

Technically it's possible to skip the manual authorization nag by pre-authorizing the app on a Profile or Permission Set. But the pre-authorization step is itself a manual process!

  • Deploy the Connected App into the org per your Metadata API
  • Go to Setup > Connected Apps > Manage Apps > Edit Policies
  • Change "Permitted Users" to "Admin approved users are pre-authorized" then save
  • Edit the Profiles or Permission Sets then navigate to Connected App Access
  • Enable the app, then save.

If all you need to do is to kick off the oAuth flow so that the user may authorize the app, the auth provider supports this natively:

public PageReference (String authProvider) {

        AuthProvider provider = [
            SELECT Id,OauthKickoffUrl
            FROM AuthProvider
            WHERE DeveloperName = :authProvider
        ];

        return new PageReference(provider.OauthKickoffUrl);
 }