Единый вход с использованием MSAL.js

Единый вход (SSO) обеспечивает более эффективную работу за счет сокращения количества запросов учетных данных пользователей. Пользователи вводят свои учетные данные один раз, и установленный сеанс может быть повторно использован другими приложениями на устройстве без дополнительных запросов.

Azure Active Directory (Azure AD) обеспечивает единый вход, задавая файл cookie сеанса при первой проверке подлинности пользователя. MSAL.js позволяет использовать файл cookie сеанса для единого входа между вкладками браузера, открытыми для одного или нескольких приложений.

Единый вход между вкладками браузера для одного приложения

Когда пользователь открывает приложение на нескольких вкладках и входит в него на одной из них, он может войти в то же приложение, открытое на других вкладках, без запроса. Для этого вам необходимо задать для cacheLocation в объекте конфигурации MSAL.js значение localStorage, как показано ниже.

const config = {
  auth: {
    clientId: "1111-2222-3333-4444-55555555",
  },
  cache: {
    cacheLocation: "localStorage",
  },
};

const msalInstance = new msal.PublicClientApplication(config);

Единый вход между различными приложениями

Когда пользователь проходит проверку подлинности, в домене Azure AD в браузере задается файл cookie сеанса. MSAL.js полагается на этот файл cookie сеанса для предоставления единого входа для пользователя между различными приложениями. MSAL.js также кэширует маркеры идентификаторов и маркеры доступа пользователя в хранилище браузера на домен приложения.

MSAL.js предлагает метод ssoSilent для входа пользователя и получения маркеров без взаимодействия. Однако если в сеансе Azure AD у пользователя несколько учетных записей, ему будет предложено выбрать учетную запись для входа. Таким образом, существует два способа обеспечения единого входа с использованием метода ssoSilent.

С подсказкой пользователя

Чтобы повысить производительность и убедиться, что сервер авторизации будет искать правильный сеанс учетной записи. Чтобы автоматически получить маркер, можно передать один из следующих параметров в объекте запроса метода ssoSilent.

  • Идентификатор сеанса sid (который можно получить из idTokenClaims объекта account)
  • login_hint (которое можно получить из свойства имени пользователя объекта account или утверждения upn в маркере идентификатора)
  • account (которую можно получить с помощью одного из методов учетной записи)

Использование идентификатора сеанса

Чтобы использовать идентификатор сеанса, добавьте sid в качестве необязательного утверждения к маркерам идентификатора приложения. Утверждение sid позволяет приложению идентифицировать сеанс Azure AD пользователя независимо от его имени учетной записи или имени пользователя. Дополнительные сведения о том, как добавить необязательные утверждения, такие как sid, см. статью Предоставление приложению необязательных утверждений. Используйте идентификатор сеанса (SID) в автоматических запросах проверки подлинности, которые вы выполняете с помощью ssoSilent в MSAL.js.

const request = {
  scopes: ["user.read"],
  sid: sid,
};

 try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

Использование указания имени для входа

Чтобы обойти запрос на выбор учетной записи, который обычно отображается во время интерактивных запросов проверки подлинности (или для автоматических запросов, если вы не настроили необязательное утверждение sid), укажите loginHint. В мультитенантных приложениях также включите domain_hint.

const request = {
  scopes: ["user.read"],
  loginHint: preferred_username,
  extraQueryParameters: { domain_hint: "organizations" },
};

try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

Получите значения для loginHint и domain_hint из пользовательского маркера идентификатора:

  • loginHint: используйте значение утверждения preferred_username маркера идентификатора.

  • domain_hint: используйте значение утверждения tid маркера идентификатора. Требуется в запросах, выполняемых мультитенантными приложениями, которые используют /часто используемые центры. Необязательно для других приложений.

Дополнительные сведения об указании имени входа и указании домена см. в разделе Поток кода авторизации OAuth 2.0 и платформа удостоверений Майкрософт.

Использование объекта учетной записи

Если вы располагаете сведениями об учетной записи пользователя, вы также можете получить ее с помощью методов getAccountByUsername() или getAccountByHomeId().

const username = "test@contoso.com";
const myAccount  = msalInstance.getAccountByUsername(username);

const request = {
    scopes: ["User.Read"],
    account: myAccount
};

try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

Без подсказки пользователя

Вы можете попытаться использовать метод ssoSilent без передачи каких-либо account, sid или login_hint, как показано в приведенном ниже коде:

const request = {
    scopes: ["User.Read"]
};

try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

Тем не менее, существует вероятность ошибок автоматического входа, если приложение имеет несколько пользователей в одном сеансе браузера или если у пользователя есть несколько учетных записей для этого сеанса браузера. В случае наличия нескольких учетных записей может возникнуть следующая ошибка:

InteractionRequiredAuthError: interaction_required: AADSTS16000: Either multiple user identities are available for the current request or selected account is not supported for the scenario.

Ошибка указывает, что серверу не удалось определить учетную запись для входа, и для ее выбора потребуется один из указанных выше параметров (account, login_hint, sid) или интерактивный вход.

Рекомендации по использованию ssoSilent

URI перенаправления (URL-адреса ответа)

Для повышения производительности и во избежание проблем задайте для redirectUri пустую страницу или другую страницу, не использующую MSAL.

  • Если ваше приложение использует только всплывающие и автоматические методы, установите redirectUri в объекте конфигурации PublicClientApplication.
  • Если ваше приложение также использует методы перенаправления, установите redirectUri для каждого запроса.

Сторонние файлы cookie

ssoSilent пытается открыть скрытый iframe и повторно использовать существующий сеанс с Azure AD. Это не будет работать в браузерах, которые блокируют сторонние файлы cookie, таких как Safari, и приведет к ошибке взаимодействия:

InteractionRequiredAuthError: login_required: AADSTS50058: A silent sign-in request was sent but no user is signed in. The cookies used to represent the user's session were not sent in the request to Azure AD

Чтобы устранить ошибку, пользователь должен создать интерактивный запрос проверки подлинности с помощью loginPopup() или loginRedirect().

Кроме того, объект запроса требуется при использовании автоматических методов. Если у вас уже есть учетные данные пользователя, вы можете передать необязательные параметры loginHint или sid для входа в определенную учетную запись.

Единый вход в ADAL.js для обновления MSAL.js

MSAL.js применяют равенство функций с ADAL.js для сценариев проверки подлинности Azure AD. Чтобы выполнить простую миграцию с ADAL.js на MSAL.js и избежать повторного входа пользователей в систему, библиотека считывает маркер идентификации, представляющий сеанс пользователя в кэше ADAL.js и без проблем осуществляет вход пользователя в MSAL.js.

Чтобы воспользоваться преимуществами единого входа при обновлении с использованием ADAL.js, необходимо убедиться, что библиотеки используют localStorage для кэширования токенов. Присвойте параметру cacheLocation значение localStorage в конфигурациях MSAL.js и ADAL.js при инициализации следующим образом.


// In ADAL.js
window.config = {
  clientId: "1111-2222-3333-4444-55555555",
  cacheLocation: "localStorage",
};

var authContext = new AuthenticationContext(config);

// In latest MSAL.js version
const config = {
  auth: {
    clientId: "1111-2222-3333-4444-55555555",
  },
  cache: {
    cacheLocation: "localStorage",
  },
};

const msalInstance = new msal.PublicClientApplication(config);

После настройки cacheLocation MSAL.js сможет считывать кэшированное состояние пользователя, прошедшего проверку подлинности в ADAL.js, и использовать его для предоставления единого входа в MSAL.js.

Дальнейшие действия

См. дополнительные сведения о едином входе: