OnAuthenticatedコンテキストとして返され、次の例に従ってクレームとして追加されたユーザープロパティを取得しようとしています: ASP.NET Identity(OWIN)を使用してFacebookの個人情報にアクセスする方法は?
期待しているデータがログイン時に返され、Starup.Auth.cs内にクレームとして追加されていることがわかります。しかし、私がアカウントコントローラー内にいる場合、UserManagerまたはUserStore内に表示される唯一のクレームは地方自治体によって発行されます。 Facebook(または他の外部プロバイダー)に対するクレームは見つかりません。コンテキストに追加されたクレームはどこに行き着くのですか? (私はVS2013 RTMを使用しています。)
ここにリンクされているAzureの完全なソースとライブサイト: https://github.com/johndpalm/IdentityUserPropertiesSample/tree/VS2013rtm
これがStartup.Auth.csにあるものです:
var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions()
{
AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),
AppSecret = ConfigurationManager.AppSettings.Get("FacebookAppSecret"),
Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
foreach (var x in context.User)
{
var claimType = string.Format("urn:facebook:{0}", x.Key);
string claimValue = x.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, XmlSchemaString, "Facebook"));
}
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook"));
return Task.FromResult(0);
}
}
};
facebookOptions.Scope.Add("email");
app.UseFacebookAuthentication(facebookOptions);
外部ログインプロパティをキャプチャする別の方法は、アクセストークンの単一のクレームを追加し、それにプロパティを入力することです。
const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions
{
AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),
AppSecret = ConfigurationManager.AppSettings.Get("FacebookAppSecret"),
Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
var claim = new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook");
foreach (var x in context.User)
{
string key = string.Format("urn:facebook:{0}", x.Key);
string value = x.Value.ToString();
claim.Properties.Add(key, value);
}
context.Identity.AddClaim(claim);
return Task.FromResult(0);
}
}
};
注-このサンプルは機能しません:プロパティを含む単一のクレームを渡すのは良いことですが。外部Cookieは、クレームプロパティを尊重することに注意しているようです。後でIDからプロパティを取得するとき、プロパティは空です。
MVC 5 RTMテンプレート、OWIN、およびASP.NET Identityビットを使用して、実用的な例を作成できました。完全なソースと実際の実用的な例へのリンクは、次の場所にあります。- https://github.com/johndpalm/IdentityUserPropertiesSample
これが私のために働いたものです:
Startup.ConfigureAuth(StartupAuth.cs)に新しい(ここにプロバイダー名を挿入)AuthenticationOptionsオブジェクトを作成し、クライアントID、クライアントシークレット、および新しいAuthenticationProviderを渡します。ラムダ式を使用して、OnAuthenticatedメソッドにコードを渡し、context.Identityから抽出した値を含むIDにクレームを追加します。
StartUp.Auth.cs
// Facebook : Create New App
// https://dev.Twitter.com/apps
if (ConfigurationManager.AppSettings.Get("FacebookAppId").Length > 0)
{
var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions()
{
AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),
AppSecret = ConfigurationManager.AppSettings.Get("FacebookAppSecret"),
Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook"));
foreach (var x in context.User)
{
var claimType = string.Format("urn:facebook:{0}", x.Key);
string claimValue = x.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, XmlSchemaString, "Facebook"));
}
return Task.FromResult(0);
}
}
};
app.UseFacebookAuthentication(facebookOptions);
}
注:Facebook認証プロバイダーは、ここで使用されているコードで動作します。これと同じコードをMicrosoftアカウントプロバイダー(または Foursquareプロバイダー MSアカウントコードをモデルとして使用して作成したもの)で使用すると、ログインに失敗します。 access_tokenパラメーターのみを選択すると、正常に機能します。一部のパラメータがログインプロセスを中断しているようです。 ( これに関する進捗状況に関心がある場合は、katanaproject.codeplex.comで問題が開かれています。 )原因が見つかった場合は更新します。 access_tokenを取得できることを確認する以外は、TwitterやGoogleではあまり何もしませんでした。
var msaccountOptions = new Microsoft.Owin.Security.MicrosoftAccount.MicrosoftAccountAuthenticationOptions()
{
ClientId = ConfigurationManager.AppSettings.Get("MicrosoftClientId"),
ClientSecret = ConfigurationManager.AppSettings.Get("MicrosoftClientSecret"),
Provider = new Microsoft.Owin.Security.MicrosoftAccount.MicrosoftAccountAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:microsoftaccount:access_token", context.AccessToken, XmlSchemaString, "Microsoft"));
return Task.FromResult(0);
}
}
};
app.UseMicrosoftAccountAuthentication(msaccountOptions);
AccountControllerで、外部Cookieを使用してAuthenticationManagerからClaimsIdentityを抽出します。次に、アプリケーションCookieを使用して作成されたIDに追加します。 「... schemas.xmlsoap.org/ws/2005/05/identity/claims」で始まるクレームはログインが壊れているようだったので無視しました。
AccountController.cs
private async Task SignInAsync(CustomUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Extracted the part that has been changed in SignInAsync for clarity.
await SetExternalProperties(identity);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
private async Task SetExternalProperties(ClaimsIdentity identity)
{
// get external claims captured in Startup.ConfigureAuth
ClaimsIdentity ext = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
if (ext != null)
{
var ignoreClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims";
// add external claims to identity
foreach (var c in ext.Claims)
{
if (!c.Type.StartsWith(ignoreClaim))
if (!identity.HasClaim(c.Type, c.Value))
identity.AddClaim(c);
}
}
}
そして最後に、LOCALAUTHORITY以外の値を表示したいと思います。 / Account/Manageページ に表示される部分ビュー _ ExternalUserPropertiesListPartial を作成しました。以前に保存したクレームをAuthenticationManager.User.Claimsから取得し、それをビューに渡します。
AccountController.cs
[ChildActionOnly]
public ActionResult ExternalUserPropertiesList()
{
var extList = GetExternalProperties();
return (ActionResult)PartialView("_ExternalUserPropertiesListPartial", extList);
}
private List<ExtPropertyViewModel> GetExternalProperties()
{
var claimlist = from claims in AuthenticationManager.User.Claims
where claims.Issuer != "LOCAL AUTHORITY"
select new ExtPropertyViewModel
{
Issuer = claims.Issuer,
Type = claims.Type,
Value = claims.Value
};
return claimlist.ToList<ExtPropertyViewModel>();
}
そして、徹底的に言うと、ビュー:
_ExternalUserPropertiesListPartial.cshtml
@model IEnumerable<MySample.Models.ExtPropertyViewModel>
@if (Model != null)
{
<legend>External User Properties</legend>
<table class="table">
<tbody>
@foreach (var claim in Model)
{
<tr>
<td>@claim.Issuer</td>
<td>@claim.Type</td>
<td>@claim.Value</td>
</tr>
}
</tbody>
</table>
}
繰り返しますが、実際の例と完全なコードはGitHubにあります: https://github.com/johndpalm/IdentityUserPropertiesSample
そして、フィードバック、修正、または改善をいただければ幸いです。
したがって、この記事では、これがすべてうまく機能する方法について説明します。 owin external authのデカップリング
しかし、簡単な答えは、Facebookから認証されると、外部IDが与えられるということです。次に、その外部IDを取得し、ローカルアプリIDに「サインイン」する必要があります。そのステップで、外部IDからUser.IdentityになるClaimsIdentityに必要なクレームを追加する必要があります。
編集:さらに明確にするために、ExternalLoginCallback内でそれを行うことができます:
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl) {
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null) {
return RedirectToAction("Login");
}
// Sign in this external identity if its already linked
var user = await UserManager.FindAsync(loginInfo.Login);
if (user != null) {
await SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl);
}
private async Task SignInAsync(ApplicationUser user, bool isPersistent) {
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
したがって、サインインに追加のデータを渡す必要があります。これは次のようになります。
ClaimsIdentity id = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
このClaimsIdentityには追加されたクレームがあり、表示するには、SignInAsyncメソッドで作成されたIDにそのクレームを追加する必要があります。
要するに、AddClaimが使用された後に必要な行は次のとおりです。
上記のジョンズの回答から取得。
ClaimsIdentity ext = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);