Después de perder el tiempo con una actualización de DotNetOpenAuth por un largo tiempo y sin experimentar ninguna suerte al conectarme a Facebook, también armé un código para admitir el inicio de sesión de Facebook desde mi aplicación ASP.NET MVC.
En primer lugar, un código como este debe ir en un controlador en alguna parte.
// You call this action to initiate the process with Facebook
public ActionResult FacebookLogIn()
{
return CreateFacebookClient().RequestAuthorisation();
}
// Facebook will call you back here
public ActionResult FacebookAuthorisationResponse()
{
var facebookClient = CreateFacebookClient();
var authorisationResponse = facebookClient.HandleAuthorisationResponse();
if (authorisationResponse.IsSuccess)
{
var accessToken = authorisationResponse.AccessToken;
// TODO do whatever you want to do with your access token here
return Redirect("SomeUrl");
}
// TODO handle the error somehow
return Content(authorisationResponse.ErrorMessage);
}
private FacebookClient CreateFacebookClient()
{
const string clientId = "xxxxxxxxxxxxxxx";
const string appSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var redirectUrl = Url.Action("FacebookAuthorisationResponse", null, null, "http");
return new FacebookClient(clientId, appSecret, redirectUrl);
}
Eso es prácticamente todo lo que tiene que hacer con su código. Una vez que tiene ese token de acceso, puede hacer cosas como esta:
// Get basic information for this user
var basicInfoUrl = string.Format("https://graph.facebook.com/me?access_token={0}", Uri.EscapeDataString(accessToken.TokenString));
var json = new WebClient().DownloadString(basicInfoUrl);
Aquí está el código que admite las cosas relativamente simples de arriba. Usted sólo puede volcar todo esto en un archivo en el proyecto:
// Drew Noakes, http://drewnoakes.com
// Created 08/08/2012 22:41
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace DrewNoakes.Facebook.Mvc
{
public sealed class FacebookClient
{
private readonly string _clientId;
private readonly string _appSecret;
private readonly string _authorisationResponseUrl;
public IFacebookClientStateManager StateManager { get; set; }
public FacebookClient(string clientId, string appSecret, string authorisationResponseUrl)
{
_clientId = clientId;
_appSecret = appSecret;
_authorisationResponseUrl = authorisationResponseUrl;
StateManager = MemoryStateManager.Instance;
}
public ActionResult RequestAuthorisation(string[] permissions = null)
{
// First step is to redirect the visitor's browser to Facebook
var state = StateManager.GetState();
var url = string.Format("https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri={1}&scope={2}&state={3}",
_clientId, Uri.EscapeDataString(_authorisationResponseUrl), permissions == null ? string.Empty : string.Join(",", permissions), state);
return new RedirectResult(url, permanent: false);
}
public AuthorisationResponse HandleAuthorisationResponse()
{
var queryString = HttpContext.Current.Request.QueryString;
// Ensure returned state is expected
if (!StateManager.IsValidState(queryString["state"]))
return AuthorisationResponse.Error("Invalid state");
// TODO handle case where user declined: YOUR_REDIRECT_URI?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request.&state=YOUR_STATE_VALUE
var code = queryString["code"];
var url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&code={3}&client_secret={2}",
_clientId, Uri.EscapeDataString(_authorisationResponseUrl), _appSecret, Uri.EscapeDataString(code));
var client = new WebClient { Proxy = null };
var responseBody = client.DownloadString(url);
// HTTP 200: access_token=USER_ACCESS_TOKEN&expires=NUMBER_OF_SECONDS_UNTIL_TOKEN_EXPIRES
// HTTP 400: TODO handle JSON error reponse: { "error": { "type": "OAuthException", "message": "Error validating verification code." } }
var response = HttpUtility.ParseQueryString(responseBody);
var accessToken = response["access_token"];
var expiresSecondsString = response["expires"];
int expiresSeconds;
if (!int.TryParse(expiresSecondsString, out expiresSeconds))
return AuthorisationResponse.Error("Unable to parse expiration time");
var expiresAtUtc = DateTime.UtcNow.AddSeconds(expiresSeconds);
return AuthorisationResponse.Success(accessToken, expiresAtUtc);
}
}
public class AuthorisationResponse
{
public bool IsSuccess { get; private set; }
public AccessToken AccessToken { get; private set; }
public string ErrorMessage { get; private set; }
private AuthorisationResponse() { }
public static AuthorisationResponse Error(string errorMessage)
{
return new AuthorisationResponse { IsSuccess = false, ErrorMessage = errorMessage };
}
public static AuthorisationResponse Success(string accessToken, DateTime expiresAtUtc)
{
return new AuthorisationResponse { IsSuccess = true, AccessToken = new AccessToken(accessToken, expiresAtUtc) };
}
}
public struct AccessToken
{
public string TokenString { get; private set; }
public DateTime ExpiresAtUtc { get; private set; }
public AccessToken(string tokenString, DateTime expiresAtUtc)
: this()
{
if (tokenString == null)
throw new ArgumentNullException("tokenString");
TokenString = tokenString;
ExpiresAtUtc = expiresAtUtc;
}
}
public interface IFacebookClientStateManager
{
string GetState();
bool IsValidState(string state);
}
/// <summary>
/// The default implementation of <see cref="IFacebookClientStateManager"/>.
/// </summary>
public sealed class MemoryStateManager : IFacebookClientStateManager
{
private static readonly IFacebookClientStateManager _instance = new MemoryStateManager();
public static IFacebookClientStateManager Instance
{
get { return _instance; }
}
private readonly Dictionary<string, DateTime> _stateTimes = new Dictionary<string, DateTime>();
public string GetState()
{
var state = Guid.NewGuid().ToString("N");
_stateTimes[state] = DateTime.UtcNow;
return state;
}
public bool IsValidState(string state)
{
var isValid = _stateTimes.Remove(state);
// Remove any keys that have not been accessed within a given period
var staleKeys = _stateTimes.Where(pair => pair.Value < DateTime.UtcNow.AddMinutes(-30)).Select(pair => pair.Key).ToList();
foreach (var staleKey in staleKeys)
_stateTimes.Remove(staleKey);
return isValid;
}
}
}
me tiró juntos rápidamente esta noche, pero va a volver más tarde y el parche si encuentro problemas. Sin embargo, está funcionando realmente bien en mi sitio ahora.
Hay un par de TODO relacionados con el manejo robusto de la respuesta de error.
¿Dónde puedo obtener 'ClientIdentifier =" xxxxxxxxxxxxxxxxxxxxxxxx "; Secret =" xxxxxxxxxxxx "; LocalSubDomain =" local.xxxxxxx.com ";' values from? – capdragon
@capdragon: Google "facebook api key" y prueba una de las guías, como [this one] (http://help.webscribble.com/display/jconnector/Getting+the+Facebook+Connect+API+Key) . – Iain
¡El código bueno funciona para mí! Puede necesitar solicitar permiso de correo electrónico explícitamente para su aplicación de Facebook, en ese caso debe agregar "& scope = email" a su llamada de punto final de autorización, así: if (needToGetVerificationCode) { var url = AuthorizationEndpoint + "? " + "client_id =" + ClientIdentifier + "&" + "redirect_uri =" + redirectUrl + "&" + "scope = email"; HttpContext.Current.Response.Redirect (url); return FacebookAuthorisationResult.RequestingCode; } – HOKBONG