Получите адрес электронной почты пользователя от Azure AD через OpenID Connect

Я пытаюсь аутентифицировать пользователей на своем сайте со своими учетными записями Office 365, поэтому я слежу за рекомендациями по использованию промежуточного программного обеспечения OWIN OpenID Connect для добавления аутентификации и успешной проверки подлинности и получения их профиля.

Теперь я пытаюсь получить адрес электронной почты пользователя (поэтому я могу заполнить их системную учетную запись контактными данными), но я не могу получить заявку на email. Я попытался сделать запрос с использованием области openid profile email, но набор требований не содержит никакой информации о почте.

Есть ли способ получить электронную почту пользователя от Azure AD через конечную точку OpenID Connect?

Ответ 1

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

  • Включите область profile или email в свой запрос и
  • Настройте приложение в разделе Active Directory Azure Portal, чтобы включить вход и просмотр профиля пользователя в разделе "Разрешенные разрешения".

Обратите внимание, что адрес электронной почты не может быть возвращен в претензии email: в моем случае (после того, как я получил его работу) он возвращается в заявку name.

Однако не получить адрес электронной почты вообще может быть вызвана одной из следующих проблем:

Отсутствует адрес электронной почты, связанный с учетной записью Azure AD

В соответствии с этим руководством по Области, разрешения и согласие в конечной точке Azure Active Directory v2.0, даже если вы включили email область действия, на которую вы не сможете получить адрес электронной почты:

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

Если вы снова получите другие претензии, связанные с профилем (например, given_name и family_name), это может быть проблемой.

Претензии, отбрасываемые промежуточным программным обеспечением

Это было причиной для меня. Я не получал никаких претензий, связанных с профилем (имя, фамилия, имя пользователя, адрес электронной почты и т.д.).

В моем случае стек обработки идентичности выглядит следующим образом:

Проблема была в классе IdentityServer3.AspNetIdentity AspNetIdentityUserService: метод InstantiateNewUserFromExternalProviderAsync() выглядит следующим образом:

protected virtual Task<TUser> InstantiateNewUserFromExternalProviderAsync(
    string provider,
    string providerId,
    IEnumerable<Claim> claims)
{
    var user = new TUser() { UserName = Guid.NewGuid().ToString("N") };
    return Task.FromResult(user);
}

Обратите внимание, что он проходит в коллекции претензий, затем игнорирует его. Моим решением было создать класс, полученный из этого, и переопределить метод примерно так:

protected override Task<TUser> InstantiateNewUserFromExternalProviderAsync(
    string provider,
    string providerId,
    IEnumerable<Claim> claims)
{
    var user = new TUser
    {
        UserName = Guid.NewGuid().ToString("N"),
        Claims = claims
    };
    return Task.FromResult(user);
}

Я не знаю точно, какие компоненты промежуточного программного обеспечения вы используете, но легко увидеть исходные претензии, возвращенные вашим внешним поставщиком; что, по крайней мере, скажут вам, что они вернутся в норму и что проблема находится где-то в вашем промежуточном программном обеспечении. Просто добавьте свойство Notifications к вашему объекту OpenIdConnectAuthenticationOptions, например:

// Configure Azure AD as a provider
var azureAdOptions = new OpenIdConnectAuthenticationOptions
{
    AuthenticationType = Constants.Azure.AuthenticationType,
    Caption = Resources.AzureSignInCaption,
    Scope = Constants.Azure.Scopes,
    ClientId = Config.Azure.ClientId,
    Authority = Constants.Azure.AuthenticationRootUri,
    PostLogoutRedirectUri = Config.Identity.RedirectUri,
    RedirectUri = Config.Azure.PostSignInRedirectUri,
    AuthenticationMode = AuthenticationMode.Passive,
    TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false
    },
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthorizationCodeReceived = context =>
        {
            // Log all the claims returned by Azure AD
            var claims = context.AuthenticationTicket.Identity.Claims;
            foreach (var claim in claims)
            {
                Log.Debug("{0} = {1}", claim.Type, claim.Value);
            }
            return null;
        }
    },
    SignInAsAuthenticationType = signInAsType // this MUST come after TokenValidationParameters
};

app.UseOpenIdConnectAuthentication(azureAdOptions);

См. также

Ответ 2

Возможно ли, чтобы вы передали & resource = https://graph.windows.net в запрос входа в конечную точку авторизации, затем запрос API Azure AD Graph для аутентифицированного адреса электронной почты Office 365 организационного пользователя? Например, GET https://graph.windows.net/me/mail?api-version=1.5

Дополнительные сведения см. в примере кода WebApp-WebAPI-MultiTenant-OpenIdConnect-DotNet на AzureADSamples GitHub.

Ответ 3

Я боролся с той же самой проблемой в течение нескольких дней... Я получал адрес электронной почты от пользователей с личными учетными записями Microsoft, но не для тех, у кого были корпоративные учетные записи Microsoft.

Для личных учетных записей адрес электронной почты возвращается в поле email как и следовало ожидать.

Для учетных записей компании адрес электронной почты возвращается в поле preferred_username.

Скрестив пальцы на том, что нет другого варианта Microsoft, которого я еще не обнаружил...

Ответ 4

Обновленный ответ на 2019 год: утверждение по email является необязательным утверждением, которое может быть не включено в запрос (источник)

Для управляемых пользователей (находящихся внутри арендатора) его следует запрашивать с помощью этого необязательного утверждения или, только на версии 2.0, с областью действия OpenID.

Вам необходимо обновить файл манифеста на портале Azure, чтобы включить необязательное утверждение, например так:

"optionalClaims": {
    "idToken": [
        {
            "name": "email",
            "source": null,
            "essential": false,
            "additionalProperties": []
        }
    ],
}

Этот ответ был частично вдохновлен этим сообщением в блоге.