http://www.asp.net/mvc/tutorials/mvc-4/using-oauth-providers-with-mvc
I'm using code from this tutorial (of course, not all). Everything works perfectly, but when I tried to pass email, I have System.Collections.Generic.KeyNotFoundException. Why? How can I pass e-mail value from Facebook?
return View("ExternalLoginConfirmation", new RegisterExternalLoginModel {
UserName = result.UserName,
ExternalLoginData = loginData,
FullName = result.ExtraData["name"],
Email = result.ExtraData["email"],
ProfileLink = result.ExtraData["link"],
});
This works:
return View("ExternalLoginConfirmation", new RegisterExternalLoginModel {
UserName = result.UserName,
ExternalLoginData = loginData,
FullName = result.ExtraData["name"],
//Email = result.ExtraData["email"],
ProfileLink = result.ExtraData["link"],
});
Regards
Facebook doesn't share Email addresses by default. See this post for more information, but you can change your registration model to require email when making a user registration for your site. Also, you can check that the collection has the key first, before trying to access it
AuthenticationResult result =
OAuthWebSecurity
.VerifyAuthentication(
Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
// Log in code
if (result.ExtraData.ContainsKey("email"))
// Use email
Related
I have to get the contacts from Exchange server from any account, so we have used the code from below link.
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
But it is not working for personal accounts, which is working fine for our organization account. So I have used AadAuthorityAudience property instead of TenantId and changed the scope from EWS.AccessAsUser.All to others. Now authentication got success but getting "The given token is invalid" error while using the token in ExchangeService.
var pcaOptions = new PublicClientApplicationOptions {
ClientId = "77xxxxxxxxxxx92324",
//TenantId = "7887xxxxxxxxxxxxx14",
RedirectUri = "https://login.live.com/oauth20_desktop.srf",
AadAuthorityAudience = AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
//var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
var ewsScopes = new string[] { "User.Read", "Contacts.ReadWrite.Shared" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "araj#concord.net");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
What am doing wrong here?
https://outlook.office365.com/EWS.AccessAsUser.All is the right scope to use. The scope is invalid for personal accounts since they're not supported by EWS.
I have a login page called LoginTrial, the user enters the username and password and presses enter to log in.
The code below does successfully test the validity of username/password combos and returns an error if it does not exist in the table User.
However, if the combo of username/password is correct, the login looks to work, but it is as if i had not logged in at all, i don't see anything under: if (User.Identity.IsAuthenticated)
I know it's a bad idea to not hash passwords, but this was made to test login features.
User appUser = dbs.FromSqlInterpolated($"SELECT * FROM [User] WHERE username = {uid} AND password = {pw}").FirstOrDefault();
principal = null;
if (appUser != null)
{
principal = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
new Claim(ClaimTypes.Name, appUser.Username),
new Claim(ClaimTypes.Role, appUser.Role)
}, "Basic"
)
);
return true;
}
return false;
We have a mvc 5 project set up with adfs (ws-federation) authentication. Now, we want to add a custom claim to the user if a flag is true in the db. Where would be the correct place to do this?
This blog entry got us in the right direction. The claims need to be injected at the last minute after the user is validated.
Startup.Auth.cs should look something like this:
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
//NameClaimType = "User-Principal-Name",
//SaveSigninToken = true
},
//Inject custom claims from Database
Provider = new OAuthBearerAuthenticationProvider()
{
OnValidateIdentity = async context =>
{
string UPN = context.Ticket.Identity.FindFirst(ClaimTypes.Upn).Value;
UPN = UPN.Remove(UPN.Length - 12);
User user = new User();
//user = GetUserData("user#domain.com");
user = GetUserData(UPN); //Get user data from your DB
context.Ticket.Identity.AddClaim(
new Claim("UserName", user.UserName.ToString(), ClaimValueTypes.String, "LOCAL AUTHORITY"));
}
}
});
The easiest way is to set up a SQL attribute store and then write a custom rule to query the store.
As per the article, something like:
c:[type == "http://contoso.com/emailaddress"]
=> issue (store = "Custom SQL Store", types = ("http://contoso.com/age", "http://contoso.com/purchasinglimit"), query = "SELECT age,purchasinglimit FROM users WHERE email={0}",param = c.value);
This question already has answers here:
Why new fb api 2.4 returns null email on MVC 5 with Identity and oauth 2?
(6 answers)
Closed 6 years ago.
With v2.3 of the Facebook API, provided the following was set, the users email address would be returned on the callback to ExternalLoginCallback;
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
AppId = "XXX",
AppSecret = "XXX",
Scope = { "email" }
});
However, any app that can only target v2.4 (released 8 July) no longer returns the email address to the ExternalLoginCallback.
I think this may possibly be related to the v2.4 changes as listed here;
Declarative Fields
To try to improve performance on mobile networks,
Nodes and Edges in v2.4 requires that you explicitly request the
field(s) you need for your GET requests. For example, GET
/v2.4/me/feed no longer includes likes and comments by default, but
GET /v2.4/me/feed?fields=comments,likes will return the data. For more
details see the docs on how to request specific fields.
How can I access this email address now?
To resolve this I had to install the Facebook SDK for .NET from nuget and query the email address separately.
In the ExternalLoginCallback method, I added a conditional to populate the email address from the Facebook Graph API;
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// added the following lines
if (loginInfo.Login.LoginProvider == "Facebook")
{
var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
var access_token = identity.FindFirstValue("FacebookAccessToken");
var fb = new FacebookClient(access_token);
dynamic myInfo = fb.Get("/me?fields=email"); // specify the email field
loginInfo.Email = myInfo.email;
}
And to get the FacebookAccessToken I extended ConfigureAuth;
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
AppId = "XXX",
AppSecret = "XXX",
Scope = { "email" },
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
return Task.FromResult(true);
}
}
});
In MVC 6 (Asp.net Core 1.0), by configuring FacebookAuthentication in startup.cs like this:
app.UseFacebookAuthentication(options =>
{
options.AppId = Configuration["Authentication:Facebook:AppId"];
options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
options.Scope.Add("email");
options.UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name";
});
I could get the email. I.e:
var info = await _signInManager.GetExternalLoginInfoAsync();
var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);
How to get user profile image and email ?
I tried to set values but did not get from Extra Data
Here is an example
var fb = new Dictionary<string, object>();
fb["scope"] = "email,user_birthday";
fb ["Gender"] ="gender";
fb["picture"] = "picture";
OAuthWebSecurity.RegisterFacebookClient(
appId: "244501199047737",
appSecret: "48110451420dc5fc0c0a37ade08cdfe7", displayName: "facebook", extraData:fb);
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl}));
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
string email = result.ExtraData["email"];
but can not get user email from
I get error message:
The given key was not present in the dictionary