All,
I am a beginner in Facebook programming. My test project is a simple website which displays Facebook account information (only name and id) and the list of albums of that Facebook account. The problem is, after authentication, I can get the profile data, but I cannot get the album list.
Here is code to get the profile information:
[FacebookAuthorize(LoginUrl = "~/Account/Login")]
public ActionResult Profile()
{
var fbWebContext = FacebookWebContext.Current;
if (fbWebContext.IsAuthorized())
{
try
{
var fb = new FacebookWebClient(fbWebContext);
var token = fb.AccessToken;
dynamic me = fb.Get("/me");
ViewBag.Name = me.name;
ViewBag.Id = me.id;
ViewBag.AccessToken = token;
}
catch (Exception ex)
{
{
fbWebContext.DeleteAuthCookie();
Session.Clear();
}
return RedirectToAction("Login", "Account");
}
}
return View();
}
and here is code to get the album list
[FacebookAuthorize(LoginUrl = "~/Account/Login")]
public ActionResult Album()
{
var fb = new FacebookWebClient(FacebookWebContext.Current);
IDictionary<string, object> albums = fb.Get("me/albums") as IDictionary<string, object>;
dynamic albumList = albums["data"];
foreach (dynamic albumInfo in albumList)
{
if (ViewBag.Albums == null)
ViewBag.Albums = new List<string>();
ViewBag.Albums.Add(albumInfo.id);
}
return View();
}
in above code, the item count of albumList always = 0.
Could you please help me to resolve this issue?
A minor note: my test website is a ASP.Net MVC3 web application written in C#.
Edit in response to Andy's answer:
In fact, I set lots of permissions but it still cannot get the album list. Here is code in my OAuth method.
var parameters = new Dictionary<string, object>();
parameters.Add("permissions", "user_about_me,offline_access,user_photos,publish_stream");
dynamic tokenResult = oAuthClient.ExchangeCodeForAccessToken(code, parameters);
Note that I did try to replace ""permissions" by "scope" but still failed.
Have you requested the user_photos permission? You need to request additional permissions during Authentication if you want to access additional user data.
See this Facebook permissions page for more info.
If you are using the Facebook JavaScript SDK FB.login method then you can simply add the user_photos permission to the perms option:
FB.login(function(response) {
if (response.session) {
if (response.perms) {
// user is logged in and granted some permissions.
// perms is a comma separated list of granted permissions
} else {
// user is logged in, but did not grant any permissions
}
} else {
// user is not logged in
}
}, {perms:'user_photos'});
Hope this helps.
Related
I'm using Azure AD Free Edition. I'm trying to get all groups of the user that logged in and for that I'm using some examples:
One of them is
foreach (IdentityReference group in System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups)
{
groups.Add(group.Translate(typeof(NTAccount)).ToString());
}
But with this I have this error:
namespace name 'HttpContext' does not existe in the namespace 'System.web'.
I tried adding the reference in my project but it does not appear in the list, so I assume it was added when I created the project.
Also this:
string username = User.FindFirst("name")?.Value;
List<string> result = new List<string>();
WindowsIdentity wi = new WindowsIdentity(username);
foreach (IdentityReference group in wi.Groups)
{
try
{
result.Add(group.Translate(typeof(NTAccount)).ToString());
}
catch (Exception ex) { }
}
result.Sort();
groups = result;
System.Collections.Generic.List`1[System.String]
This:
var g = User.Claims.Where(c => c.Type == "groups").ToList();
foreach(var nom in g){
grup += nom + " - ";
}
Exception: Windows Principal functionality is not supported on this platform.
I saw that in _LoginPartial (the view that is created by default when you assign Microsoft as Login Authentication) has #User.FindFirst("name")?.Value, that bring the username. I tried something like that but with failure #User.FindFirst("groups")?.Value.
I've been days trying this and I'm unable to do it. I read the Azure documentation and even the Microsoft gives us but is doesn´t help.
Update:
Also, I tried Adding a Policy:
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
options.AddPolicy("Policy-Name", p =>
{
p.RequireClaim("groups", "XXXX");
});
});
And in the controller I add the Authorize
[Authorize("Policy-Name")]
public IActionResult Index()
{
return View();
}
But intead of showing the view, I have the Access Denied message:
I don't know how to resolve this....
Edit:
I used some Loggers to finde where I have the error and I have this:
Authorization_RequestDenied Insufficient privileges to complete the operation. azure ad asp.net
The problem is that I configured all what I need in Azure to avoid this problem but I still have it
I am using TweetSharp to send tweets to users (currently testing it) however it keeps coming back with Bad Authentication Data
{"errors":[{"code":215,"message":"Bad Authentication data."}]}
I have checked my app settings and it has full read and write access. I have also tried to regenerate my consumer keys but still not luck.
here is my code
public ActionResult AccessToken()
{
string oauth_consumer_key = "<consumer key>";
string oauth_consumer_secret = "<consumer secret>";
var service = new TwitterService(oauth_consumer_key, oauth_consumer_secret);
// Now we need the Token and TokenSecret
OAuthRequestToken requestToken = service.GetRequestToken("http://localhost:37808/");
string authURL = service.GetAuthorizationUri(requestToken).ToString();
Process.Start(authURL);
SendTweetOptions options = new SendTweetOptions();
options.Status = "Hello there Twitter";
service.SendTweet(options);
var re = service.Response.Response;
return View();
}
Am I doing anything wrong?
Finally solved the issue and it works well. Based upon comments from Yort.
public ActionResult AccessToken()
{
// Step 1 - Retrieve an OAuth Request Token
TwitterService service = new TwitterService(ConfigurationManager.AppSettings["TwitterConsumerKey"], ConfigurationManager.AppSettings["TwitterConsumerSecret"]);
// This is the registered callback URL
OAuthRequestToken requestToken = service.GetRequestToken("http://localhost:37808/Twitter/OToken");
// Step 2 - Redirect to the OAuth Authorization URL
Uri uri = service.GetAuthorizationUri(requestToken);
return new RedirectResult(uri.ToString(), false /*permanent*/);
//return View();
}
public ActionResult OToken()
{
return View();
}
public ActionResult UserInfo(string oauth_token, string oauth_verifier)
{
var requestToken = new OAuthRequestToken { Token = oauth_token };
// Step 3 - Exchange the Request Token for an Access Token
TwitterService service = new TwitterService(ConfigurationManager.AppSettings["TwitterConsumerKey"],
ConfigurationManager.AppSettings["TwitterConsumerSecret"]);
OAuthAccessToken accessToken = service.GetAccessToken(requestToken, oauth_verifier);
// Step 4 - User authenticates using the Access Token
service.AuthenticateWith(accessToken.Token, accessToken.TokenSecret);
TwitterUser user = service.VerifyCredentials(new VerifyCredentialsOptions());
ViewBag.Message = string.Format("{0}", user.ScreenName);
// Step 5 - Send Tweet to User TimeLine
SendTweetOptions options = new SendTweetOptions();
string URL = "file:\\C:\\Users\\<User>\\Desktop\\test.jpg";
string path = new Uri(URL).LocalPath;
// Sending with Media
using (var stream = new FileStream(path, FileMode.Open))
{
service.SendTweetWithMedia(new SendTweetWithMediaOptions
{
Status = "<status>",
Images = new Dictionary<string, Stream> { { path, stream } }
});
}
var responseText = service.Response.StatusCode;
if (responseText.ToString() == "OK")
{
ViewBag.Message = "Tweet Successful";
}
else
{
ViewBag.Message = "Tweet Unsuccessful";
}
return View();
}
}
I don't believe you can send Tweets as just a consumer, the Tweets have to be "owned" by a user account. You need to register a Twitter account, then do the full oauth authentication process to get an access token (in addition to the consumer token), then reauthorise the TweetSharp service using both tokens.
Your code above nearly gets there (I think). After the Process.start call there needs to be logic to use the verifier returned in the browser (a number displayed after the user logs in) to complete the auth process and act as that user. At the moment, your code gets half way through that process but does not complete it, so when you try to tweet your TweetSharp service is only authed as the app and not the user.
The originalTweetSharp readme.md does include the missing bits of code. Step 3 needs the actual verifier returned in the browser after login:
// Step 3 - Exchange the Request Token for an Access Token
string verifier = "123456"; // <-- This is input into your application by your user
OAuthAccessToken access = service.GetAccessToken(requestToken, verifier);
// Step 4 - User authenticates using the Access Token
service.AuthenticateWith(access.Token, access.TokenSecret);
//Now your tweet call should work here.
It also looks like you're doing this in a web app on the server? In which case you're using entirely the wrong oauth flow (I believe). This one is designed for desktop apps, hence the call that starts a new browser process for the user to login with. I'm not entirely sure how the web flow works as I've never used it, but I believe you need to redirect the user to the authorisation url you receive, and the callback registered with Twitter should point back to your site. I think there is some kind of state parameter that can be passed back through the oauth flow so you can implement your own logic to pickup where you left off based on a session id or similar.
I worked on this subject before. You have to developer account before the send tweet because you need tokens and keys. It's my windows service project.
I wrote my tokens and key codes in App.config
<appSettings>
<add key="twitterAccessToken" value="*****"/>
<add key="twitterAccessTokenSecret" value="*****"/>
<add key="twitterConsumerKey" value="*****"/>
<add key="twitterConsumerSecret" value="*****"/>
public static void SendTweet()
{
try
{
GetPixelImageFile();
string key = ConfigurationSettings.AppSettings.Get("twitterConsumerKey");
string secret = ConfigurationSettings.AppSettings.Get("twitterConsumerSecret");
string token = ConfigurationSettings.AppSettings.Get("twitterAccessToken");
string tokenSecret = ConfigurationSettings.AppSettings.Get("twitterAccessTokenSecret");
string message = "Color, Colorful, Pixel, Art, PixelColouring, Follow";
var service = new TweetSharp.TwitterService(key, secret);
service.AuthenticateWith(token, tokenSecret);
using (var stream = new FileStream(#"C:\Images\Pixel.png", FileMode.Open))
{
var result = service.SendTweetWithMedia(new SendTweetWithMediaOptions
{
Status = message,
Images = new Dictionary<string, Stream> { { "john", stream } }
});
SendMail("SendTweet", (result == null ? "" : result.Text));
}
}
catch (Exception ex)
{
SendMail("SendTweet", ex.Message);
}
}
I realize OpenID is somewhat of a behemoth, or more complex than a typical registration form, but I feel I'm missing something here.
According to this question, I'm supposed to save the unique identifier key I'm given by my provider.
The provider will give you a unique ID for each user - this you need
to save. It's how you will match up the user that just logged in with
a record in your database.
In my code (taken from the MVC portion), this unique ID is given inside the switch in the LogOn() action method:
public ActionResult LogOn()
{
var openid = new OpenIdRelyingParty();
IAuthenticationResponse response = openid.GetResponse();
if (response != null)
{
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
FormsAuthentication.RedirectFromLoginPage(
response.ClaimedIdentifier, false); // <-------- ID HERE! "response.ClaimedIdentifier"
break;
case AuthenticationStatus.Canceled:
ModelState.AddModelError("loginIdentifier",
"Login was cancelled at the provider");
break;
case AuthenticationStatus.Failed:
ModelState.AddModelError("loginIdentifier",
"Login failed using the provided OpenID identifier");
break;
}
}
return View();
}
[HttpPost]
public ActionResult LogOn(string loginIdentifier)
{
if (!Identifier.IsValid(loginIdentifier))
{
ModelState.AddModelError("loginIdentifier",
"The specified login identifier is invalid");
return View();
}
else
{
var openid = new OpenIdRelyingParty();
IAuthenticationRequest request = openid.CreateRequest(Identifier.Parse(loginIdentifier));
// Require some additional data
request.AddExtension(new ClaimsRequest
{
BirthDate = DemandLevel.NoRequest,
Email = DemandLevel.Require,
FullName = DemandLevel.Require
});
return request.RedirectingResponse.AsActionResult();
}
}
Do I use this identifier for the FormsAuthentication.SetAuthCookie(IDHERE, true);?
What if I want to also save the users information, such as email, name, nickname or whatever. How do I get this collection of data from the relying party? In case this process depends on the provider I'm using, I am using Steam OpenID provider:
http://steamcommunity.com/openid
http://steamcommunity.com/dev
When You are successfully logged On, you can then do whatever you like with the received data:
the Unique identifier alons with the claims you requested.
Store the collected data in a database record.
Save it in a cookie (either to send it as a token to your services if any or use it in your RP(Reliant party)).
Use it along with a universal membership provider or a simple Sql provider.
Here is how you should have the second action in your controller:
[AcceptVerbs(HttpVerbs.Post), ValidateInput(false)]
public ActionResult LogOnPostAssertion(string openid_openidAuthData)
{
IAuthenticationResponse response;
if (!string.IsNullOrEmpty(openid_openidAuthData))
{
var auth = new Uri(openid_openidAuthData);
var headers = new WebHeaderCollection();
foreach (string header in Request.Headers)
{
headers[header] = Request.Headers[header];
}
// Always say it's a GET since the payload is all in the URL, even the large ones.
HttpRequestInfo clientResponseInfo = new HttpRequestInfo("GET", auth, auth.PathAndQuery, headers, null);
response = this.RelyingParty.GetResponse(clientResponseInfo);
}
else
{
response = this.RelyingParty.GetResponse();
}
if (response != null)
{
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
var token = RelyingPartyLogic.User.ProcessUserLogin(response);
this.FormsAuth.SignIn(token.ClaimedIdentifier, false);
string returnUrl = Request.Form["returnUrl"];
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
case AuthenticationStatus.Canceled:
ModelState.AddModelError("OpenID", "It looks like you canceled login at your OpenID Provider.");
break;
case AuthenticationStatus.Failed:
ModelState.AddModelError("OpenID", response.Exception.Message);
break;
}
}
Other hints about what you can do with the received data:
By creating a user login record in a UserLogin table in you reliant party database (your app). You will be able to validate the authentication and the status of your user the next time he will visit your app. You can also redirect him, the first time, to a specific page to collect more specific data that the OPenID provider did not provide (eg: age or gender).
You can keep track of all user logins (OpenID (steam),google,liveID) and link them to the user. This will allow your unique user to login with whatever authentication provider he would like too.
For a full example using the Open ID authenticator you can look at the OpenId for MVC2 project1
from wich I extracted the previous example.
I've created Facebook page.
I have no application secret and no access token.
I want to post to this page from my .NET desktop application.
How can I do it? Can anyone help please, where can I get access token for this?
Should I create a new Facebook Application? If yes, how can I grant permissions to this application to post on page's wall?
UPD1:
I have no website.
I need to post company's news from .NET desktop application to company's Facebook page.
All I have is Login/Password for Facebook Page Account.
UPD2:
I've created Facebook Application. With AppID/SecretKey. I can get access token. But...
How can I grant permissions to post to page's wall?
(OAuthException) (#200) The user hasn't authorized the application to perform this action
I have created a video tutorial showing how to do this at this location:
http://www.markhagan.me/Samples/Grant-Access-And-Post-As-Facebook-User-ASPNet
You will notice that, in my example, I am asking for both "publish_stream" and "manage_pages". This let's you also post on pages of which that users is an admin. Here is the full code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Facebook;
namespace FBO
{
public partial class facebooksync : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CheckAuthorization();
}
private void CheckAuthorization()
{
string app_id = "374961455917802";
string app_secret = "9153b340ee604f7917fd57c7ab08b3fa";
string scope = "publish_stream,manage_pages";
if (Request["code"] == null)
{
Response.Redirect(string.Format(
"https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope));
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
//meh.aspx?token1=steve&token2=jake&...
tokens.Add(token.Substring(0, token.IndexOf("=")),
token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));
}
}
string access_token = tokens["access_token"];
var client = new FacebookClient(access_token);
client.Post("/me/feed", new { message = "markhagan.me video tutorial" });
}
}
}
}
You need to ask the user for the publish_stream permission. In order to do this you need to add publish_stream to the scope in the oAuth request you send to Facebook. The easiest way to do all of this is to use the facebooksdk for .net which you can grab from codeplex. There are some examples there of how to do this with a desktop app.
Once you ask for that permission and the user grants it you will receive an access token which you can use to post to your page's wall. If you need to store this permission you can store the access token although you might need to ask for offline_access permission in your scope in order to have an access token that doesn't expire.
You can use
https://www.nuget.org/packages/Microsoft.Owin.Security.Facebook/ to obtain users login and permission and
https://www.nuget.org/packages/Facebook.Client/
to post to feeds.
Below example is for ASP.NET MVC 5:
public void ConfigureAuth(IAppBuilder app)
{
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Facebook
var facebookOptions = new FacebookAuthenticationOptions
{
AppId = "{get_it_from_dev_console}",
AppSecret = "{get_it_from_dev_console}",
BackchannelHttpHandler = new FacebookBackChannelHandler(),
UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name,location",
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new Claim("FacebookAccessToken", context.AccessToken)); // user acces token needed for posting on the wall
return Task.FromResult(true);
}
}
};
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("publish_actions"); // permission needed for posting on the wall
facebookOptions.Scope.Add("publish_pages"); // permission needed for posting on the page
app.UseFacebookAuthentication(facebookOptions);
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
}
}
On the callback you get user access token:
public ActionResult callback()
{
// Here we skip all the error handling and null checking
var auth = HttpContext.GetOwinContext().Authentication;
var loginInfo = auth.GetExternalLoginInfo();
var identityInfo = auth.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
var email = loginInfo.Email // klaatuveratanecto#gmail.com
var name = loginInfo.ExternalIdentity.Name // Klaatu Verata Necto
var provider = loginInfo.Login.LoginProvider // Facebook | Google
var fb_access_token = loginInfo.identityInfo.FindFirstValue("FacebookAccessToken");
// Save this token to database, for the purpose of this example we will save it to Session.
Session['fb_access_token'] = fb_access_token;
// ...
}
Which then you can use to post to user's feed or page
public class postcontroller : basecontroller
{
public ActionResult wall()
{
var client = new FacebookClient( Session['fb_access_token'] as string);
var args = new Dictionary<string, object>();
args["message"] = "Klaatu Verata N......(caugh, caugh)";
try
{
client.Post("/me/feed", args); // post to users wall (feed)
client.Post("/{page-id}/feed", args); // post to page feed
}
catch (Exception ex)
{
// Log if anything goes wrong
}
}
}
You need to grant the permission "publish_stream".
Possibly the easiest way to do this is via Facebook PowerShell Module, http://facebookpsmodule.codeplex.com. This allows the same sort of operations as FacebookSDK, but via an IT-Admin scripting interface rather than a developer-oriented interface.
AFAIK there is still a limitation of Facebook Graph API that you will not be able to post references to other pages (e.g. #Microsoft) using the Facebook Graph API. This will apply to FacebookSDK, FacebookPSModule, and anything else built over Facebook Graph API.
You will get information on how to create a facebook app or link your website to facebook on https://developers.facebook.com/?ref=pf.
You will be able to download facebook sdk at http://facebooksdk.codeplex.com/. There are some good example given in the document section of the site.
public void PostImageOnPage()
{
string filename=string.Empty;
if(ModelState.IsValid)
{
//-------- save image in image/
if (System.Web.HttpContext.Current.Request.Files.Count > 0)
{
var file = System.Web.HttpContext.Current.Request.Files[0];
// fetching image
filename = Path.GetFileName(file.FileName);
filename = DateTime.Now.ToString("yyyyMMdd") + "_" + filename;
file.SaveAs(Server.MapPath("~/images/Advertisement/") + filename);
}
}
string Picture_Path = Server.MapPath("~/Images/" + "image3.jpg");
string message = "my message";
try
{
string PageAccessToken = "EAACEdEose0cBAAoWM3X";
// ————————create the FacebookClient object
FacebookClient facebookClient = new FacebookClient(PageAccessToken);
// ————————set the parameters
dynamic parameters = new ExpandoObject();
parameters.message = message;
parameters.Subject = "";
parameters.source = new FacebookMediaObject
{
ContentType = "image/jpeg",
FileName = Path.GetFileName(Picture_Path)
}.SetValue(System.IO.File.ReadAllBytes(Picture_Path));
// facebookClient.Post("/" + PageID + "/photos", parameters);// working for notification on user page
facebookClient.Post("me/photos", parameters);// woring using bingoapp access token not page in(image album) Post the image/picture to User wall
}
catch (Exception ex)
{
}
}
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 back 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.