Controller REST personalizzato per accedere a Auth.AuthToken.getAccessToken che restituisce null

Oct 07 2020

A seguito di una domanda precedente:

  • Come accedere al token OAuth archiviato in NamedCredential utilizzando Apex per l'utilizzo in altre applicazioni di terze parti

Ho creato un endpoint REST personalizzato a cui accede tramite proxy Auth.AuthToken.getAccessToken(authProviderId, providerName);come suggerito da @identigral.

Classe controller REST Apex utilizzando API v49.0

@RestResource(urlMapping='/AccessToken/*')
global with sharing class AccessTokenRESTController {
    @HttpGet
    global static void getAccessToken() {
        try {
            String token = Auth.AuthToken.getAccessToken(authProviderId, providerName);

            System.debug(token);

            if (token == null) {
                RestContext.response.statusCode = 404;
                RestContext.Response.responseBody = Blob.valueOf('Unable to find token for authProviderId: ' + authProviderId);
                //return; // commented out for debugging
            }

            AccessTokenInfo info = new AccessTokenInfo();
            info.AuthProviderId = authProviderId;
            info.AccessToken = token;

            RestContext.Response.addHeader('Content-Type', 'application/json');
            RestContext.Response.statusCode = 200;
            RestContext.Response.responseBody = Blob.valueOf(JSON.serializePretty(info));
        } catch (Exception error) {
            System.debug(LoggingLevel.ERROR, error);
            throw error;
        }
    }

    public class AccessTokenInfo {
        public String Name {
            get {
                return UserInfo.getName();
            }
        }
        public String Username {
            get {
                return UserInfo.getUsername();
            }
        }
        public String AccessToken { get; set; }
        public String AuthProviderId { get; set; }
    }

    private static String authProviderId {
        get {
            List<AuthProvider> providers = [SELECT Id FROM AuthProvider WHERE DeveloperName = :authProviderDeveloperName];

            if (providers.size() == 0) {
                throw new CustomException('Unable to find an Auth. Provider with DeveloperName: ' + authProviderDeveloperName);
            }

            System.debug(providers);

            return providers[0].Id;
        }
    }

    private static String authProviderDeveloperName {
        get {
            return 'MockLab';
        }
    }

    private static String providerName {
        get {
            return 'Open ID Connect';
        }
    }
}

Il controller REST è accessibile tramite a Sitee sto passando un bearer token quando chiamo l'endpoint.

La Auth. Providerconfigurazione è:

  • Tipo di fornitore: Open ID Connect
  • Nome: MockLab
  • Suffisso URL: MockLab
  • Chiave consumatore: mocklab_oauth2
  • Segreto del consumatore: whatever
  • Autorizza URL endpoint: http://weyz3.mocklab.io/oauth/authorize
  • URL endpoint token: http://weyz3.mocklab.io/oauth/token
  • URL endpoint informazioni utente: vuoto
  • Emittente del token: vuoto
  • Ambiti predefiniti: vuoto
  • Invia token di accesso nell'intestazione: true
  • Invia le credenziali del cliente nell'intestazione: false
  • Includi il segreto del consumatore nelle risposte dell'API: true
  • URL di errore personalizzato: vuoto
  • URL di disconnessione personalizzato: vuoto
  • Gestore della registrazione: vuoto
  • Esegui registrazione come: vuoto
  • Portale: vuoto
  • URL icona: vuoto

La NamedCredentialconfigurazione è:

  • Etichetta: MockLab
  • Nome: MockLab
  • URL: https://weyz3.mocklab.io/
  • Certificato: vuoto
  • Tipo d'identità: Named Principal
  • Protocollo di autenticazione: OAuth 2.0
  • Provider di autenticazione: MockLab
  • Scopo: openid, profile, email
  • Stato di autenticazione: Authenticated
  • Genera intestazione autorizzazione: true
  • Consenti campi unione nell'intestazione HTTP: false
  • Consenti campi unione nel corpo HTTP: false
  • Connessione di rete in uscita: falso

Ho completato il OAuthflusso, in modo che il NamedCredentialha un Authentication Statusdi Authenticated.

Ho anche testato i NamedCredentiallavori collegandomi all'API esterna e recuperando alcuni dati utilizzando Apex.

Ma quando chiamo il mio endpoint REST personalizzato per ottenere il token di accesso, ottengo sempre un nullvalore.

Risposta di esempio:

{
  "Username" : "[email protected]",
  "Name" : "Admin User",
  "AuthProviderId" : "0SO4K000000GozdWAC",
  "AccessToken" : null
}

In base alla risposta, posso vedere che la richiesta è stata autenticata correttamente utilizzando il token di trasporto.

Ma la chiamata a Auth.AuthToken.getAccessToken(authProviderId, providerName);sta ancora tornandonull

Se provo a eseguire questo codice nella console per sviluppatori:

String token = Auth.AuthToken.getAccessToken('0SO4K000000GozdWAC', 'Open ID Connect');
System.debug(token);

Ottengo un nullvalore.

Ho provato a chiamare il metodo tramite un componente LWC:

@AuraEnabled(cacheable=true)
public static String getAccessToken() {
    return Auth.AuthToken.getAccessToken('0SO4K000000GozdWAC', 'Open ID Connect');
}

Ottengo un nullvalore.

Tutto viene eseguito utilizzando lo stesso utente amministratore.

AGGIORNAMENTO: Ho modificato i dettagli Auth. Providere Named Credenitalai valori effettivi per un MockLabambiente che ho configurato, in modo da poter testare utilizzando esattamente le stesse informazioni / configurazione che sto utilizzando.

Domande

  1. Che cosa sto facendo di sbagliato?
  2. Come posso risolverlo, in modo che il controller restituisca il token?

Risposte

3 Adam Oct 10 2020 at 09:53

Modificato

Ho eseguito alcuni test con il tuo codice e la configurazione in un'organizzazione per sviluppatori,


Test 1: accedi come l'utente che ha creato l'Auth. Fornitore in Workbench

Risultato: posso ottenere il token nel banco di lavoro.


Test 2: concedi l'accesso di classe apex a un sito e visita il sito

Risultato: ho ottenuto un nullcome utente del sito.


Test 3: accedere come un altro amministratore di sistema in Workbench

Risultato: ho ottenuto un file null


Immagino che solo l'utente creato Auth. Providerpossa ottenere il token usandoAuth.AuthToken.getAccessToken(authProviderId, providerName);

Puoi confermare che il nome utente nella tua risposta di esempio è uguale al nome utente dell'amministratore Salesforce che ha creato il provider di autenticazione?


Ho creato un'app connessa e ho ricevuto un token dell'utente corrente

quindi ho utilizzato il token utente per chiamare l'API rest e sono riuscito a ottenere AccessToken in Postman.

Sebbene sia possibile ottenere correttamente il token, questo introduce un nuovo token.