「名前」フィールドが提供されていることは知っていますが、姓と名に明示的にアクセスしたいと思います。誰かがこれを手伝ってくれる?私はまだASP.Net MVCに頭を抱えています。
Startup.Auth.cs ConfigureAuth(IAppBuilder app)
メソッドで、Facebookに次のように設定します。
var x = new FacebookAuthenticationOptions();
x.Scope.Add("email");
x.AppId = "*";
x.AppSecret = "**";
x.Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
foreach (var claim in context.User)
{
var claimType = string.Format("urn:facebook:{0}", claim.Key);
string claimValue = claim.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
}
}
};
x.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
app.UseFacebookAuthentication(x);
/*
app.UseFacebookAuthentication(
appId: "*",
appSecret: "*");
* */
次に、これを使用してユーザーのログイン情報にアクセスします。
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
そして、次のように名を取得します。
var firstNameClaim = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:first_name");
Facebookは許可APIを変更しました。詳細については、こちらをご覧ください: https://developers.facebook.com/docs/facebook-login/permissions
名前にはpublic_profile権限が必要です
var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
{
AppId = "appId",
AppSecret = "key"
};
facebookAuthenticationOptions.Scope.Add("email");
facebookAuthenticationOptions.Scope.Add("public_profile");
app.UseFacebookAuthentication(facebookAuthenticationOptions);
そしてあなたはそれを使ってそれを得ることができます:
var loginInfo = await authenticationManager.GetExternalLoginInfoAsync();
loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:name")
authenticationManagerはインスタンスです。次を使用して取得できます。
HttpContext.GetOwinContext().Authentication;
2017年現在、これは私のために機能しているコードです(上記のDavid Poxonのコードに感謝します)。 Microsoft.Owin.Security.Facebook
のバージョン3.1.0にアップグレードしたことを確認してください。
Startup.Auth.cs(または場合によってはStartup.cs)に、次のコードを配置します。
app.UseFacebookAuthentication(new FacebookAuthenticationOptions()
{
AppId = "***",
AppSecret = "****",
BackchannelHttpHandler = new HttpClientHandler(),
UserInformationEndpoint = "https://graph.facebook.com/v2.8/me?fields=id,name,email,first_name,last_name",
Scope = { "email" },
Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
foreach (var claim in context.User)
{
var claimType = string.Format("urn:facebook:{0}", claim.Key);
string claimValue = claim.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
}
}
}
});
次に、コントローラーの外部ログインコールバックメソッドで、次のコードを追加します。
var firstName = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:first_name").Value;
同様に姓を取得するには、上記の行を使用してurn:facebook:first_name
をurn:facebook:last_name
に置き換えます
2019年1月の時点で、これを確認し、追加のビットをいくつか提供したいと思っていました(答えが書かれた年によっては、競合する情報がたくさんあります!)。 DavidとWaqasが最良の答えです(IMO)。 MVC5、AspNetIdentity 2、IdentityServer 3を使用しています。
まず、FacebookのIDプロバイダー構成:
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
AuthenticationType = "facebook",
Caption = "Login with Facebook",
SignInAsAuthenticationType = signInAsType,
AppId = ConfigurationManager.AppSettings["FacebookAppId"],
AppSecret = ConfigurationManager.AppSettings["FacebookAppSecret"],
Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = ctx =>
{
foreach (var claim in ctx.User)
{
var claimType = $"urn:facebook:{claim.Key}";
var claimValue = claim.Value.ToString();
if (!ctx.Identity.HasClaim(claim.Key, claimValue))
{
ctx.Identity.AddClaim(new Claim(claim.Key, claimValue));
}
}
return Task.FromResult(0);
}
}
});
他の回答の一部とは異なり、これは追加の要求されたフィールドをデフォルトで取得するフィールドと組み合わせ、urn:facebook:
をクレームの先頭から削除して、デフォルトのクレーム命名スキームと一致させます。
Scopes
やFields
を追加する必要はありません(少なくとも、姓名は除く)。 Microsoft.Owin.Security.Facebook
のバージョン4.1では、これがすでに行われています。 FacebookAuthenticationOptionsのソースコードはこちら です。関連ビット:
public FacebookAuthenticationOptions()
: base(Constants.DefaultAuthenticationType)
{
Caption = Constants.DefaultAuthenticationType;
CallbackPath = new PathString("/signin-facebook");
AuthenticationMode = AuthenticationMode.Passive;
Scope = new List<string>();
BackchannelTimeout = TimeSpan.FromSeconds(60);
SendAppSecretProof = true;
_fields = new HashSet<string>();
CookieManager = new CookieManager();
AuthorizationEndpoint = Constants.AuthorizationEndpoint;
TokenEndpoint = Constants.TokenEndpoint;
UserInformationEndpoint = Constants.UserInformationEndpoint;
Scope.Add("public_profile");
Scope.Add("email");
Fields.Add("name");
Fields.Add("email");
Fields.Add("first_name");
Fields.Add("last_name");
}
(私と同じように)IdentityServer 3を使用している場合は、次のようにカスタムUserService
で認証に関するこれらの要求を取得する必要があります。
public async override Task AuthenticateExternalAsync(ExternalAuthenticationContext ctx)
{
// first, lets see if we have enough data from this external provider
// at a minimum, FirstName, LastName, and Email are required
string email = null;
string firstName = null;
string lastName = null;
var idp = ctx.ExternalIdentity.Provider;
email = GetClaimValue(ctx, "email");
if (idp == "google")
{
firstName = GetClaimValue(ctx, "given_name");
lastName = GetClaimValue(ctx, "family_name");
}
else if (idp == "facebook")
{
firstName = GetClaimValue(ctx, "first_name");
lastName = GetClaimValue(ctx, "last_name");
}
var missingClaims = "";
if (email == null)
{
missingClaims = "email";
}
if (firstName == null)
{
if (missingClaims.Length > 0) { missingClaims += ", "; }
missingClaims += "first name";
}
if (lastName == null)
{
if (missingClaims.Length > 0) { missingClaims += ", "; }
missingClaims += "last name";
}
if (missingClaims.Length > 0)
{
var errorMessage = $"The external login provider didn't provide the minimum required user profile data. Missing: {missingClaims} " +
"Verify that these fields are specified in your external login provider user profile and that you have allowed external apps (i.e. this one) access to them. " +
"Alternatively, you can try a different external login provider, or create a local acount right here.";
ctx.AuthenticateResult = new AuthenticateResult(errorMessage);
return;
}
var login = new Microsoft.AspNet.Identity.UserLoginInfo(ctx.ExternalIdentity.Provider, ctx.ExternalIdentity.ProviderId);
var user = await _userManager.FindAsync(login);
if (user == null)
{
// this user either does not exist or has not logged in with this identity provider
// let's see if they already exist (by checking to see if there is a user account with this email address)
user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
// there is no existing user with this email, therefore, a new user will be created
user = new MotoTallyUser()
{
Id = Guid.NewGuid(),
UserName = email,
Email = email,
EmailConfirmed = true,
FirstName = firstName,
LastName = lastName
};
await _userManager.CreateAsync(user);
await _userManager.AddLoginAsync(user.Id, login);
}
else
{
// this user DOES exist (matched email provided by external login provider)
// however, they have not logged in with this identity provider
// therefore, update the user info with that reported by the external identity provider, and add the external login
user.UserName = email;
user.Email = email;
user.EmailConfirmed = true;
user.FirstName = firstName;
user.LastName = lastName;
await _userManager.UpdateAsync(user);
await _userManager.AddLoginAsync(user.Id, login);
}
}
else
{
// this user DOES exist (they already have an external login on record)
// therefore, update the user info with that reported by the external identity provider (no need to add external login, its already there)
user.UserName = email;
user.Email = email;
user.EmailConfirmed = true;
user.FirstName = firstName;
user.LastName = lastName;
await _userManager.UpdateAsync(user);
}
ctx.AuthenticateResult = new AuthenticateResult(user.Id.ToString(), user.Email, null, ctx.ExternalIdentity.Provider);
return;
}
private string GetClaimValue(ExternalAuthenticationContext ctx, string claimType)
{
if (ctx.ExternalIdentity.Claims.FirstOrDefault(x => x.Type == claimType) != null)
{
return ctx.ExternalIdentity.Claims.FirstOrDefault(x => x.Type == claimType).Value;
}
return null;
}
これが誰かを助けることを願っています!
private Uri RedirectUri
{
get
{
var uriBuilder = new UriBuilder(Request.Url);
uriBuilder.Query = null;
uriBuilder.Fragment = null;
uriBuilder.Path = Url.Action("FacebookCallback");
return uriBuilder.Uri;
}
}
[AllowAnonymous]
public ActionResult Facebook()
{
var fb = new FacebookClient();
var loginUrl = fb.GetLoginUrl(new
{
client_id = "296002327404***",
client_secret = "4614cd636ed2029436f75c77961a8***",
redirect_uri = RedirectUri.AbsoluteUri,
response_type = "code",
scope = "email" // Add other permissions as needed
});
return Redirect(loginUrl.AbsoluteUri);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return View("Login");
}
public ActionResult FacebookCallback(string code)
{
var fb = new FacebookClient();
dynamic result = fb.Post("oauth/access_token", new
{
client_id = "296002327404***",
client_secret = "4614cd636ed2029436f75c77961a8***",
redirect_uri = RedirectUri.AbsoluteUri,
code = code
});
var accessToken = result.access_token;
// Store the access token in the session for farther use
Session["AccessToken"] = accessToken;
// update the facebook client with the access token so
// we can make requests on behalf of the user
fb.AccessToken = accessToken;
// Get the user's information
dynamic me = fb.Get("me?fields=first_name,middle_name,last_name,id,email");
string email = me.email;
string firstname = me.first_name;
string middlename = me.middle_name;
string lastname = me.last_name;
db.Insert_customer(firstname,email,null,null,null,null,null,null,null,null,null,null,1,1,System.DateTime.Now,1,System.DateTime.Now);
// Set the auth cookie
FormsAuthentication.SetAuthCookie(email, false);
return RedirectToAction("Index", "Home");
}
}
}
Facebookは、アップグレード2.4でGraph APIが値を返す方法を変更しました。ここで、取得したいすべてのフィールドを明示的に指定する必要があります。
次のメモを参照してください 開発者向けアップグレードアップグレード情報 :
バージョン2.4でのグラフAPIの変更
これまで、Graph API呼び出しからの応答は一連のデフォルトフィールドを返していました。ペイロードサイズを削減し、モバイルネットワークの遅延を改善するために、ほとんどのGraph API呼び出しで返されるデフォルトフィールドの数を減らしました。 v2.4では、呼び出しの応答フィールドを宣言的にリストする必要があります。
facebookからメール、FirstName、LastNameを取得するには:
まず、インストールする必要があります Facebook SDK for .NET nugetパッケージ
次に、startup.Auth.csで、Facebook認証の設定を次のように変更します。
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
// put your AppId and AppSecret here. I am reading them from AppSettings
AppId = ConfigurationManager.AppSettings["FacebookAppId"],
AppSecret = ConfigurationManager.AppSettings["FacebookAppSecret"],
Scope = { "email" },
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
return Task.FromResult(true);
}
}
});
// this is no longer needed
//app.UseFacebookAuthentication(
// appId: ConfigurationManager.AppSettings["FacebookAppId"],
// appSecret: ConfigurationManager.AppSettings["FacebookAppSecret"]);
最後に、AccountControllerで、ExternalLoginCallbackメソッドに次のコードを追加します。
if (string.Equals(loginInfo.Login.LoginProvider, "facebook", StringComparison.CurrentCultureIgnoreCase))
{
var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
var access_token = identity.FindFirstValue("FacebookAccessToken");
var fb = new FacebookClient(access_token);
// you need to specify all the fields that you want to get back
dynamic myInfo = fb.Get("/me?fields=email,first_name,last_name");
string email = myInfo.email;
string firstName = myInfo.first_name;
string lastName = myInfo.last_name;
}
取得できるその他のパラメーターについては、 facebook API Guid を参照してください。