/// <summary> /// Gets the login uri. /// </summary> /// <param name="parameters"> /// The parameters. /// </param> /// <returns> /// Returns the facebook login uri. /// </returns> /// <remarks> /// http://developers.facebook.com/docs/reference/dialogs/oauth /// Parameters that can be used: /// client_id : Your application's identifier. This is called client_id instead of app_id for this particular method to be compliant with the OAuth 2.0 specification. Required, but automatically specified by most SDKs. /// redirect_uri : The URL to redirect to after the user clicks a button on the dialog. Required, but automatically specified by most SDKs. /// scope : Optional. A comma-delimited list of permissions. /// state : Optional. An opaque string used to maintain application state between the request and callback. When Facebook redirects the user back to your redirect_uri, this value will be included unchanged in the response. /// response_type : Optional, default is token. The requested response: an access token (token), an authorization code (code), or both (code_and_token). /// display : The display mode in which to render the dialog. The default is page on the www subdomain and wap on the m subdomain. This is automatically specified by most SDKs. (For WP7 builds it is set to touch.) /// </remarks> public Uri GetLoginUrl(IDictionary <string, object> parameters) { Contract.Ensures(Contract.Result <Uri>() != null); var defaultParameters = new Dictionary <string, object>(); defaultParameters["client_id"] = AppId; defaultParameters["redirect_uri"] = RedirectUri ?? new Uri("http://www.facebook.com/connect/login_success.html"); #if WINDOWS_PHONE defaultParameters["display"] = "touch"; #endif var mergedParameters = FacebookUtils.Merge(defaultParameters, parameters); // check if client_id and redirect_uri is not null or empty. if (mergedParameters["client_id"] == null || string.IsNullOrEmpty(mergedParameters["client_id"].ToString())) { throw new ArgumentException("client_id required."); } if (mergedParameters["redirect_uri"] == null || string.IsNullOrEmpty(mergedParameters["redirect_uri"].ToString())) { throw new ArgumentException("redirect_uri required."); } // seems like if we don't do this and rather pass the original uri object, // it seems to have http://localhost:80/csharpsamples instead of // http://localhost/csharpsamples // notice the port number, that shouldn't be there. // this seems to happen for iis hosted apps. mergedParameters["redirect_uri"] = mergedParameters["redirect_uri"].ToString(); var url = "http://www.facebook.com/dialog/oauth/?" + FacebookUtils.ToJsonQueryString(mergedParameters); return(new Uri(url)); }
/// <summary> /// Gets the logout url. /// </summary> /// <param name="parameters"> /// The parameters. /// </param> /// <returns> /// Returns the logout url. /// </returns> public Uri GetLogoutUrl(IDictionary <string, object> parameters) { // more information on this at http://stackoverflow.com/questions/2764436/facebook-oauth-logout var uriBuilder = new UriBuilder("http://m.facebook.com/logout.php"); var defaultParams = new Dictionary <string, object>(); defaultParams["confirm"] = 1; defaultParams["next"] = RedirectUri ?? new Uri("http://www.facebook.com"); var mergedParameters = FacebookUtils.Merge(defaultParams, parameters); if (mergedParameters["next"] == null) { mergedParameters.Remove("next"); } else { mergedParameters["next"] = mergedParameters["next"].ToString(); } uriBuilder.Query = FacebookUtils.ToJsonQueryString(mergedParameters); return(uriBuilder.Uri); }
internal protected virtual void ApiAsync(string path, IDictionary <string, object> parameters, HttpMethod httpMethod, object userToken) { var mergedParameters = FacebookUtils.Merge(null, parameters); if (!mergedParameters.ContainsKey("access_token") && !String.IsNullOrEmpty(AccessToken)) { mergedParameters["access_token"] = AccessToken; } Uri requestUrl; string contentType; byte[] postData = BuildRequestData(path, mergedParameters, httpMethod, out requestUrl, out contentType); var tempState = new WebClientStateContainer { UserState = userToken, Method = httpMethod, RequestUri = requestUrl }; Action <string, Exception> callback = (json, ex) => { byte[] result = null; if (ex == null) { result = Encoding.UTF8.GetBytes(json); } if (httpMethod == HttpMethod.Get) { DownloadDataCompleted(this, new DownloadDataCompletedEventArgsWrapper(ex, false, tempState, result)); } else { UploadDataCompleted(this, new UploadDataCompletedEventArgsWrapper(ex, false, tempState, result)); } }; var request = (HttpWebRequest)HttpWebRequest.Create(requestUrl); request.Method = FacebookUtils.ConvertToString(httpMethod); // Set the http method GET, POST, etc. if (httpMethod == HttpMethod.Post) { if (path == null && mergedParameters.ContainsKey("batch")) { tempState.IsBatchRequest = true; } request.ContentType = contentType; request.BeginGetRequestStream((ar) => { RequestCallback(ar, postData, callback, tempState); }, request); } else { request.BeginGetResponse((ar) => { ResponseCallback(ar, callback, tempState); }, request); } }
internal protected virtual object Api(string path, IDictionary <string, object> parameters, HttpMethod httpMethod, Type resultType) { var mergedParameters = FacebookUtils.Merge(null, parameters); if (!mergedParameters.ContainsKey("access_token") && !string.IsNullOrEmpty(AccessToken)) { mergedParameters["access_token"] = AccessToken; } Uri requestUrl; string contentType; byte[] postData = BuildRequestData(path, mergedParameters, httpMethod, out requestUrl, out contentType); var jsonString = MakeRequest(httpMethod, requestUrl, postData, contentType); var json = JsonSerializer.Current.DeserializeObject(jsonString); FacebookApiException facebookApiException = ExceptionFactory.GetGraphException(json) ?? ExceptionFactory.CheckForRestException(DomainMaps, requestUrl, json); if (facebookApiException != null) { throw facebookApiException; } return(resultType == null ? json : JsonSerializer.Current.DeserializeObject(jsonString, resultType)); }
/// <summary> /// Internal method for parsing the Facebook oauth ur.. /// </summary> /// <param name="uri"> /// The url to parse. /// </param> /// <param name="throws"> /// Whether to throw the exception or not incase an error occurs. /// </param> /// <returns> /// The <see cref="FacebookOAuthResult"/>. /// </returns> /// <exception cref="InvalidOperationException"> /// Throws if cannot parse the specified url. /// </exception> private static FacebookOAuthResult Parse(Uri uri, bool throws) { IDictionary <string, object> parameters = null; try { bool found = false; if (!string.IsNullOrEmpty(uri.Fragment)) { // #access_token and expires_in are in fragment var fragment = uri.Fragment.Substring(1); parameters = FacebookUtils.ParseUrlQueryString(fragment); if (parameters.ContainsKey("access_token")) { found = true; } } // code, state, error_reason, error and error_description are in query // ?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request. var queryPart = FacebookUtils.ParseUrlQueryString(uri.Query); if (queryPart.ContainsKey("code") || (queryPart.ContainsKey("error") && queryPart.ContainsKey("error_description"))) { found = true; } if (found) { parameters = FacebookUtils.Merge(parameters, queryPart); return(new FacebookOAuthResult(parameters)); } } catch { if (throws) { throw; } return(null); } if (throws) { throw new InvalidOperationException("Could not parse authentication url."); } return(null); }
/// <summary> /// Gets the login url. /// </summary> /// <param name="parameters"> /// The parameters. /// </param> /// <returns> /// Returns the Facebook login url. /// </returns> /// <remarks> /// http://developers.facebook.com/docs/reference/dialogs/oauth /// Parameters that can be used: /// client_id : Your application's identifier. This is called client_id instead of app_id for this particular method to be compliant with the OAuth 2.0 specification. Required, but automatically specified by most SDKs. /// redirect_uri : The URL to redirect to after the user clicks a button on the dialog. Required, but automatically specified by most SDKs. /// scope : Optional. A comma-delimited list of permissions. /// state : Optional. An opaque string used to maintain application state between the request and callback. When Facebook redirects the user back to your redirect_uri, this value will be included unchanged in the response. /// response_type : Optional, default is token. The requested response: an access token (token), an authorization code (code), or both (code token). /// display : The display mode in which to render the dialog. The default is page on the www subdomain and wap on the m subdomain. This is automatically specified by most SDKs. (For WP7 builds it is set to touch.) /// </remarks> public virtual Uri GetLoginUrl(IDictionary <string, object> parameters) { var defaultParameters = new Dictionary <string, object>(); defaultParameters["client_id"] = AppId; defaultParameters["redirect_uri"] = RedirectUri ?? new Uri("http://www.facebook.com/connect/login_success.html"); #if WINDOWS_PHONE defaultParameters["display"] = "touch"; #endif var mergedParameters = FacebookUtils.Merge(defaultParameters, parameters); // check if client_id and redirect_uri is not null or empty. if (mergedParameters["client_id"] == null || string.IsNullOrEmpty(mergedParameters["client_id"].ToString())) { throw new ArgumentException("client_id required."); } if (mergedParameters["redirect_uri"] == null || string.IsNullOrEmpty(mergedParameters["redirect_uri"].ToString())) { throw new ArgumentException("redirect_uri required."); } // seems like if we don't do this and rather pass the original uri object, // it seems to have http://localhost:80/csharpsamples instead of // http://localhost/csharpsamples // notice the port number, that shouldn't be there. // this seems to happen for iis hosted apps. mergedParameters["redirect_uri"] = mergedParameters["redirect_uri"].ToString(); var url = "http://www.facebook.com/dialog/oauth/?" + FacebookUtils.ToJsonQueryString(mergedParameters); // In order to be compliant with the OAuth spec Facebook have made changes to their auth APIs. // As part of this update, they will be deprecating 'code_and_token' and need developers // to use 'code%20token'. Everything is identical, just replace '_and_' with encoded // <space> '%20'. // url = url.Replace("response_type=code+token", "response_type=code%20token"); return(new Uri(url)); }
/// <summary> /// Converts the facebook batch to POST parameters. /// </summary> /// <param name="batchParameter"> /// The batch parameter. /// </param> /// <returns> /// The post parameters. /// </returns> protected IDictionary <string, object> ToParameters(FacebookBatchParameter batchParameter) { Contract.Requires(batchParameter != null); Contract.Ensures(Contract.Result <IDictionary <string, object> >() != null); IDictionary <string, object> returnResult = null; var defaultParameters = new Dictionary <string, object>(); defaultParameters["method"] = FacebookUtils.ConvertToString(batchParameter.HttpMethod); IDictionary <string, object> parameters = null; if (batchParameter.Parameters == null) { parameters = new Dictionary <string, object>(); } else { if (batchParameter.Parameters is IDictionary <string, object> ) { parameters = (IDictionary <string, object>)batchParameter.Parameters; } else { parameters = FacebookUtils.ToDictionary(batchParameter.Parameters); } } var path = FacebookUtils.ParseQueryParametersToDictionary(batchParameter.Path, parameters); string queryString = string.Empty; if (batchParameter.HttpMethod == HttpMethod.Get) { queryString = FacebookUtils.ToJsonQueryString(parameters); } else { defaultParameters["body"] = FacebookUtils.ToJsonQueryString(parameters); } var relativeUrl = new StringBuilder(path); if (!string.IsNullOrEmpty(queryString)) { relativeUrl.AppendFormat("?{0}", queryString); } defaultParameters["relative_url"] = relativeUrl.ToString(); var data = batchParameter.Data; if (data == null) { returnResult = defaultParameters; } else { if (!(data is IDictionary <string, object>)) { data = FacebookUtils.ToDictionary(batchParameter.Data); } returnResult = FacebookUtils.Merge(defaultParameters, (IDictionary <string, object>)data); } return(returnResult); }