Share via


Ottenere un token per un'app per dispositivi mobili che chiama le API Web

Prima che l'app possa chiamare API Web protette, è necessario un token di accesso. Questo articolo illustra il processo per ottenere un token usando Microsoft Authentication Library (MSAL).

Definire un ambito

Quando si richiede un token, definire un ambito. L'ambito determina quali dati risultano accessibili per l'app.

Il modo più semplice per definire un ambito consiste nel combinare l'API App ID URI Web desiderata con l'ambito .default. Questa definizione indica a Microsoft Identity Platform che l'app richiede tutti gli ambiti impostati nel portale.

Android

String[] SCOPES = {"https://graph.microsoft.com/.default"};

iOS

let scopes = ["https://graph.microsoft.com/.default"]

Xamarin

var scopes = new [] {"https://graph.microsoft.com/.default"};

Ottenere i token

Acquisire i token tramite MSAL

MSAL consente alle app di acquisire i token in modo invisibile all'utente e in modo interattivo. Quando si chiama AcquireTokenSilent() o AcquireTokenInteractive(), MSAL restituisce un token di accesso per gli ambiti richiesti. Il modello corretto consiste nell'effettuare una richiesta invisibile all'utente e quindi eseguire il fallback a una richiesta interattiva.

Android

String[] SCOPES = {"https://graph.microsoft.com/.default"};
PublicClientApplication sampleApp = new PublicClientApplication(
                    this.getApplicationContext(),
                    R.raw.auth_config);

// Check if there are any accounts we can sign in silently.
// Result is in the silent callback (success or error).
sampleApp.getAccounts(new PublicClientApplication.AccountsLoadedCallback() {
    @Override
    public void onAccountsLoaded(final List<IAccount> accounts) {

        if (accounts.isEmpty() && accounts.size() == 1) {
            // TODO: Create a silent callback to catch successful or failed request.
            sampleApp.acquireTokenSilentAsync(SCOPES, accounts.get(0), getAuthSilentCallback());
        } else {
            /* No accounts or > 1 account. */
        }
    }
});

[...]

// No accounts found. Interactively request a token.
// TODO: Create an interactive callback to catch successful or failed requests.
sampleApp.acquireToken(getActivity(), SCOPES, getAuthInteractiveCallback());

iOS

Provare prima di tutto ad acquisire un token in modo invisibile all'utente:


NSArray *scopes = @[@"https://graph.microsoft.com/.default"];
NSString *accountIdentifier = @"my.account.id";

MSALAccount *account = [application accountForIdentifier:accountIdentifier error:nil];

MSALSilentTokenParameters *silentParams = [[MSALSilentTokenParameters alloc] initWithScopes:scopes account:account];
[application acquireTokenSilentWithParameters:silentParams completionBlock:^(MSALResult *result, NSError *error) {

    if (!error)
    {
        // You'll want to get the account identifier to retrieve and reuse the account
        // for later acquireToken calls
        NSString *accountIdentifier = result.account.identifier;

        // Access token to call the web API
        NSString *accessToken = result.accessToken;
    }

    // Check the error
    if (error && [error.domain isEqual:MSALErrorDomain] && error.code == MSALErrorInteractionRequired)
    {
        // Interactive auth will be required, call acquireTokenWithParameters:error:
        return;
    }
}];

let scopes = ["https://graph.microsoft.com/.default"]
let accountIdentifier = "my.account.id"

guard let account = try? application.account(forIdentifier: accountIdentifier) else { return }
let silentParameters = MSALSilentTokenParameters(scopes: scopes, account: account)
application.acquireTokenSilent(with: silentParameters) { (result, error) in

    guard let authResult = result, error == nil else {

    let nsError = error! as NSError

    if (nsError.domain == MSALErrorDomain &&
        nsError.code == MSALError.interactionRequired.rawValue) {

            // Interactive auth will be required, call acquireToken()
            return
         }
         return
     }

    // You'll want to get the account identifier to retrieve and reuse the account
    // for later acquireToken calls
    let accountIdentifier = authResult.account.identifier

    // Access token to call the web API
    let accessToken = authResult.accessToken
}

Se MSAL restituisce MSALErrorInteractionRequired, provare ad acquisire i token in modo interattivo:

UIViewController *viewController = ...; // Pass a reference to the view controller that should be used when getting a token interactively
MSALWebviewParameters *webParameters = [[MSALWebviewParameters alloc] initWithAuthPresentationViewController:viewController];
MSALInteractiveTokenParameters *interactiveParams = [[MSALInteractiveTokenParameters alloc] initWithScopes:scopes webviewParameters:webParameters];
[application acquireTokenWithParameters:interactiveParams completionBlock:^(MSALResult *result, NSError *error) {
    if (!error)
    {
        // You'll want to get the account identifier to retrieve and reuse the account
        // for later acquireToken calls
        NSString *accountIdentifier = result.account.identifier;

        NSString *accessToken = result.accessToken;
    }
}];
let viewController = ... // Pass a reference to the view controller that should be used when getting a token interactively
let webviewParameters = MSALWebviewParameters(authPresentationViewController: viewController)
let interactiveParameters = MSALInteractiveTokenParameters(scopes: scopes, webviewParameters: webviewParameters)
application.acquireToken(with: interactiveParameters, completionBlock: { (result, error) in

    guard let authResult = result, error == nil else {
        print(error!.localizedDescription)
        return
    }

    // Get access token from result
    let accessToken = authResult.accessToken
})

MSAL per iOS e macOS supporta vari modificatori per ottenere un token in modo interattivo o invisibile all'utente:

Xamarin

L'esempio seguente mostra il codice minimo per ottenere un token in modo interattivo. L'esempio usa Microsoft Graph per leggere il profilo dell'utente.

string[] scopes = new string[] {"user.read"};
var app = PublicClientApplicationBuilder.Create(clientId).Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
{
 result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
             .ExecuteAsync();
}
catch(MsalUiRequiredException)
{
 result = await app.AcquireTokenInteractive(scopes)
             .ExecuteAsync();
}

Parametri obbligatori in MSAL.NET

AcquireTokenInteractive ha un solo parametro obbligatorio: scopes. Il scopes parametro enumera le stringhe che definiscono gli ambiti per i quali è necessario un token. Se il token è per Microsoft Graph, è possibile trovare gli ambiti necessari nel riferimento API di ogni API Microsoft Graph. Nel riferimento passare alla sezione "Autorizzazioni".

Ad esempio, per elencare i contatti dell'utente, usare l'ambito "User.Read", "Contacts.Read". Per altre informazioni, vedere le Informazioni di riferimento per le autorizzazioni dell'API Microsoft Graph.

In Android è possibile specificare l'attività padre quando si crea l'app usando PublicClientApplicationBuilder. Se non si specifica l'attività padre in quel momento, in un secondo momento è possibile specificarla usando .WithParentActivityOrWindow come nella sezione seguente. Se si specifica l'attività padre, il token torna all'attività padre dopo l'interazione. Se non viene specificato, la .ExecuteAsync() chiamata genera un'eccezione.

Parametri facoltativi specifici in MSAL.NET

Le sezioni seguenti illustrano i parametri facoltativi in MSAL.NET.

WithPrompt

Il WithPrompt() parametro controlla l'interattività con l'utente specificando un prompt.

Image showing the fields in the Prompt structure. These constant values control interactivity with the user by defining the type of prompt displayed by the WithPrompt() parameter.

La classe definisce le costanti seguenti:

  • SelectAccount forza il servizio token di sicurezza (STS) a presentare la finestra di dialogo di selezione dell'account. La finestra di dialogo contiene gli account per i quali l'utente dispone di una sessione. È possibile usare questa opzione quando si vuole consentire all'utente di scegliere tra identità diverse. Questa opzione consente a MSAL di inviare prompt=select_account al provider di identità.

    La SelectAccount costante è l'impostazione predefinita e offre in modo efficace la migliore esperienza possibile in base alle informazioni disponibili. Le informazioni disponibili possono includere account, presenza di una sessione per l'utente e così via. Non modificare questa impostazione predefinita, a meno che non si abbia un buon motivo per farlo.

  • Consent consente di richiedere all'utente il consenso anche se il consenso è stato concesso in precedenza. In questo caso, MSAL invia prompt=consent al provider di identità.

    È possibile usare la Consent costante nelle applicazioni incentrate sulla sicurezza in cui la governance dell'organizzazione richiede agli utenti di visualizzare la finestra di dialogo di consenso ogni volta che usano l'applicazione.

  • ForceLogin consente al servizio di richiedere all'utente le credenziali anche se la richiesta non è necessaria.

    Questa opzione può essere utile se l'acquisizione del token non riesce e si vuole consentire all'utente di accedere di nuovo. In questo caso, MSAL invia prompt=login al provider di identità. È possibile usare questa opzione nelle applicazioni incentrate sulla sicurezza in cui la governance dell'organizzazione richiede all'utente di accedere ogni volta che accedono a parti specifiche dell'applicazione.

  • Never è solo per .NET 4.5 e Windows Runtime (WinRT). Questa costante non richiederà all'utente, ma tenterà di usare il cookie archiviato nella visualizzazione Web incorporata nascosta. Per altre informazioni, vedere Uso di Web browser con MSAL.NET.

    Se questa opzione ha esito negativo, AcquireTokenInteractive genera un'eccezione per notificare che è necessaria un'interazione dell'interfaccia utente. Usare quindi un altro Prompt parametro.

  • NoPrompt non invia una richiesta al provider di identità.

    Questa opzione è utile solo per i criteri del profilo di modifica in Azure Active Directory B2C. Per altre informazioni, vedere Specifiche di B2C.

WithExtraScopeToConsent

Usare il WithExtraScopeToConsent modificatore in uno scenario avanzato in cui si vuole che l'utente fornisca il consenso iniziale a diverse risorse. È possibile usare questo modificatore quando non si vuole usare il consenso incrementale, che viene in genere usato con MSAL.NET o Microsoft Identity Platform. Per altre informazioni, vedere Ricevere il consenso utente in anticipo per numerose risorse.

Ecco un esempio di codice:

var result = await app.AcquireTokenInteractive(scopesForCustomerApi)
                     .WithExtraScopeToConsent(scopesForVendorApi)
                     .ExecuteAsync();
Altri parametri facoltativi

Per altre informazioni sugli altri parametri facoltativi per AcquireTokenInteractive, vedere la documentazione di riferimento per AcquireTokenInteractiveParameterBuilder.

Acquisire i token tramite il protocollo

Non è consigliabile usare direttamente il protocollo per ottenere i token. In questo caso, l'app non supporterà alcuni scenari che coinvolgono l'accesso Single Sign-On (SSO), la gestione dei dispositivi e l'accesso condizionale.

Quando si usa il protocollo per ottenere i token per le app per dispositivi mobili, effettuare due richieste:

  • Ottenere un codice di autorizzazione.
  • Scambiare il codice per un token.

Ottenere un codice di autorizzazione

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=<CLIENT_ID>
&response_type=code
&redirect_uri=<ENCODED_REDIRECT_URI>
&response_mode=query
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2F.default
&state=12345

Ottenere l'accesso e aggiornare il token

POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=<CLIENT_ID>
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=<ENCODED_REDIRECT_URI>
&grant_type=authorization_code

Passaggi successivi

Passare all'articolo successivo in questo scenario, Chiamata di un'API Web.