Obtenir un jeton pour une application mobile qui appelle des API web

Pour pouvoir appeler des API web protégées, votre application doit disposer d'un jeton d'accès. Cet article décrit la procédure à suivre pour obtenir un jeton à l’aide de la bibliothèque d’authentification Microsoft (MSAL).

Définir une étendue

Lorsque vous demandez un jeton, définissez une étendue. L’étendue détermine les données auxquelles votre application peut accéder.

Pour définir une étendue, l'approche la plus simple consiste à combiner l'App ID URI de l'API web souhaitée avec l'étendue .default. Cette définition indique à la plateforme d’identités Microsoft que votre application a besoin de toutes les étendues définies sur le portail.

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"};

Obtenir des jetons

Acquérir des jetons via MSAL

MSAL permet aux applications d’acquérir des jetons en mode silencieux et de manière interactive. Lorsque vous appelez AcquireTokenSilent() ou AcquireTokenInteractive(), MSAL renvoie un jeton d'accès pour les étendues demandées. La procédure appropriée consiste à effectuer une demande en mode silencieux, puis à revenir à une demande interactive.

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

Essayez d'abord d'acquérir un jeton de manière silencieuse :


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
}

Si MSAL renvoie MSALErrorInteractionRequired, essayez d'acquérir des jetons de manière interactive :

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 pour iOS et macOS prend en charge différents modificateurs pour obtenir un jeton de manière interactive ou silencieuse :

Xamarin

L'exemple suivant présente le code minimal à utiliser pour obtenir un jeton de manière interactive. L'exemple utilise Microsoft Graph pour lire le profil de l'utilisateur.

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();
}

Paramètres obligatoires dans MSAL.NET

AcquireTokenInteractive n'a qu'un seul paramètre obligatoire : scopes. Le paramètre scopes énumère les chaînes qui définissent les étendues pour lesquelles un jeton est requis. Si le jeton est destiné à Microsoft Graph, vous trouvez les étendues nécessaires dans les informations de référence de chaque API Microsoft Graph. Dans les informations de référence, accédez à la section « Autorisations ».

Par exemple, pour répertorier les contacts de l'utilisateur, utilisez les étendues « User.Read », « Contacts.Read ». Pour plus d’informations, consultez la documentation de référence sur les autorisations Microsoft Graph.

Sur Android, vous pouvez spécifier l'activité parente lors de la création de l'application à l'aide de PublicClientApplicationBuilder. Si vous ne spécifiez pas l'activité parente à ce moment-là, vous pouvez la spécifier ultérieurement à l'aide de .WithParentActivityOrWindow, comme dans la section suivante. Si vous spécifiez l'activité parente, le jeton y revient après l'interaction. Si vous ne la spécifiez pas, l'appel .ExecuteAsync() renvoie une exception.

Paramètres facultatifs particuliers dans MSAL.NET

Les sections suivantes décrivent les paramètres facultatifs de MSAL.NET.

WithPrompt

Le paramètre WithPrompt() contrôle l'interactivité avec l'utilisateur en spécifiant une invite.

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 définit les constantes suivantes :

  • SelectAccount force le service d'émission de jeton de sécurité (STS) à présenter la boîte de dialogue de sélection de compte. La boîte de dialogue contient les comptes pour lesquels l'utilisateur dispose d'une session. Vous pouvez utiliser cette option pour permettre à l'utilisateur de choisir parmi différentes identités. Cette option oblige MSAL à envoyer prompt=select_account au fournisseur d’identité.

    La constante SelectAccount est le paramètre par défaut. Elle fournit la meilleure expérience possible sur la base des informations disponibles. Les informations disponibles peuvent inclure le compte, la présence d'une session pour l'utilisateur, etc. Ne remplacez pas ce paramètre par défaut, sauf si vous avez une bonne raison de le faire.

  • Consent vous permet de demander à l'utilisateur de donner son consentement, même si celui-ci a déjà été accordé. Dans ce cas, MSAL envoie prompt=consent au fournisseur d’identité.

    Vous souhaiterez peut-être utiliser la constante Consent dans les applications axées sur la sécurité pour lesquelles la gouvernance de l'organisation exige que les utilisateurs voient la boîte de dialogue de consentement chaque fois qu'ils utilisent l'application.

  • ForceLogin permet au service d'inviter l'utilisateur à entrer ses informations d'identification même si l'invite n'est pas nécessaire.

    Cette option peut être utile si l'acquisition du jeton échoue et que vous souhaitez permettre à l'utilisateur de se reconnecter. Dans ce cas, MSAL envoie prompt=login au fournisseur d’identité. Vous souhaiterez peut-être utiliser cette option dans les applications axées sur la sécurité pour lesquelles la gouvernance de l'organisation exige que l'utilisateur se connecte chaque fois qu'il accède à des parties spécifiques de l'application.

  • Never concerne uniquement .NET 4.5 et Windows Runtime (WinRT). Cette constante n'affichera aucune invite utilisateur, mais elle tentera d'utiliser le cookie stocké dans l'affichage web incorporé masqué. Pour plus d'informations, consultez Utilisation de navigateurs avec MSAL.NET.

    Si cette option échoue, AcquireTokenInteractive renvoie une exception pour vous informer qu'une interaction avec l'interface utilisateur est nécessaire. Utilisez ensuite un autre paramètre Prompt.

  • NoPrompt n'envoie pas d'invite au fournisseur d'identité.

    Cette option n'est utile que pour les stratégies de modification de profil d'Azure Active Directory B2C. Pour plus d'informations, consultez Spécificités de B2C.

WithExtraScopeToConsent

Utilisez le modificateur WithExtraScopeToConsent dans un scénario avancé où vous souhaitez que l'utilisateur fournisse son consentement préalable à plusieurs ressources. Vous pouvez utiliser ce modificateur lorsque vous ne souhaitez pas avoir recours au consentement incrémentiel, qui est normalement utilisé avec MSAL.NET ou la plateforme d’identités Microsoft. Pour plus d’informations, consultez Guide pratique pour obtenir le consentement préalable de l’utilisateur sur plusieurs ressources.

Exemple de code :

var result = await app.AcquireTokenInteractive(scopesForCustomerApi)
                     .WithExtraScopeToConsent(scopesForVendorApi)
                     .ExecuteAsync();
Autres paramètres facultatifs

Pour en savoir plus sur les autres paramètres facultatifs de AcquireTokenInteractive, consultez la documentation de référence relative à AcquireTokenInteractiveParameterBuilder.

Acquérir des jetons via le protocole

Nous vous déconseillons d'utiliser directement le protocole pour obtenir des jetons. Si vous le faites, l'application ne prendra pas en charge certains scénarios impliquant l'authentification unique (SSO), la gestion des périphériques et l'accès conditionnel.

Lorsque vous utilisez le protocole pour obtenir des jetons destinés aux applications mobiles, effectuez deux demandes :

  • Obtention d'un code d'autorisation
  • Échange du code contre un jeton

Obtention d’un code d’autorisation

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

Obtention de l'accès et actualisation du jeton

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

Étapes suivantes

Passez à l’article suivant de ce scénario, Appeler une API web.