Accorder ou révoquer des autorisations d’API par programmation
Article
Lorsque vous accordez des autorisations d’API à une application cliente dans Microsoft Entra ID, les autorisations sont enregistrées en tant qu’objets accessibles, mis à jour ou supprimés, comme vos données. L’utilisation de Microsoft Graph pour créer directement des octrois d’autorisations est une alternative programmatique au consentement interactif et peut être utile pour les scénarios d’automatisation, la gestion en bloc ou d’autres opérations personnalisées dans votre organization.
Dans ce guide, vous allez apprendre à accorder et révoquer des rôles d’application pour une application à l’aide de Microsoft Graph. Les rôles d’application, également appelés autorisations d’application, ou autorisations d’accès direct, permettent à une application d’appeler une API avec sa propre identité.
Attention
Soyez prudent ! Les autorisations accordées par programme ne sont pas sujettes à révision ou confirmation. Ils prennent effet immédiatement.
Configuration requise
Pour suivre ces instructions, vous avez besoin des ressources et privilèges suivants :
Locataire Microsoft Entra opérationnel.
Vous allez exécuter les requêtes de cet article en tant qu’utilisateur. Vous devez effectuer les étapes suivantes :
Connectez-vous à un client API tel que Graph Explorer en tant qu’utilisateur disposant de privilèges pour créer des applications dans le locataire.
Dans l’application à laquelle vous êtes connecté, consentez aux autorisations déléguées Application.Read.All et AppRoleAssignment.ReadWrite.All au nom de l’utilisateur connecté. Vous n’avez pas besoin de donner votre consentement au nom de votre organization.
Obtenez l’ID d’objet du principal de service client auquel vous accorderez des rôles d’application. Dans cet article, le principal du service client est identifié par l’ID b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94. Dans la centre d'administration Microsoft Entra, accédez à Identity>Applications>Applications d’entreprise>Applications d’application pour rechercher le principal du service client. Sélectionnez-la et dans la page Vue d’ensemble , copiez la valeur ID d’objet.
Attention
Les applications qui ont reçu l’autorisation AppRoleAssignment.ReadWrite.All ne doivent être accessibles qu’aux utilisateurs appropriés.
Étape 1 : Obtenir les appRoles du principal du service de ressources
Avant de pouvoir accorder des rôles d’application, vous devez d’abord identifier les rôles d’application à accorder et le principal de service de ressources qui expose les rôles d’application. Les rôles d’application sont définis dans l’objet appRoles d’un principal de service. Dans cet article, vous allez utiliser le principal de service Microsoft Graph dans le locataire comme principal du service de ressources.
Demande
La requête suivante récupère les rôles d’application définis par le principal de service Microsoft Graph dans le locataire.
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=displayName eq 'Microsoft Graph'&$select=id,displayName,appId,appRoles
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "displayName eq 'Microsoft Graph'";
requestConfiguration.QueryParameters.Select = new string []{ "id","displayName","appId","appRoles" };
});
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc service-principals list --filter "displayName eq 'Microsoft Graph'" --select "id,displayName,appId,appRoles"
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
ServicePrincipalCollectionResponse result = graphClient.servicePrincipals().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "displayName eq 'Microsoft Graph'";
requestConfiguration.queryParameters.select = new String []{"id", "displayName", "appId", "appRoles"};
});
Remarque : l’objet de réponse affiché ci-après peut être raccourci pour plus de lisibilité.
HTTP/1.1 201 Created
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals(id,displayName,appId,appRoles)",
"value": [
{
"id": "7ea9e944-71ce-443d-811c-71e8047b557a",
"displayName": "Microsoft Graph",
"appId": "00000003-0000-0000-c000-000000000000",
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Allows the app to read user profiles without a signed in user.",
"displayName": "Read all users' full profiles",
"id": "df021288-bdef-4463-88db-98f22de89214",
"isEnabled": true,
"origin": "Application",
"value": "User.Read.All"
}
]
}
]
}
Étape 2 : Accorder un rôle d’application à un principal de service client
Dans cette étape, vous allez accorder à votre application un rôle d’application exposé par Microsoft Graph, créant ainsi une attribution de rôle d’application. À l’étape 1, l’ID d’objet de Microsoft Graph est 7ea9e944-71ce-443d-811c-71e8047b557a et le rôle User.Read.All d’application est identifié par l’ID df021288-bdef-4463-88db-98f22de89214.
Demande
La requête suivante accorde à votre application cliente (le principal de l’ID b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94) un rôle d’application d’ID df021288-bdef-4463-88db-98f22de89214 exposé par un principal de service de ressources de l’ID 7ea9e944-71ce-443d-811c-71e8047b557a.
Remarque
Si vous utilisez le Kit de développement logiciel (SDK) Python, importez les bibliothèques suivantes :
from msgraph.generated.models.app_role_assignment import AppRoleAssignment
from msgraph.generated.models.service_principal import ServicePrincipal
// Code snippets are only available for the latest version. Current version is 5.x
// Dependencies
using Microsoft.Graph.Models;
var requestBody = new AppRoleAssignment
{
PrincipalId = Guid.Parse("b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94"),
ResourceId = Guid.Parse("7ea9e944-71ce-443d-811c-71e8047b557a"),
AppRoleId = Guid.Parse("df021288-bdef-4463-88db-98f22de89214"),
};
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals["{servicePrincipal-id}"].AppRoleAssignedTo.PostAsync(requestBody);
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc service-principals app-role-assigned-to create --service-principal-id {servicePrincipal-id} --body '{\
"principalId": "b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94",\
"resourceId": "7ea9e944-71ce-443d-811c-71e8047b557a",\
"appRoleId": "df021288-bdef-4463-88db-98f22de89214"\
}\
'
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
AppRoleAssignment appRoleAssignment = new AppRoleAssignment();
appRoleAssignment.setPrincipalId(UUID.fromString("b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94"));
appRoleAssignment.setResourceId(UUID.fromString("7ea9e944-71ce-443d-811c-71e8047b557a"));
appRoleAssignment.setAppRoleId(UUID.fromString("df021288-bdef-4463-88db-98f22de89214"));
AppRoleAssignment result = graphClient.servicePrincipals().byServicePrincipalId("{servicePrincipal-id}").appRoleAssignedTo().post(appRoleAssignment);
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\Models\AppRoleAssignment;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new AppRoleAssignment();
$requestBody->setPrincipalId('b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94');
$requestBody->setResourceId('7ea9e944-71ce-443d-811c-71e8047b557a');
$requestBody->setAppRoleId('df021288-bdef-4463-88db-98f22de89214');
$result = $graphServiceClient->servicePrincipals()->byServicePrincipalId('servicePrincipal-id')->appRoleAssignedTo()->post($requestBody)->wait();
GET https://graph.microsoft.com/v1.0/servicePrincipals/7ea9e944-71ce-443d-811c-71e8047b557a/appRoleAssignedTo
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals["{servicePrincipal-id}"].AppRoleAssignedTo.GetAsync();
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
AppRoleAssignmentCollectionResponse result = graphClient.servicePrincipals().byServicePrincipalId("{servicePrincipal-id}").appRoleAssignedTo().get();
L’objet response inclut une collection d’attributions de rôles d’application à votre principal de service de ressources et inclut l’attribution de rôle d’application que vous avez créée à l’aide de la requête POST.
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
await graphClient.ServicePrincipals["{servicePrincipal-id}"].AppRoleAssignedTo["{appRoleAssignment-id}"].DeleteAsync();
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc service-principals app-role-assigned-to delete --service-principal-id {servicePrincipal-id} --app-role-assignment-id {appRoleAssignment-id}
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
graphClient.servicePrincipals().byServicePrincipalId("{servicePrincipal-id}").appRoleAssignedTo().byAppRoleAssignmentId("{appRoleAssignment-id}").delete();
<?php
use Microsoft\Graph\GraphServiceClient;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$graphServiceClient->servicePrincipals()->byServicePrincipalId('servicePrincipal-id')->appRoleAssignedTo()->byAppRoleAssignmentId('appRoleAssignment-id')->delete()->wait();
Vous avez appris à gérer les octrois de rôles d’application pour un principal de service. Cette méthode d’octroi d’autorisations à l’aide de Microsoft Graph est un consentement interactif alternatif et doit être utilisée avec prudence.
Dans ce guide, vous allez apprendre à accorder et révoquer des autorisations déléguées pour une application à l’aide de Microsoft Graph. Les autorisations déléguées, également appelées étendues ou autorisations OAuth2, permettent à une application d’appeler une API pour le compte d’un utilisateur connecté.
Attention
Soyez prudent ! Les autorisations accordées par programme ne sont pas sujettes à révision ou confirmation. Ils prennent effet immédiatement.
Configuration requise
Pour suivre ces instructions, vous avez besoin des ressources et privilèges suivants :
Locataire Microsoft Entra opérationnel.
Vous allez exécuter les requêtes de cet article en tant qu’utilisateur. Vous devez effectuer les étapes suivantes :
Connectez-vous à un client API tel que Graph Explorer en tant qu’utilisateur disposant de privilèges pour créer des applications dans le locataire.
Dans l’application à laquelle vous êtes connecté, consentez aux autorisations déléguées Application.Read.All, DelegatedPermissionGrant.ReadWrite.All au nom de l’utilisateur connecté. Vous n’avez pas besoin de donner votre consentement au nom de votre organization.
Obtenez l’ID d’objet du principal de service client auquel vous accorderez des autorisations déléguées pour le compte d’un utilisateur. Dans cet article, le principal du service client est identifié par l’ID b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94.
Attention
Les applications qui ont reçu l’autorisation DelegatedPermissionGrant.ReadWrite.All ne doivent être accessibles que par les utilisateurs appropriés.
Étape 1 : Obtenir les autorisations déléguées du principal du service de ressources
Avant de pouvoir accorder des autorisations déléguées, vous devez d’abord identifier les autorisations déléguées à accorder et le principal du service de ressources qui expose les autorisations déléguées. Les autorisations déléguées sont définies dans l’objet oauth2PermissionScopes d’un principal de service. Dans cet article, vous allez utiliser le principal de service Microsoft Graph dans le locataire comme principal du service de ressources.
Demande
La requête suivante récupère les autorisations déléguées définies par le principal de service Microsoft Graph dans le locataire.
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=displayName eq 'Microsoft Graph'&$select=id,displayName,appId,oauth2PermissionScopes
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "displayName eq 'Microsoft Graph'";
requestConfiguration.QueryParameters.Select = new string []{ "id","displayName","appId","oauth2PermissionScopes" };
});
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc service-principals list --filter "displayName eq 'Microsoft Graph'" --select "id,displayName,appId,oauth2PermissionScopes"
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
ServicePrincipalCollectionResponse result = graphClient.servicePrincipals().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "displayName eq 'Microsoft Graph'";
requestConfiguration.queryParameters.select = new String []{"id", "displayName", "appId", "oauth2PermissionScopes"};
});
Remarque : l’objet de réponse affiché ci-après peut être raccourci pour plus de lisibilité.
HTTP/1.1 201 Created
Content-type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals(id,displayName,appId,oauth2PermissionScopes)",
"value": [
{
"id": "7ea9e944-71ce-443d-811c-71e8047b557a",
"displayName": "Microsoft Graph",
"appId": "00000003-0000-0000-c000-000000000000",
"oauth2PermissionScopes": [
{
"adminConsentDescription": "Allows the app to read the full set of profile properties, reports, and managers of other users in your organization, on behalf of the signed-in user.",
"adminConsentDisplayName": "Read all users' full profiles",
"id": "a154be20-db9c-4678-8ab7-66f6cc099a59",
"isEnabled": true,
"type": "Admin",
"userConsentDescription": "Allows the app to read the full set of profile properties, reports, and managers of other users in your organization, on your behalf.",
"userConsentDisplayName": "Read all users' full profiles",
"value": "User.Read.All"
},
{
"adminConsentDescription": "Allows the app to list groups, and to read their properties and all group memberships on behalf of the signed-in user. Also allows the app to read calendar, conversations, files, and other group content for all groups the signed-in user can access. ",
"adminConsentDisplayName": "Read all groups",
"id": "5f8c59db-677d-491f-a6b8-5f174b11ec1d",
"isEnabled": true,
"type": "Admin",
"userConsentDescription": "Allows the app to list groups, and to read their properties and all group memberships on your behalf. Also allows the app to read calendar, conversations, files, and other group content for all groups you can access. ",
"userConsentDisplayName": "Read all groups",
"value": "Group.Read.All"
}
]
}
]
}
Étape 2 : Accorder une autorisation déléguée au principal de service client pour le compte d’un utilisateur
Demande
Dans cette étape, vous allez accorder à votre application, au nom d’un utilisateur, une autorisation déléguée exposée par Microsoft Graph, créant ainsi une autorisation déléguée.
À l’étape 1, l’ID d’objet de Microsoft Graph dans le locataire est 7ea9e944-71ce-443d-811c-71e8047b557a
Les autorisations User.Read.All déléguées et Group.Read.All sont identifiées par les ID a154be20-db9c-4678-8ab7-66f6cc099a59 globaux uniques et 5f8c59db-677d-491f-a6b8-5f174b11ec1d respectivement.
Le principal est un utilisateur identifié par l’ID 3fbd929d-8c56-4462-851e-0eb9a7b3a2a5.
Le principal du service client est identifié par l’ID b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94. Il s’agit de l’ID d’objet du principal de service et non de son appId.
// Code snippets are only available for the latest version. Current version is 5.x
// Dependencies
using Microsoft.Graph.Models;
var requestBody = new OAuth2PermissionGrant
{
ClientId = "b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94",
ConsentType = "Principal",
ResourceId = "7ea9e944-71ce-443d-811c-71e8047b557a",
PrincipalId = "3fbd929d-8c56-4462-851e-0eb9a7b3a2a5",
Scope = "User.Read.All Group.Read.All",
};
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Oauth2PermissionGrants.PostAsync(requestBody);
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
OAuth2PermissionGrant oAuth2PermissionGrant = new OAuth2PermissionGrant();
oAuth2PermissionGrant.setClientId("b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94");
oAuth2PermissionGrant.setConsentType("Principal");
oAuth2PermissionGrant.setResourceId("7ea9e944-71ce-443d-811c-71e8047b557a");
oAuth2PermissionGrant.setPrincipalId("3fbd929d-8c56-4462-851e-0eb9a7b3a2a5");
oAuth2PermissionGrant.setScope("User.Read.All Group.Read.All");
OAuth2PermissionGrant result = graphClient.oauth2PermissionGrants().post(oAuth2PermissionGrant);
Bien que la demande précédente accorde le consentement au nom d’un seul utilisateur, vous pouvez choisir d’accorder le consentement au nom de tous les utilisateurs du locataire. Le corps de la demande est similaire au corps de la demande précédent, sauf avec les modifications suivantes :
ConsentType est AllPrincipals, ce qui indique que vous consentez au nom de tous les utilisateurs du locataire.
La propriété principalId n’est pas fournie ou peut être null.
Voici un exemple de corps de demande pour accorder le consentement au nom de tous les utilisateurs :
Si vous avez accordé le consentement pour tous les utilisateurs du locataire, le consentType dans l’objet response est AllPrincipals, et principalId est null.
Confirmer l’octroi d’autorisation
Pour confirmer les autorisations déléguées attribuées au principal de service au nom de l’utilisateur, exécutez la requête suivante.
GET https://graph.microsoft.com/v1.0/oauth2PermissionGrants?$filter=clientId eq 'b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94' and principalId eq '3fbd929d-8c56-4462-851e-0eb9a7b3a2a5' and consentType eq 'Principal'
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Oauth2PermissionGrants.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "clientId eq 'b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94' and principalId eq '3fbd929d-8c56-4462-851e-0eb9a7b3a2a5' and consentType eq 'Principal'";
});
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc oauth2-permission-grants list --filter "clientId eq 'b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94' and principalId eq '3fbd929d-8c56-4462-851e-0eb9a7b3a2a5' and consentType eq 'Principal'"
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
OAuth2PermissionGrantCollectionResponse result = graphClient.oauth2PermissionGrants().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "clientId eq 'b0d9b9e3-0ecf-4bfd-8dab-9273dd055a94' and principalId eq '3fbd929d-8c56-4462-851e-0eb9a7b3a2a5' and consentType eq 'Principal'";
});
Étape 3 : Révoquer les autorisations déléguées accordées à un principal de service pour le compte d’un utilisateur [Facultatif]
Si un principal de service a reçu plusieurs octrois d’autorisations déléguées pour le compte d’un utilisateur, vous pouvez choisir de révoquer des octrois spécifiques ou tous les octrois. Utilisez cette méthode pour supprimer et révoquer le consentement pour les autorisations déléguées que vous avez attribuées à Graph Explorer.
Pour révoquer un ou plusieurs octrois, exécutez une demande PATCH sur l’objet oauth2PermissionGrant et spécifiez uniquement les autorisations déléguées à conserver dans le paramètre scope .
Pour révoquer tous les octrois, exécutez une requête DELETE sur l’objet oauth2PermissionGrant.
Demande
La requête suivante révoque tous les octrois d’autorisations et conserve uniquement l’octroi d’autorisation User.Read.All . Les autorisations sont supprimées et le consentement précédemment accordé est révoqué.
// Code snippets are only available for the latest version. Current version is 5.x
// Dependencies
using Microsoft.Graph.Models;
var requestBody = new OAuth2PermissionGrant
{
Scope = "User.Read.All",
};
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Oauth2PermissionGrants["{oAuth2PermissionGrant-id}"].PatchAsync(requestBody);
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc oauth2-permission-grants patch --o-auth2-permission-grant-id {oAuth2PermissionGrant-id} --body '{\
"scope": "User.Read.All"\
}\
'
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
OAuth2PermissionGrant oAuth2PermissionGrant = new OAuth2PermissionGrant();
oAuth2PermissionGrant.setScope("User.Read.All");
OAuth2PermissionGrant result = graphClient.oauth2PermissionGrants().byOAuth2PermissionGrantId("{oAuth2PermissionGrant-id}").patch(oAuth2PermissionGrant);
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\Models\OAuth2PermissionGrant;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new OAuth2PermissionGrant();
$requestBody->setScope('User.Read.All');
$result = $graphServiceClient->oauth2PermissionGrants()->byOAuth2PermissionGrantId('oAuth2PermissionGrant-id')->patch($requestBody)->wait();
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
await graphClient.Oauth2PermissionGrants["{oAuth2PermissionGrant-id}"].DeleteAsync();
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
graphClient.oauth2PermissionGrants().byOAuth2PermissionGrantId("{oAuth2PermissionGrant-id}").delete();
<?php
use Microsoft\Graph\GraphServiceClient;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$graphServiceClient->oauth2PermissionGrants()->byOAuth2PermissionGrantId('oAuth2PermissionGrant-id')->delete()->wait();
Vous avez accordé des autorisations déléguées (ou des étendues) à un principal de service. Cette méthode d’octroi d’autorisations à l’aide de Microsoft Graph est une alternative au consentement interactif et doit être utilisée avec prudence.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultez https://aka.ms/ContentUserFeedback.