問題描述
我正在嘗試使用他們的 Office 365 帳戶對我的站點的用戶進(jìn)行身份驗證,因此我一直在遵循有關(guān)使用 OWIN OpenID Connect 中間件添加身份驗證的指南,并成功地驗證并檢索了他們的個人資料.
我現(xiàn)在正在嘗試獲取用戶的電子郵件地址(以便我可以使用他們的聯(lián)系方式填充他們的系統(tǒng)帳戶),但我似乎無法收到電子郵件聲明.我嘗試使用范圍 openid profile email
發(fā)出請求,但聲明集不包含任何郵件信息.
有沒有辦法通過 OpenID Connect 端點從 Azure AD 獲取用戶的電子郵件?
我在同一個問題上苦苦掙扎了幾天才找到解決方案.回答您的問題:是的,只要您:
- 在您的請求中包含
profile
或email
范圍,并且 - 在 Azure 門戶 Active Directory 部分中配置您的應(yīng)用程序,以在 委派權(quán)限 下包含登錄和讀取用戶配置文件.
請注意,電子郵件地址可能不會在 email
聲明中返回:在我的情況下(一旦我讓它工作)它會在 name
聲明中返回.
但是,根本沒有得到電子郵件地址可能是由以下問題之一引起的:
沒有與 Azure AD 帳戶關(guān)聯(lián)的電子郵件地址
根據(jù)本指南 Azure Active Directory v2.0 端點中的范圍、權(quán)限和同意,即使您包含 email
范圍,您也可能無法獲得電子郵件地址:p><塊引用>
email
聲明僅在電子郵件地址與用戶帳戶相關(guān)聯(lián)時包含在令牌中,但情況并非總是如此.如果它使用 email
范圍,您的應(yīng)用應(yīng)該準(zhǔn)備好處理令牌中不存在 email
聲明的情況.
如果您收到其他與個人資料相關(guān)的聲明(如 given_name
和 family_name
),這可能是問題所在.
中間件丟棄的聲明
這就是我的原因.我沒有收到任何與個人資料相關(guān)的聲明(名字、姓氏、用戶名、電子郵件等).
在我的例子中,身份處理堆棧如下所示:
- IdentityServer3
- IdentityServer3.AspNetIdentity
- 基于 couchbase-aspnet-identity 的自定義 Couchbase 存儲提供程序
問題出在 IdentityServer3.AspNetIdentity AspNetIdentityUserService
類中:InstantiateNewUserFromExternalProviderAsync()
方法如下所示:
受保護(hù)的虛擬任務(wù)<TUser>InstantiateNewUserFromExternalProviderAsync(字符串提供者,字符串 providerId,IEnumerable<Claim>索賠){var user = new TUser() { UserName = Guid.NewGuid().ToString("N") };返回 Task.FromResult(user);}
注意它會傳入一個聲明集合然后忽略它.我的解決方案是創(chuàng)建一個派生自此的類并將該方法重寫為如下所示:
受保護(hù)的覆蓋任務(wù)<TUser>InstantiateNewUserFromExternalProviderAsync(字符串提供者,字符串 providerId,IEnumerable<Claim>索賠){var user = 新的 TUser{用戶名 = Guid.NewGuid().ToString("N"),索賠=索賠};返回 Task.FromResult(user);}
我不確切知道您正在使用什么中間件組件,但很容易看到從您的外部提供商返回的原始聲明;這至少會告訴您他們恢復(fù)正常,并且問題出在您的中間件的某個地方.只需將 Notifications
屬性添加到您的 OpenIdConnectAuthenticationOptions
對象,如下所示:
//將 Azure AD 配置為提供程序var azureAdOptions = 新的 OpenIdConnectAuthenticationOptions{AuthenticationType = 常量.Azure.AuthenticationType,標(biāo)題 = Resources.AzureSignInCaption,范圍 = 常量.Azure.Scopes,ClientId = Config.Azure.ClientId,權(quán)限 = 常量.Azure.AuthenticationRootUri,PostLogoutRedirectUri = Config.Identity.RedirectUri,RedirectUri = Config.Azure.PostSignInRedirectUri,AuthenticationMode = AuthenticationMode.Passive,TokenValidationParameters = 新的 TokenValidationParameters{驗證發(fā)行人 = 假},通知 = 新的 OpenIdConnectAuthenticationNotifications{AuthorizationCodeReceived = 上下文 =>{//記錄 Azure AD 返回的所有聲明var 聲明 = context.AuthenticationTicket.Identity.Claims;foreach(聲明中的 var 聲明){Log.Debug("{0} = {1}", claim.Type, claim.Value);}返回空值;}},SignInAsAuthenticationType = signInAsType//這必須在 TokenValidationParameters 之后};app.UseOpenIdConnectAuthentication(azureAdOptions);
另見
- 這篇文章由 Scott Brady 撰寫 包含有關(guān)聲明轉(zhuǎn)換的部分,如果上述方法均未修復(fù)它,這可能很有用.
- 關(guān)于 IdentityServer3 GitHub 帳戶的討論 對我?guī)椭艽?,尤其?此回復(fù).
I'm trying to authenticate users to my site with their Office 365 accounts, so I have been following the guidance on using the OWIN OpenID Connect middleware to add authentication and successfully managed to authenticate and retrieve their profile.
I am now trying to get the email address of the user (so I can populate their system account with their contact details), but I can't seem to get an email claim back. I have tried making a request using the scope openid profile email
, but the claim-set does not contain any mail information.
Is there a way to get the email of a user from Azure AD via the OpenID Connect endpoint?
I struggled with the same problem for a few days before arriving at a solution. In answer to your question: yes, you should be able to get the e-mail address back in your claims as long as you:
- Include the
profile
oremail
scope in your request, and - Configure your application in the Azure Portal Active Directory section to include Sign in and read user profile under Delegated Permissions.
Note that the e-mail address may not be returned in an email
claim: in my case (once I got it working) it's coming back in a name
claim.
However, not getting the e-mail address back at all could be caused by one of the following issues:
No e-mail address associated with the Azure AD account
As per this guide to Scopes, permissions, and consent in the Azure Active Directory v2.0 endpoint, even if you include the email
scope you may not get an e-mail address back:
The
If you're getting other profile-related claims back (like given_name
and family_name
), this might be the problem.
Claims discarded by middleware
This was the cause for me. I wasn't getting any profile-related claims back (first name, last name, username, e-mail, etc.).
In my case, the identity-handling stack looks like this:
- IdentityServer3
- IdentityServer3.AspNetIdentity
- A custom Couchbase storage provider based on couchbase-aspnet-identity
The problem was in the IdentityServer3.AspNetIdentity AspNetIdentityUserService
class: the 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);
}
Note it passes in a claims collection then ignores it. My solution was to create a class derived from this and override the method to something like this:
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);
}
I don't know exactly what middleware components you're using, but it's easy to see the raw claims returned from your external provider; that'll at least tell you they're coming back OK and that the problem is somewhere in your middleware. Just add a Notifications
property to your OpenIdConnectAuthenticationOptions
object, like this:
// 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);
See also
- This article by Scott Brady contains a section on Claims Transformation which may be useful if neither of the above fixes it.
- This discussion on the IdentityServer3 GitHub account was a huge help to me, especially this response.
這篇關(guān)于通過 OpenID Connect 從 Azure AD 獲取用戶的電子郵件地址的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!