Вызов веб-API из мобильного приложения
После того как приложение авторизует пользователя и получит маркеры, библиотека проверки подлинности Microsoft (MSAL) предоставляет информацию о пользователе, среде пользователя и выданных маркерах. Эти значения можно использовать для вызова веб-API или отображения приветственного сообщения для пользователя.
В этой статье мы сначала рассмотрим результат, полученный MSAL. Затем мы рассмотрим, как использовать маркер доступа из AuthenticationResult
или result
для вызова защищенного веб-API.
Результат, полученный MSAL
MSAL предоставляет следующие значения:
AccessToken
вызывает защищенные веб-API в запросе носителя HTTP.IdToken
содержит полезную информацию об авторизованном пользователе. Эта информация включает имя пользователя, домашнего клиента и уникальный идентификатор хранилища.ExpiresOn
— это время истечения срока действия маркера. MSAL обрабатывает автоматическое обновление приложения.TenantId
— это идентификатор клиента, где выполнил вход пользователь. Для гостевых пользователей в Microsoft Entra B2B это значение определяет клиент, в котором пользователь вошел в систему. Это значение не идентифицирует домашний клиент пользователя.Scopes
обозначает области, предоставленные вместе с вашим маркером. Предоставленные области могут представлять собой подмножество запрошенных вами областей.
MSAL также предоставляет абстракцию значения Account
. Значение Account
представляет учетную запись, с которой выполнил вход текущий пользователь:
HomeAccountIdentifier
обозначает домашний клиент пользователя.UserName
— это предпочитаемое пользователем имя пользователя. Для пользователей B2C Azure AD это значение может быть пустым.AccountIdentifier
обозначает авторизованного пользователя. В большинстве случаев это значение совпадает со значениемHomeAccountIdentifier
(кроме случаев, когда пользователь является гостем в другом клиенте).
Вызов API
Получив маркер доступа, можно вызывать веб-API. Ваше приложение будет использовать этот токен для создания HTTP-запроса с последующим выполнением этого запроса.
Android
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject parameters = new JSONObject();
try {
parameters.put("key", "value");
} catch (Exception e) {
// Error when constructing.
}
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, MSGRAPH_URL,
parameters,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// Successfully called Graph. Process data and send to UI.
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Error.
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
// Put access token in HTTP request.
headers.put("Authorization", "Bearer " + authResult.getAccessToken());
return headers;
}
};
request.setRetryPolicy(new DefaultRetryPolicy(
3000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
MSAL для iOS и MacOS
Методы получения маркеров возвращают объект MSALResult
. MSALResult
предоставляет свойство accessToken
. Можно использовать accessToken
для вызова веб-API. Добавьте это свойство в заголовок авторизации HTTP, прежде чем отправлять запрос на доступ к защищенному веб-API.
NSMutableURLRequest *urlRequest = [NSMutableURLRequest new];
urlRequest.URL = [NSURL URLWithString:"https://contoso.api.com"];
urlRequest.HTTPMethod = @"GET";
urlRequest.allHTTPHeaderFields = @{ @"Authorization" : [NSString stringWithFormat:@"Bearer %@", accessToken] };
NSURLSessionDataTask *task =
[[NSURLSession sharedSession] dataTaskWithRequest:urlRequest
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {}];
[task resume];
let urlRequest = NSMutableURLRequest()
urlRequest.url = URL(string: "https://contoso.api.com")!
urlRequest.httpMethod = "GET"
urlRequest.allHTTPHeaderFields = [ "Authorization" : "Bearer \(accessToken)" ]
let task = URLSession.shared.dataTask(with: urlRequest as URLRequest) { (data: Data?, response: URLResponse?, error: Error?) in }
task.resume()
Xamarin
Свойства объекта AuthenticationResult в MSAL.NET
Для получения маркеров методы возвращают объект AuthenticationResult
. Для асинхронных методов возвращается Task<AuthenticationResult>
.
MSAL.NET AuthenticationResult
предоставляет следующие параметры:
AccessToken
— обеспечивает для веб-API доступ к ресурсам. Это строковый параметр, который обычно представляет собой маркер JWT в кодировке Base-64. Клиент никогда не должен считывать содержимое маркера доступа. Стабильность формата не гарантируется, и маркер может быть зашифрован для конкретного ресурса. Написание кода, который зависит от содержимого маркера доступа на стороне клиента, является одним из основных источников для ошибок и сбоев в логике клиента. Дополнительные сведения см. в разделе Маркеры доступа.IdToken
— предназначается для пользователей. Этот параметр является зашифрованным маркером JWT. Дополнительные сведения см. в разделе Маркеры идентификации.ExpiresOn
— сообщает дату и время истечения срока действия маркера.TenantId
— содержит сведения о клиенте, в котором был найден пользователь. Для гостевых пользователей в сценариях Microsoft Entra B2B идентификатор клиента является гостевым клиентом, а не уникальным клиентом. При предоставлении маркера для пользователя в объектеAuthenticationResult
также содержится информация об этом пользователе. Для потоков конфиденциальных клиентов, где маркеры запрашиваются без пользователя для приложения, эта информация о пользователе имеет значение NULL.Scopes
— обозначает области, для которых выдан маркер.- Уникальный идентификатор пользователя.
IAccount
В MSAL.NET понятие учетной записи определяется через интерфейс IAccount
. Такое радикальное изменение обеспечивает правильную семантику. Один и тот же пользователь может иметь несколько учетных записей в разных каталогах Microsoft Entra. Также MSAL.NET предоставляет более подробные сведения в сценариях с гостевым входом благодаря добавлению информации о домашней учетной записи.
Структура интерфейса IAccount
представлена на следующей схеме.
Класс AccountId
определяет учетную запись в конкретном клиенте с помощью свойств, приведенных в следующей таблице.
Свойство | Description |
---|---|
TenantId |
Строковое представление идентификатора GUID, которое является идентификатором клиента, где находится учетная запись. |
ObjectId |
Строковое представление идентификатора GUID, являющееся идентификатором пользователя, которому принадлежит учетная запись в клиенте. |
Identifier |
Уникальный идентификатор для учетной записи. Identifier является объединением ObjectId и TenantId , разделенных запятой. Для этих значений шифрование Base 64 не применяется. |
Интерфейс IAccount
предоставляет сведения об одной учетной записи. Один и тот же пользователь может быть в разных клиентах, это означает, что у пользователя может быть несколько учетных записей. Компоненты этого интерфейса представлены в следующей таблице.
Свойство | Description |
---|---|
Username |
Строка с отображаемым значением в формате UserPrincipalName (UPN), например john.doe@contoso.com. Эта строка может иметь значение NULL, в отличие от свойств HomeAccountId и HomeAccountId.Identifier, у которых не может быть значения NULL. Это свойство заменяет свойство DisplayableId интерфейса IUser из предыдущих версий MSAL.NET. |
Environment |
Строка с поставщиком удостоверений для этой учетной записи, например login.microsoftonline.com . Это свойство заменяет свойство IdentityProvider интерфейса IUser , за исключением того, что в свойстве IdentityProvider также содержались сведения о клиенте в дополнение к информации об облачной среде. Содержащееся здесь значение определяет только узел. |
HomeAccountId |
Идентификатор домашней учетной записи пользователя. Это свойство однозначно идентифицирует пользователя в клиентах Microsoft Entra. |
Использование маркера для вызова защищенного API
После того как AuthenticationResult
возвращается MSAL в переменную result
, ее нужно добавить в HTTP-заголовок авторизации перед тем, как делать вызов для доступа к защищенному веб-API.
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Call the web API.
HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
...
}
Выполнение нескольких запросов API
Чтобы вызвать один и тот же API несколько раз или вызвать несколько API, при разработке приложения следует учитывать следующие моменты.
Добавочное согласие. Платформа удостоверений Microsoft позволяет приложениям получать согласие пользователя, когда необходимы разрешения, а не все сразу во время запуска. Всякий раз, когда ваше приложение готово вызвать API, оно должно запрашивать только необходимые ему области.
Условный доступ. При отправке нескольких запросов API в некоторых сценариях потребуется обеспечить выполнение дополнительных требований к условному доступу. Требования могут увеличиваться таким образом, если первый запрос не имеет политик условного доступа, и приложение пытается автоматически получить доступ к новому API, которому требуется условный доступ. Для решения этой проблемы необходимо перехватывать ошибки, генерируемые такими автоматическими запросами, и быть готовым к выполнению интерактивного запроса. Дополнительные сведения см. в руководстве по условному доступу.
Вызов нескольких API с помощью добавочного согласия и условного доступа
Чтобы вызвать несколько API для одного пользователя после получения маркера для этого пользователя, можно не требовать от него предоставления учетных данных. Достаточно вызывать AcquireTokenSilent
, чтобы получить маркер:
var result = await app.AcquireTokenXX("scopeApi1")
.ExecuteAsync();
result = await app.AcquireTokenSilent("scopeApi2")
.ExecuteAsync();
Взаимодействие необходимо, если:
- Пользователь предоставил согласие для первого API, а теперь ему требуется согласие для других областей. В этом случае следует использовать добавочное согласие.
- Первый API не требует многофакторной проверки подлинности, в отличие от следующего API.
var result = await app.AcquireTokenXX("scopeApi1")
.ExecuteAsync();
try
{
result = await app.AcquireTokenSilent("scopeApi2")
.ExecuteAsync();
}
catch(MsalUiRequiredException ex)
{
result = await app.AcquireTokenInteractive("scopeApi2")
.WithClaims(ex.Claims)
.ExecuteAsync();
}
Следующие шаги
См. следующую статью для этого сценария: Переход к рабочей среде.