I'm developing a Facebook app, and i only want to allow access to certain views if the visitor is authorized through Facebook. This should be a pretty simple task, and i thought is was, until i tried it out in IE. The following code works fine in Chrome and Safari. I want to use Forms authentication, and therefore i have set
<forms loginUrl="~/Account/Login" timeout="2880" />
in web.config. This will direct the visitor to the following ActionResult when entering my app:
public ActionResult Login(string returnUrl)
{
ManagerGame2.Utilities.StaticDataContent.InitStaticData();
var oAuthClient = new FacebookOAuthClient();
oAuthClient.AppId = FacebookApplication.Current.AppId;
oAuthClient.RedirectUri = new Uri(redirectUrl);
var loginUri = oAuthClient.GetLoginUrl(new Dictionary<string, object> { { "state", returnUrl } });
return Redirect(loginUri.AbsoluteUri);
}
Then the user is redirected to a Facebook page, and an access token is sent back into my OAuth ActionResult:
public ActionResult OAuth(string code, string state)
{
FacebookOAuthResult oauthResult;
if (FacebookOAuthResult.TryParse(Request.Url, out oauthResult))
{
if (oauthResult.IsSuccess)
{
var oAuthClient = new FacebookOAuthClient();
oAuthClient.AppId = FacebookApplication.Current.AppId;
oAuthClient.AppSecret = FacebookApplication.Current.AppSecret;
oAuthClient.RedirectUri = new Uri(redirectUrl);
dynamic tokenResult = oAuthClient.ExchangeCodeForAccessToken(code);
string accessToken = tokenResult.access_token;
DateTime expiresOn = DateTime.MaxValue;
if (tokenResult.ContainsKey("expires"))
{
DateTimeConvertor.FromUnixTime(tokenResult.expires);
}
FacebookClient fbClient = new FacebookClient(accessToken);
dynamic me = fbClient.Get("me?fields=id,name");
long facebookID = Convert.ToInt64(me.id);
Account acc = (from x in db.Account.OfType<Account>() where x.FaceBookID == facebookID select x).FirstOrDefault();
if (acc == null)
{
acc = CreateAccount(me);
}
acc.LatestLogin = DateTime.Now;
db.Entry(acc).State = EntityState.Modified;
db.SaveChanges();
MemoryUserStore.CurrentAccount = acc;
UserRoleProvider usp = new UserRoleProvider();
usp.GetRolesForUser(acc.AccountID.ToString());
FormsAuthentication.SetAuthCookie(acc.AccountID.ToString(), false);
if (Url.IsLocalUrl(state))
{
return Redirect(state);
}
return RedirectToAction("Details", "Account", new { id = acc.AccountID });
}
}
return RedirectToAction("Index", "Account");
}
What i am trying to do here, is to first verify if the token i get b开发者_运维技巧ack from the redirect is valid. If it is, then i pull some data about the visitor, like FacebookID and Name. I then match it with my database, to see if the user already exists, and if not, i create one. I also assign a role for the user in my custom Role provider, but i had the infinite loop problem before this. Then i set
FormsAuthentication.SetAuthCookie(acc.AccountID.ToString(), false);
and i assume this is the core of keeping track of wheter a visitor is authorized or not. As far as i understand, when the visitor is trying to call a ActionResult that requires [Authorize] then the system will check for this cookie.
Well, could someone please clarify why the above code is working in Chrome/Safari, but keeps looping through Login and then OAuth infinitely in IE?
My app is using MVC 3, EF Code First and Facebook C# SDK 5.0.25
Okay, so i figured out that the problem was triggered by the [Authorize] annotation, as expected. The Facebook SDK has a [CanvasAuthorize] annotation, and when i switch to using this, IE works fine and does not login forever.
Before this, i tried using cookieless authentication, but IE still didn't want to play along.
As far as i have figured out, the problem occurs because Facebook apps are inside an IFrame. This supposedly screws something up with cookies and trust. If someone knows why this is, i would appreciate to hear about it.
Also, if anyone knows how to use and maintain roles, easily, with this [CanvasAuthorize], i would be glad to know.
I know this seems obvious but are you sure cookies aren't disabled in IE? There is an option to disable cookies in developer tools.
精彩评论