I'm using pretty much the exact example code that's found on the page for the Facebook iOS SDK component.
If I remove the ids_for_business it works fine. The thing is, I need either ids_for_business or token_for_business.
I tested the following using the Facebook Graph API Explorer and it works fine.
me?fields=ids_for_business,token_for_business
Here's the permissions I'm requesting:
List<string> readPermissions = new List<string> {
"public_profile","name","email","first_name","last_name", "ids_for_business" };
And here's the method I'm calling:
private void ShowLogin()
{
// If was send true to Profile.EnableUpdatesOnAccessTokenChange method
// this notification will be called after the user is logged in and
// after the AccessToken is gotten
Profile.Notifications.ObserveDidChange((sender, e) => {
if (e.NewProfile == null)
return;
});
// Set the Read and Publish permissions you want to get
loginView = new LoginButton(new CGRect(51, Element.Height / 2, 218, 46))
{
LoginBehavior = LoginBehavior.Native,
ReadPermissions = readPermissions.ToArray(),
};
// Handle actions once the user is logged in
loginView.Completed += (sender, e) => {
if (e.Error != null)
{
// Handle if there was an error
System.Diagnostics.Debug.WriteLine($"Facebook Login Failed! {e.Error.DebugDescription}");
login.FacebookNotAuthenticated();
}
if (e.Result.IsCancelled)
{
// Handle if the user cancelled the login request
login.FacebookNotAuthenticated();
}
else
System.Diagnostics.Debug.WriteLine("Facebook Login Success!");
};
// Handle actions once the user is logged out
loginView.LoggedOut += (sender, e) => {
// Handle your logout
};
View.AddSubview(loginView);
}
Please check the documentation: Permissions Reference - Facebook Login, this lists all permission keys we can require. But I didn't find ids_for_business nor token_for_business, it's not a legal string on facebook. So it will return invalid scope. Is business_management what you need?
Please refer to this documentation to find the corresponding permission string. Moreover notice that only public_profile, user_friends, and email do not require Review, all other permissions do.
Related
I'm building a authentication app using OWIN. I'm trying to get both the Bear token and userinfo claims. The code below gets me to 85% of what I want. While initially writing the code I used IIS Express. I debugged and coded towards that environment. For whatever reason after the initial challenge called in the else block the request.isauthenticated is false after the return from the login screen (Using KeyCloak as idp). The code then drops the user into the else if block where I find request.form has my Bearer token. I must then execute the authentication.challenge again (no KeyCloak login screen opens) and I return to the top of the page_load and this time the request.isauthenticated is true and I can get the userinfo but the request.form is empty. This is find for me because I can store all the info off somewhere for later use.
Once I got to this point I targeted IIS. Ran the code and got different behavior. The code drops into the else block initially (same as before) I login but upon return from the idp this time the request.isAuthenticated is true. I have the userinfo but not the Bearer token. Any ideas why??
protected void Page_Load(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
String str = String.Empty;
var qry = ((System.Security.Claims.ClaimsPrincipal)Request.RequestContext.HttpContext.User).Claims;
if (null != qry)
{
foreach (System.Security.Claims.Claim item in qry)
{
if (item.Type == "preferred_username")
{
str = item.Value;
}
}
}
}else if (!Request.IsAuthenticated && Request.Form.Count > 0)
{
HttpContext.Current.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
else
{
HttpContext.Current.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/XXXapp locationXXX/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
I've figured it out,. Needed to set the save token flag to true. This allowed the token to be carried along in the request. So, I don't need if else. Now that I got that working I'm changing this section of code. My main issue is it is hard to find complete and current documentation with sample code for my use case. --Thanks
I added a Facebook login in my app. When I log in in my application it also logs in toSAFARI so that next time when I want to login, I don't need to enter login and password. You might press continue and you already login. I created a method to log out but it's not working. Its working in a simulator so I can close my app then open Safari and go to Facebook.com then press logout. Finally I open my app press press the Facebook login and got login and password fields.
public void Logout()
{
_loginManager.LogOut();
NSHttpCookieStorage storage = NSHttpCookieStorage.SharedStorage;
foreach (NSHttpCookie cookie in storage.Cookies)
{
if(cookie.Domain == ".facebook.com")
{
storage.DeleteCookie(cookie);
}
}
}
How can I log out from FB to every time enter login and password?
This image show that my credentials already entered:
You are maybe looking for methods and classes from WebKit instead. Also refer to this Forum post: https://forums.xamarin.com/discussion/149720/delete-web-cache-javascript-storage
You can get cookies and sessions with (there are more types in WKWebsiteDataType if there are other things you want to clear):
var websiteDataTypes = new NSSet<NSString>(
WKWebsiteDataType.Cookies,
WKWebsiteDataType.SessionStorage);
Or you can use WKWebsiteDataStore.AllWebsiteDataTypes to just clear everything.
You can then fetch these types with:
WKWebsiteDataStore.DefaultDataStore.FetchDataRecordsOfTypes()
It has a callback you need to listen to, to get these. Then you can remove all these records with:
WKWebsiteDataStore.DefaultDataStore.RemoveDataOfTypes();
Put it all together like:
var websiteDataTypes = new NSSet<NSString>(
WKWebsiteDataType.Cookies,
WKWebsiteDataType.SessionStorage);
WKWebsiteDataStore.DefaultDataStore.FetchDataRecordsOfTypes(websiteDataTypes, records =>
{
for (nuint i = 0; i < records.Count; i++)
{
var record = records.GetItem<WKWebsiteDataRecord>(i);
WKWebsiteDataStore.DefaultDataStore.RemoveDataOfTypes(
record.DataTypes,
new[] {record},
() => {}
);
}
});
I am working on app development with a strong custom backend part where each API request call contain Firebase auth token in a header. In a testing process we realised that token always received twice.
I used same logic as described in a Firebase sample project. To be sure it's not my mistake I check clean sample project, and result is still the same - somehow OnIdTokenChanged called twice on login. Both callbacks contain correct token.
I am on Unity 2018.3.5f1, .NET 4.5, and Firebase SDK v.5.4.4
Here is some code sample:
public virtual void Start() {
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available) {
InitializeFirebase();
} else {
Debug.LogError(
"Could not resolve all Firebase dependencies: " + dependencyStatus);
}
});
}
protected void InitializeFirebase() {
DebugLog("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
auth.IdTokenChanged += IdTokenChanged;
}
void IdTokenChanged(object sender, System.EventArgs eventArgs) {
Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
if (senderAuth == auth && senderAuth.CurrentUser != null && !fetchingToken) {
senderAuth.CurrentUser.TokenAsync(false).ContinueWith(
// THIS CALLED TWICE
task => DebugLog(String.Format("Token = {0}", task.Result)));
}
}
Some important app logic is based on a token receive event which should be received only once, and it's completely incorrect to get 2 token for 1 login.
Is it a bug or expected behaviour? If bug, does same behaviour exists on other platforms, like iOS/Android native or it's just Unity3d problem?
I'd expect the first invocation to happen right after you attach the listener, in which case it's the local token as taken from the application's cache. The second time is after the client has verified with the server that the token is still valid, or has refreshed the ID token.
From the documentation on the IDTokenChanged event:
Authentication ID token changes are:
When a user signs in
When the current user signs out
When the current user changes
When there is a change in the current user's token
I have a web application in asp.net . I want to use login with twiiter to get get user info. I have followed all instructions mentioned in below article
http://www.aspsnippets.com/Articles/Login-with-Twitter-in-ASPNet-using-Twitter-Button.aspx
I am getting redirected to twitter app then after authentication I am being redirected to my localhost app. Then I have check user is authorized but when I try to get user details by method FetchProfile() I am getting error.
My code is as below :
First on button click
protected void LoginTwitter(object sender, EventArgs e)
{
if (!TwitterConnect.IsAuthorized)
{
TwitterConnect twitter = new TwitterConnect();
twitter.Authorize(Request.Url.AbsoluteUri.Split('?')[0]);
}
}
then after authenticating back from twitter . on page load of application
I have check url its
http://localhost:63977/Account/Login?oauth_token=K0mECAAAAAAAxRXEAAABV44xPgc&oauth_verifier=qYLFiOlFPx4gxEu6V4AmTJG2JNjJ3nV2
then code to check
protected void Page_Load(object sender, EventArgs e)
{
TwitterConnect.API_Key = HelperClasses.TwitterApiKey;
TwitterConnect.API_Secret = HelperClasses.TwitterApiSecret;
if (Request.QueryString["oauth_token"] != null)
{
//twiiter
if (TwitterConnect.IsAuthorized)
{
TwitterConnect twitter = new TwitterConnect();
//LoggedIn User Twitter Profile Details
DataTable twitterUserDataTable = twitter.FetchProfile(); // error here
}
}
}
Tweetinvi provides a sample project doing exactly what you want to do : https://github.com/linvi/tweetinvi/tree/master/Examplinvi.Web.
I have highlighted the lines you will be interested in :
https://github.com/linvi/tweetinvi/blob/master/Examplinvi.Web/Controllers/HomeController.cs#L14-L36
You can also find more about the Authentication in tweetinvi here : https://github.com/linvi/tweetinvi/wiki/Authentication.
Here is the snippet that you want to use of ASP.NET authentication :
private IAuthenticationContext _authenticationContext;
// Step 1 : Redirect user to go on Twitter.com to authenticate
public ActionResult TwitterAuth()
{
var appCreds = new ConsumerCredentials("CONSUMER_KEY", "CONSUMER_SECRET");
// Specify the url you want the user to be redirected to
var redirectURL = "http://" + Request.Url.Authority + "/Home/ValidateTwitterAuth";
_authenticationContext = AuthFlow.InitAuthentication(appCreds, redirectURL);
return new RedirectResult(authenticationContext.AuthorizationURL);
}
public ActionResult ValidateTwitterAuth()
{
// Get some information back from the URL
var verifierCode = Request.Params.Get("oauth_verifier");
// Create the user credentials
var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, _authenticationContext);
// Do whatever you want with the user now!
ViewBag.User = Tweetinvi.User.GetAuthenticatedUser(userCreds);
return View();
}
I am developing a WPF application that needs post on wall of a facebook's Page, and this without login window.
Well, I want to get access token for my facebook page, and this is my code.
var fb = new FacebookClient();
string token = "";
dynamic accounts = fb.Get("/"<USER_ID>"/accounts");
foreach (dynamic account in accounts)
{
if (account.id == <PAGE_ID>)
{
token = account.access_token;
break;
}
}
But I receive a error #104. It is a simple error, that I need a access token to do this operation.
Then I use other code to get the user access token
var fb = new FacebookClient();
dynamic result = fb.Get("oauth/access_token", new
{
client_id = <PAGE_ID>,
client_secret = <APP_SECRET>,
grant_type = "fb_exchange_token",
fb_exchange_token = <USER_TOKEN>
});
But I get error #101:
"Error validating application. Cannot get application info due to a system error."
Someone knows what I have to do?
Thanks!!!
I'm not sure if you've been able to get a never expiring token for the page, so I'll explain you the steps:
Open Graph API Explorer
Select your app from the drop-down
Click "Get Access Token" button, and select the manage_pages permission.
Copy the token and run this in the browser:
https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id={app-id}&client_secret={app-secret}&fb_exchange_token={step-3-token}
Copy the token from step-4 and paste in to the access_token field and call:
/{page-id}?fields=access_token
The token you get now is a never-expiring token, you can validate the same in Debugger .Use this in your app.
But beware, its not recommended to use this token on client side if your app is public.
If you use the fb_exchange_token call, it will give you a token that expires after 60 days. In order to make it work correctly, I had to go through the login web flow to guarantee I got an up-to-date page access token.
Go to the Facebook App dashboard
If you haven't already added the Facebook Login product, click "+ Add Product" and select Facebook Login
Enable the "embedded browser control" option and enter https://www.facebook.com/connect/login_success.html as the allowed redirect URL.
Make a Window with a WebView control on it. The WebBrowser control no longer works; the browser engine powering it is too old.
Add code to listen for the navigation to the success URL:
this.webView.NavigationCompleted += (sender, args) =>
{
if (args.Uri.AbsolutePath == "/connect/login_success.html")
{
if (args.Uri.Query.Contains("error"))
{
MessageBox.Show("Error logging in.");
}
else
{
string fragment = args.Uri.Fragment;
var collection = HttpUtility.ParseQueryString(fragment.Substring(1));
string token = collection["access_token"];
// Save the token somewhere to give back to your code
}
this.Close();
}
};
Add code to navigate to the facebook login URL:
string returnUrl = WebUtility.UrlEncode("https://www.facebook.com/connect/login_success.html");
this.webView.Source = new Uri($"https://www.facebook.com/dialog/oauth?client_id={appId}&redirect_uri={returnUrl}&response_type=token%2Cgranted_scopes&scope=manage_pages&display=popup");
Call window.ShowDialog() to pop up the login window, then grab the user access token.
Create some models to help you out:
public class AccountsResult
{
public List<Account> data { get; set; }
}
public class Account
{
public string access_token { get; set; }
public string id { get; set; }
}
Using the user access token, get the page access token:
FacebookClient userFacebookClient = new FacebookClient(userAccessToken);
var accountsResult = await userFacebookClient.GetTaskAsync<AccountsResult>("/me/accounts");
string pageAccessToken = accountsResult.data.FirstOrDefault(account => account.id == PageId)?.access_token;
if (pageAccessToken == null)
{
MessageBox.Show("Could not find page under user accounts.");
}
else
{
FacebookClient pageFacebookClient = new FacebookClient(pageAccessToken);
// Use pageFacebookClient here
}