我正在尝试使用他们的 Office 365 帐户对访问我网站的用户进行身份验证,因此我一直遵循有关使用 OWIN OpenID Connect 中间件添加身份验证的指南,并成功地设法对他们的个人资料进行身份验证和检索。
我现在正在尝试获取用户的电子邮件地址(以便我可以使用他们的详细联系信息填充他们的系统帐户),但我似乎无法收回电子邮件声明。我已尝试使用范围 openid profile email
发出请求,但声明集不包含任何邮件信息。
有没有办法通过 OpenID Connect 端点从 Azure AD 获取用户的电子邮件?
最佳答案
在找到解决方案之前,我为同一个问题苦苦挣扎了几天。在回答您的问题时:是的,只要您满足以下条件,您就应该能够在 claim 中取回电子邮件地址:
- 在您的请求中包含
profile
或email
范围,并且 - 在 Azure 门户 Active Directory 部分配置您的应用程序以在委派权限下包含登录和阅读用户配置文件。
请注意,电子邮件地址可能不会在 email
声明中返回:在我的情况下(一旦我开始工作)它会在 name
声明中返回.
但是,根本 无法取回电子邮件地址可能是由以下问题之一引起的:
没有与 Azure AD 帐户关联的电子邮件地址
根据本指南Scopes, permissions, and consent in the Azure Active Directory v2.0 endpoint ,即使您包含 email
范围,您也可能无法取回电子邮件地址:
The
如果您收到其他与配置文件相关的声明(例如 given_name
和 family_name
),这可能就是问题所在。
被中间件丢弃的声明
这就是我的原因。我没有收到任何个人资料相关的声明(名字、姓氏、用户名、电子邮件等)。
在我的例子中,身份处理堆栈如下所示:
- IdentityServer3
- IdentityServer3.AspNetIdentity
- 基于 couchbase-aspnet-identity 的自定义 Couchbase 存储提供程序
问题出在 IdentityServer3.AspNetIdentity AspNetIdentityUserService
类中:InstantiateNewUserFromExternalProviderAsync()
method looks like this :
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);
另见
- This article by Scott Brady包含关于 Claims Transformation 的部分,如果上述方法均未解决,该部分可能会有用。
- This discussion on the IdentityServer3 GitHub account对我帮助很大,尤其是this response .
关于c# - 通过 OpenID Connect 从 Azure AD 获取用户的电子邮件地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30983694/