But the problem is extended permission or userpermission is required. Facebook oAuth doesnot pass scope=email as the paramter in the popup dialog that asks for extended permissions .
Solution is to use the graph API and write your own code. or modify the existing code. This is what i have done.
//return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
string code = Request.QueryString["code"];
string id = "facebook";
//AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
IDictionary<string, string> userData = GetUserData(code);
AuthenticationResult result = new AuthenticationResult(isSuccessful: true, provider: "facebook", providerUserId: userData["id"], userName: userData["username"], extraData: userData);
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
The above method works for me. But I am still writing the code. I will update the code sample when I am done. in my website
I dug through the DotNetOpenAuth source and it appears to be looking for lowercase entries in this dictionary. I was able to get past the error by changing this section of the GetUserData() method (I also added username):
var rtnval = new Dictionary<string, string> {
{
"username",
data.username
},
{
"id",
data.id
},
{
"name",
data.name
},
cemelma
Member
5 Points
37 Posts
[Urgent] How can I get ExtraData from OAuthWebSecurity?
Oct 01, 2012 12:43 PM|LINK
AuthConfig.cs in definition;
OAuthWebSecurity.RegisterFacebookClient(
appId: "21703538......",
appSecret: "28cbbc965e8ff6c9dc57.........");
ExternalLoginCallback function in, OAuthWebSecurity.VerifyAuthentication returned results (name,link,gender). But i need email address.
How can i get email address from facebook ?
Waiting for answers...
cemelma
Member
5 Points
37 Posts
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Oct 01, 2012 07:32 PM|LINK
Does not anyone know?
BrockAllen
All-Star
28084 Points
4997 Posts
MVP
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Oct 01, 2012 08:12 PM|LINK
http://brockallen.com/2012/09/04/using-oauthwebsecurity-without-simplemembership/
http://brockallen.com/2012/09/05/integrating-claims-and-oauthwebsecurity/
DevelopMentor | http://www.develop.com
thinktecture | http://www.thinktecture.com/
murugan_ad
Member
301 Points
61 Posts
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Oct 04, 2012 07:54 PM|LINK
By default oAuth for facebook takes email in the username field
The code from oAuth is given below for facebook
var userData =newDictionary<string,string>();userData.AddItemIfNotEmpty("id", graphData.Id);userData.AddItemIfNotEmpty("username", graphData.Email);userData.AddItemIfNotEmpty("name", graphData.Name);userData.AddItemIfNotEmpty("link", graphData.Link ==null?null: graphData.Link.AbsoluteUri);userData.AddItemIfNotEmpty("gender", graphData.Gender);userData.AddItemIfNotEmpty("birthday", graphData.Birthday);returnuserDataBut the problem is extended permission or userpermission is required. Facebook oAuth doesnot pass scope=email as the paramter in the popup dialog that asks for extended permissions .
Solution is to use the graph API and write your own code. or modify the existing code. This is what i have done.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
return Redirect("https://www.facebook.com/dialog/oauth?client_id=YOUR CLIENT ID&redirect_uri=http%3A%2F%2Flocalhost%3A50411%2FAccount%2FExternalLoginCallback%3F__provider__%3Dfacebook&scope=email");
//return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
string code = Request.QueryString["code"];
string id = "facebook";
//AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
IDictionary<string, string> userData = GetUserData(code);
AuthenticationResult result = new AuthenticationResult(isSuccessful: true, provider: "facebook", providerUserId: userData["id"], userName: userData["username"], extraData: userData);
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
The above method works for me. But I am still writing the code. I will update the code sample when I am done. in my website
http://mvc4beginner.com/Sample-Code/Facebook-Twitter/MVC-4-oAuth-Facebook-Login-EMail-Problem-Solved.html
EMail : murugan@muruganad.com
www.mvc4beginner.com
SoyUnEmilio
Member
2 Points
1 Post
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Oct 10, 2012 04:12 AM|LINK
Hi you should extend facebook client because I belieive default client doesn't have this functionallity:
public class MyFacebookClient : DotNetOpenAuth.AspNet.Clients.OAuth2Client { private const string AuthorizationEP = "https://www.facebook.com/dialog/oauth"; private const string TokenEP = "https://graph.facebook.com/oauth/access_token"; private readonly string _appId; private readonly string _appSecret; public MyFacebookClient(string appId, string appSecret) : base("myfacebook") { this._appId = appId; this._appSecret = appSecret; } protected override Uri GetServiceLoginUrl(Uri returnUrl) { return new Uri( AuthorizationEP + "?client_id=" + this._appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=email,user_about_me" + "&display=page" ); } protected override IDictionary<string, string> GetUserData(string accessToken) { WebClient client = new WebClient(); string content = client.DownloadString( "https://graph.facebook.com/me?access_token=" + accessToken ); dynamic data = Json.Decode(content); return new Dictionary<string, string> { { "Id", data.id }, { "Name", data.name }, { "Photo", "https://graph.facebook.com/" + data.id + "/picture" }, { "Email", data.email } }; } protected override string QueryAccessToken(Uri returnUrl, string authorizationCode) { WebClient client = new WebClient(); string content = client.DownloadString( TokenEP + "?client_id=" + this._appId + "&client_secret=" + this._appSecret + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&code=" + authorizationCode ); NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(content); if (nameValueCollection != null) { string result = nameValueCollection["access_token"]; return result; } return null; } }Look at GetServiceLoginUrl scope is something like permissions (reference http://developers.facebook.com/docs/authentication/permissions/) you can specify scope=email,user_about_me so you will have profile of the user and email permissions.
You should register MyFacebookClient in AuthConfig.cs
OAuthWebSecurity.RegisterClient( new MyFacebookClient( appId: "xxxxxxxxxx", appSecret: "xxxxxxxxxxxxxxxx"), "MyFacebook", null );If you want to save email in the profile user you should modify UserProfile in AccountModels:
[Table("UserProfile")] public class UserProfile { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string UserName { get; set; } public string Email { get; set; } public string Photo { get; set; } }With this you will write your UserProfile with the data you want to store.
In AccountController:
[AllowAnonymous] public ActionResult ExternalLoginCallback(string returnUrl) { AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl })); if (!result.IsSuccessful) { return RedirectToAction("ExternalLoginFailure"); } if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false)) { return RedirectToLocal(returnUrl); } if (User.Identity.IsAuthenticated) { // Si el usuario actual ha iniciado sesión, agregue la cuenta nueva OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name); return RedirectToLocal(returnUrl); } else { // El usuario es nuevo, solicitar nombres de pertenencia deseados string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId); ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName; ViewBag.ReturnUrl = returnUrl; return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData }); } }result have the ExtraData: result.ExtraData you should persist it.
Derix
Member
2 Points
1 Post
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Nov 26, 2012 06:59 AM|LINK
Thanks. I tried this and im getting exception:
[KeyNotFoundException: The given key was not present in the dictionary.] System.Collections.Generic.Dictionary`2.get_Item(TKey key) +10678889 DotNetOpenAuth.AspNet.Clients.OAuth2Client.VerifyAuthentication(HttpContextBase context, Uri returnPageUrl) +240 DotNetOpenAuth.AspNet.OpenAuthSecurityManager.VerifyAuthentication(String returnUrl) +239 Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.VerifyAuthenticationCore(HttpContextBase context, String returnUrl) +129 Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.VerifyAuthentication(String returnUrl) +86 PandaTag.Controllers.AccountController.ExternalLoginCallback(String returnUrl) in d:\CDP_Backup\CDP_Backup\Mynice\ISS\QRCProject\Web\PandaTag\PandaTag\Controllers\AccountController.cs:451 lambda_method(Closure , ControllerBase , Object[] ) +104 System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +182 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27 System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +28 System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +10 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32 System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +58 System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +225 System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +225 System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +225 System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +10 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34 System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +24 System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +99 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27 System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +14 System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39 System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10 System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +25 System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +31 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9629708 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
JRdotNet
Member
17 Points
4 Posts
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Nov 28, 2012 05:58 AM|LINK
I dug through the DotNetOpenAuth source and it appears to be looking for lowercase entries in this dictionary. I was able to get past the error by changing this section of the GetUserData() method (I also added username):
var rtnval = new Dictionary<string, string> { { "username", data.username }, { "id", data.id }, { "name", data.name },abecommis
Member
8 Points
4 Posts
Re: [Urgent] How can I get ExtraData from OAuthWebSecurity?
Dec 29, 2012 04:59 AM|LINK
The developer(s) of this package has made an update already to gain access to the user's email address. Now, the
is producing email address.
On your Package Manager Console, type:
to update your DotNetOpenAuth package. Build the solution, then restart to apply all the changes. Run your application and it works.