Office 365アカウントを使用して自分のサイトでユーザーを認証しようとしているので、OWIN OpenID Connectミドルウェアを使用して認証を追加するためのガイダンスに従い、ユーザーのプロファイルの認証と取得に成功しました。
現在、ユーザーの電子メールアドレスを取得しようとしています(システムアカウントに連絡先の詳細を入力できるように)が、電子メールの要求を取り戻すことができないようです。スコープを使ってリクエストしてみましたopenid profile email
ですが、クレームセットにはメール情報が含まれていません。
OpenID Connectエンドポイントを介してAzureADからユーザーの電子メールを取得する方法はありますか?
私は解決策にたどり着く前に、同じ問題に数日間苦労しました。あなたの質問への回答:はい、あなたが次のことをしている限り、あなたはあなたの主張で電子メールアドレスを取り戻すことができるはずです:
profile
またはemail
スコープを含め、電子メールアドレスはemail
クレームで返されない場合があることに注意してください。私の場合(機能するようになったら)、name
クレームで返されます。
ただし、電子メールアドレスが戻らないまったくは、次のいずれかの問題が原因である可能性があります。
このガイドに従って Azure Active Directory v2.0エンドポイントのスコープ、アクセス許可、および同意email
スコープを含めても、電子メールアドレスが返されない場合があります:
他のプロファイル関連のクレーム(_given_name
_や_family_name
_など)が返される場合は、これが問題である可能性があります。
これが私の原因でした。 anyプロファイル関連のクレーム(名、姓、ユーザー名、電子メールなど)が返されませんでした。
私の場合、ID処理スタックは次のようになります。
問題はIdentityServer3.AspNetIdentityAspNetIdentityUserService
クラスにありました: 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);
_
サインイン要求で&resource = https://graph.windows.net を承認エンドポイントに渡してから、Azure AD GraphAPIに認証済みの組織ユーザーのOfficeを照会するオプションはありますか? 365の電子メールアドレス?たとえば、GET https://graph.windows.net/me/mail?api-version=1.5
追加のリファレンスについては、AzureADSamplesGitHubのWebApp-WebAPI-MultiTenant-OpenIdConnect-DotNetコードサンプルを参照してください。
私は何日も同じ問題に苦しんでいました...私は個人のMicrosoftアカウントを持つユーザーから電子メールアドレスを取得していましたが、会社のMicrosoftアカウントを持つユーザーからは取得していませんでした。
個人アカウントの場合、電子メールアドレスは予想どおりemail
フィールドに返されます。
会社のアカウントの場合、メールアドレスはpreferred_username
フィールドに返されます。
私がまだ発見していない別のマイクロソフトのバリエーションがないことを私の指を交差させ続けます...
2019年の更新された回答:email
クレームは、リクエストに含まれない可能性のあるオプションのクレームです( ソース )
管理対象ユーザー(テナント内のユーザー)の場合は、このオプションのクレームを介して、またはv2.0の場合のみOpenIDスコープを使用して要求する必要があります。
次のように、Azure Portalのマニフェストファイルを更新して、オプションのクレームを含める必要があります。
"optionalClaims": {
"idToken": [
{
"name": "email",
"source": null,
"essential": false,
"additionalProperties": []
}
],
}
この回答は部分的に このブログ投稿 に触発されました。
同じ状況で、ログイン後にアクセス可能なすべてのユーザークレームを返す非常に単純なコードになりました(電子メールを含む)
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
namespace Controllers
{
public class BaseController : Controller
{
protected string GetCurrentUserIDFromClaims()
{
return User.FindFirstValue(ClaimTypes.NameIdentifier);
}
protected List<string> AllClaimsFromAzure()
{
ClaimsIdentity claimsIdentity = ((ClaimsIdentity)User.Identity);
return claimsIdentity.Claims.Select(x => x.Value).ToList();
}
protected string GetCurrentEmailFromAzureClaims()
{
return AllClaimsFromAzure()[3];
}
}
}