2012-09-26 20 views
6

फेसबुक के साथ प्रमाणीकरण के लिए नई OAuthWebSecurity का उपयोग करके, मैंने अपने फेसबुक एप्लिकेशन पर ईमेल अनुमति जोड़ा। अब, जैसा कि मैं पढ़ सकता हूं, मुझे परिणाम में वास्तव में ईमेल प्राप्त करने में सक्षम होने के लिए एक दायरा परिभाषित करने की आवश्यकता है। अब तक दायरे के बिना मुझे उपयोगकर्ताओं का ईमेल नहीं मिल रहा है और मुझे यकीन नहीं है कि क्यों मैं नहीं देख सकता कि "दायरा" को परिभाषित करने के लिए कहां जाना है।फेसबुक के साथ OAuthWebSecurity फेसबुक की अनुमति के रूप में ईमेल अनुमति का उपयोग नहीं कर रहा है

यह ASP.NET MVC 4 डिफ़ॉल्ट प्रमाणीकरण नियंत्रक बाहरी लॉगिन का सिर्फ एक चीर है।

+0

शायद यह मदद करता है: http://blogs.msdn.com/b/webdev/archive/2012/08/23/plugging-custom-oauth-openid-providers.aspx – CBroe

उत्तर

0

मुझे यहां एक ही समस्या का सामना करना पड़ा। फेसबुक पर "स्कोप" पैरामीटर पास करने का एकमात्र तरीका मेरे अपने ओथ क्लाइंट को कोडिंग कर रहा था।

ऐसा करने के लिए, आपको DotNetOpenAuth.AspNet.Clients.OAuth2Client के सार विधियों को विस्तार और कार्यान्वित करना होगा।

GetServiceLoginUrl विधि पर आप यूआरएल में स्कोप पैरामीटर जोड़ सकते हैं। तो, जब आप OAuthWebSecurity.VerifyAuthentication() विधि को कॉल करते हैं, तो प्रमाणीकरणResult.UserName उपयोगकर्ता का ईमेल प्रदान करता है।

एक उदाहरण here पाया जा सकता है।

शुभकामनाएं।

+0

ठीक है अब मैंने विधि में एक बार फिर देखा फेसबुक पंजीकृत करने के लिए और इसमें एक अधिभार है जो कुछ अतिरिक्त डेटा पैरामीटर लेता है, लेकिन यह लॉगिन के लिए है? IDictionary fbParams = new Dictionary (); fbParams.Add ("स्कोप", "ईमेल"); OAuthWebSecurity.RegisterFacebookClient ("एककी", "anotherkey", "facebook", fbParams); –

+0

मैंने कोशिश की। लेकिन OAuthWebSecurity अनदेखा किया। आप के लिए काम किया? –

+0

क्या यह विचारशील नहीं होगा ... इस तरह से "अतिरिक्त डेटा" घोषणाओं को सक्षम करने के लिए अपशिष्ट की तरह लगता है। मुझे आश्चर्य है कि इस तरह से ऐसा करने के लिए तर्क क्या था। –

21

सबसे पहले, अतिरिक्त डेटा पैरामीटर फेसबुक को पास नहीं किया गया है। यह केवल आंतरिक उपयोग के लिए है।

http://blogs.msdn.com/b/pranav_rastogi/archive/2012/08/24/customizing-the-login-ui-when-using-oauth-openid.aspx

अब, मांस के लिए:

इसके अलावा तरीकों RegisterFacebookClient, OAuthWebSecurity में RegisterYahooClient आदि करने के लिए, वहाँ भी है पर नीचे दिए गए लिंक इस डेटा का किस अपनी साइट पर इस्तेमाल किया जा सकता देखें एक सामान्य विधि RegisterClient। यह वह तरीका है जिसका हम इस समाधान के लिए उपयोग करेंगे।

यह विचार पर प्रदान की कोड से अंकुरित: http://mvc4beginner.com/Sample-Code/Facebook-Twitter/MVC-4-oAuth-Facebook-Login-EMail-Problem-Solved.html

हालांकि, हम समाधान द्वारा प्रदान की hacky दृष्टिकोण का उपयोग नहीं किया जाएगा। इसके बजाए, हम FacebookScopedClient नामक एक नई कक्षा तैयार करेंगे जो IAuthenticationClient लागू करेगा। फिर हम बस का उपयोग कर वर्ग में दर्ज किए जाएंगे:

OAuthWebSecurity.RegisterClient(new FacebookScopedClient("your_app_id", "your_app_secret"), "Facebook", null); 

AuthConfig.cs

में वर्ग के लिए कोड है:

using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Web; 

    public class FacebookScopedClient : IAuthenticationClient 
     { 
      private string appId; 
      private string appSecret; 

      private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id="; 
      public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?"; 
      public const string graphApiMe = "https://graph.facebook.com/me?"; 


      private static string GetHTML(string URL) 
      { 
       string connectionString = URL; 

       try 
       { 
        System.Net.HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(connectionString); 
        myRequest.Credentials = CredentialCache.DefaultCredentials; 
        //// Get the response 
        WebResponse webResponse = myRequest.GetResponse(); 
        Stream respStream = webResponse.GetResponseStream(); 
        //// 
        StreamReader ioStream = new StreamReader(respStream); 
        string pageContent = ioStream.ReadToEnd(); 
        //// Close streams 
        ioStream.Close(); 
        respStream.Close(); 
        return pageContent; 
       } 
       catch (Exception) 
       { 
       } 
       return null; 
      } 

      private IDictionary<string, string> GetUserData(string accessCode, string redirectURI) 
      { 

       string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode); 
       if (token == null || token == "") 
       { 
        return null; 
       } 
       string data = GetHTML(graphApiMe + "fields=id,name,email,gender,link&access_token=" + token.Substring("access_token=", "&")); 

       // this dictionary must contains 
       Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data); 
       return userData; 
      } 

      public FacebookScopedClient(string appId, string appSecret) 
      { 
       this.appId = appId; 
       this.appSecret = appSecret; 
      } 

      public string ProviderName 
      { 
       get { return "Facebook"; } 
      } 

      public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl) 
      { 
       string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=email"; 
       context.Response.Redirect(url); 
      } 

      public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context) 
      { 
       string code = context.Request.QueryString["code"]; 

       string rawUrl = context.Request.Url.OriginalString; 
       //From this we need to remove code portion 
       rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", ""); 

       IDictionary<string, string> userData = GetUserData(code, rawUrl); 

       if (userData == null) 
        return new AuthenticationResult(false, ProviderName, null, null, null); 

       string id = userData["id"]; 
       string username = userData["email"]; 
       userData.Remove("id"); 
       userData.Remove("email"); 

       AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData); 
       return result; 
      } 
     } 
अब

public ActionResult ExternalLoginCallback(string returnUrl) 

विधि में में

AccountController, result.ExtraData ईमेल होना चाहिए।

संपादित करें: मुझे इस पोस्ट में कुछ कोड याद आया। मैं इसे नीचे जोड़ रहा हूं:

public static class String 
    { 
     public static string Substring(this string str, string StartString, string EndString) 
     { 
      if (str.Contains(StartString)) 
      { 
       int iStart = str.IndexOf(StartString) + StartString.Length; 
       int iEnd = str.IndexOf(EndString, iStart); 
       return str.Substring(iStart, (iEnd - iStart)); 
      } 
      return null; 
     } 
    } 

चीयर्स!

+0

मुझे आपके "टोकन। सब्स्ट्रिंग (" access_token = "," & "))" पंक्ति के साथ कोई समस्या थी, क्योंकि सबस्ट्रिंग केवल पूर्णांक स्वीकार करता है, लेकिन इससे बहुत मदद मिली। मैंने एक ब्लॉग पोस्ट लिखने का फैसला किया कि यह थोड़ा आगे कैसे बढ़ाया जाए, लेकिन इस पोस्ट ने मुझे 98% वहां पहुंचाया। http://savvydev.com/authenticating-facebook-users-with-mvc-4-oauth-and-obtaining-scope-permissions/ – MattSavage

+0

क्षमा करें।स्ट्रिंग के लिए एक्सटेंशन क्लास शामिल करना भूल गए। इसे कोड में जोड़ना ..... –

+0

धन्यवाद, वरुण। मुझे AppHarbor पर होस्ट किए जा रहे ऐप्स के लिए थोड़ा सा झटका लगाना पड़ा (जिसे मैं [एक और उत्तर] में बताता हूं (http://stackoverflow.com/a/14567037/389899)) लेकिन आपने सभी कड़ी मेहनत की। – blachniet

13

अपने एमवीसी 4 इंटरनेट प्रोजेक्ट में अपना NuGet पैकेज अपडेट करें।

डॉटनेट ओपेनऑथकोर। यह स्वचालित रूप से सभी निर्भरताओं को अपडेट करेगा।

अब परिणाम। उपयोगकर्ता नाम में आपके नाम के बजाय ईमेल पता होगा।

[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) 
     { 
      // If the current user is logged in add the new account 
      OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name); 
      return RedirectToLocal(returnUrl); 
     } 
     else 
     { 
      // User is new, ask for their desired membership name 
      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 }); 
     } 
    } 

इसका कारण क्या है?

https://github.com/AArnott/dotnetopenid/blob/a9d2443ee1a35f13c528cce35b5096abae7128f4/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs नवीनतम NuGet पैकेज में अद्यतन किया गया है।

फिक्स के साथ प्रतिबद्ध: https://github.com/AArnott/dotnetopenid/commit/a9d2443ee1a35f13c528cce35b5096abae7128f4

+1

यह बहुत अच्छा है :) बहुत धन्यवाद, जिसने इसे अनुकूलित करने के लिए मुझे समय और प्रयास बचाया, अब इसे बनाया जाना चाहिए क्योंकि यह होना चाहिए;) – Shadi

+0

@PUssInBoots। महान निर्देश। मैंने उनका पीछा किया और मुझे एक ईमेल वापस मिल रहा है, सिवाय इसके कि अब यह '[email protected].facebook.com' है जो मैं चाहता हूं। कोई विचार है कि मुझे यह लंबा proxymail.facebook.com पता क्यों मिल रहा है? – user576838

+0

@ user576838 पहले कभी मेरे ऐप में उस तरह का ईमेल नहीं देखा। शायद किसी अन्य उपयोगकर्ता के साथ किसी अन्य ईमेल प्रदाता से लॉग इन करने का प्रयास करें, देखें कि क्या आपको एक ही परिणाम मिलते हैं। – PussInBoots

2

मैं Varun's answer करते थे, लेकिन मैं इसे अपने अनुप्रयोग के लिए काम करने के लिए AppHarbor पर होस्ट किया जा पाने के लिए एक छोटा सा संशोधन करना था।

ऐपहार्बर लोड संतुलन को संभालने के लिए यूआरएल में बंदरगाह संख्या के साथ कुछ भयानक सामान करना है। आप here के बारे में कुछ और पढ़ सकते हैं। संक्षेप में, ऐपहॉर्बर पर होस्टिंग करते समय वर्तमान अनुरोध का निरपेक्ष यूरी प्राप्त करना 80 से अधिक के पोर्ट नंबर के साथ एक यूरी वापस कर सकता है। इससे फेसबुक प्रमाणीकरण के साथ समस्याएं आती हैं, क्योंकि वे उम्मीद करते हैं कि आपका ऐप बनाने के दौरान आपके रिटर्न यूआरएल को निर्दिष्ट किया जाए।

समस्या VerifyAuthentication() में string rawUrl = context.Request.Url.OriginalString; पर आती है। यदि आप इस कोड का उपयोग करते हैं, तो rawUrl में 80 से अधिक पोर्ट नंबर हो सकते हैं, जिससे फेसबुक प्रमाणीकरण विफल हो जाता है। इसके बजाय,

string rawUrl = GetRawUrl(context.Request.Url); 

साथ कि लाइन की जगह और कक्षा में GetRawUrl() समारोह जोड़ें:

public static string GetRawUrl(Uri url) 
{ 
    var port = url.Port; 
    if (SettingsHelper.GetHostingService() == HostingServices.AppHarbor) 
     port = 80; 

    return new UriBuilder(url) 
    { 
     Port = port 
    }.Uri.AbsoluteUri; 
} 

आप या नहीं, आपके आवेदन AppHarbor पर चल रहा है निर्धारित करने के लिए अपने स्वयं के तर्क के साथ if (SettingsHelper.GetHostingService() == HostingServices.AppHarbor) को प्रतिस्थापित करना होगा ।

-2

यह किया जा सकता है ... इस तरह:

var fb = new Dictionary<string, object>(); 
fb.Add("scope", "email,publish_actions"); 
OAuthWebSecurity.RegisterFacebookClient(
appId: ConfigurationManager.AppSettings["FacebookAppId"], 
appSecret: ConfigurationManager.AppSettings["FacebookAppSecret"], 
displayName: "FaceBook", 
extraData: fb); 
+1

सहायता करें यह बहुत व्यावहारिक लग रहा है। लेकिन यह मेरे लिए काम नहीं किया। – elif

+1

यह काम नहीं करता है। "अतिरिक्त डेटा" पैरामीटर फेसबुक द्वारा भेजा या उपयोग नहीं किया जाता है। –

1

मैं इस समस्या का समाधान अपने ही लिखा था। मैंने OAuth2Client को इसका उपयोग करने के लिए विस्तारित किया और अतिरिक्त उपयोगकर्ता डेटा पुनर्प्राप्त करने के लिए फेसबुक स्कोप और अन्य सुविधाओं का उपयोग किया। मैंने अपना खुद का समाधान here पोस्ट किया, मुझे उम्मीद है कि यह किसी की मदद करेगा!

संबंधित मुद्दे