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},
() => {}
);
}
});
Related
I am having a strange issue with my login web page, where user's login session gets lost occasionally after successful login.
When the user accesses the next page after login, it would be redirected back to the login page because the login session doesn't exist.
It happens about 10% of the time randomly (seems so) among many users, and usually the same user who experienced this would get in after the second try. It doesn't seem to me that the system was busy when this happens.
Here's the login process:
User enters the username and password on the login page (login.asp),
then the login credentials are sent from the login page (login.asp)
to a Asp.Net login handler (LoginHandler.ashx) via an javascript
Ajax call.
The Login Handler then validates the credential and set a login
session (Session["CC_VendorInfo"]) which includes user's information.
Then the Login Handler sends back an OK response to the Ajax call.
Upon receipt of the OK response, the javascript on Login.asp would
send the user to the next page.
When user requests the next page, the server tries to retrieve info
from the Login session (Session["CC_VendorInfo"]). If the session is null then it would
redirect the user back to the login page.
I have some debug log on the server to print out the login session contents which proves that the session is successfully set in Step 2. And I also have log showing that in Step 4, the login session sometimes is NULL.
More Notes:
The application is deployed on a standard Windows virtual machine in Azure, so the session management limitations caused by load balancing don't seem to apply to this problem.
What would be the possible cause of this issue? Any answer is much appreciated!
Part of the code in Login.asp:
function Login() {
$.ajax({
type: "POST",
url: "../Home/LoginHandler.ashx",
data: {
user: $("#UserName").val(),
pswd: $("#PassWord").val()
},
success: function (response) {
ProcessLogin(response);
},
error: function (xhr, status) {
alert("Failed to login.");
}
})
return false;
}
function ProcessLogin(response) {
// ... ...
if (response == 'OK') {
window.location.href = strNextUrl;
} else {
alert("Failed to login.");
}
}
Part of the code in LoginHandler.ashx:
if (CheckCredential(context, sUserName, sPassword))
{
ClsVendorInfo oVendorInfo = new ClsVendorInfo();
oVendorInfo.iVendorID = iVendorID;
oVendorInfo.sUserName = sUserName;
// set the login session here
ClsCommonUI.SetVendorInfoSession(oVendorInfo);
sResp = "0|OK";
}
A function in an utility class to set the login session:
static class ClsCommonUI
{
// ... ...
public static bool SetVendorInfoSession(ClsVendorInfo oVendorInfo)
{
ClsVendorInfo oSessVendorInfo = HttpContext.Current.Session["CC_VendorInfo"] as ClsVendorInfo;
if (oSessVendorInfo != null &&
(oSessVendorInfo.iVendorID != oVendorInfo.iVendorID ||
oSessVendorInfo.iUserID != oVendorInfo.iUserID))
{
DebugLog(oSessVendorInfo,
string.Format("Login Session Changed [{0}] (before): {1}",
HttpContext.Current.Session.SessionID,
oSessVendorInfo.Print()));
}
// update session
HttpContext.Current.Session.Remove("CC_VendorInfo");
HttpContext.Current.Session["CC_VendorInfo"] = oVendorInfo.Clone();
oSessVendorInfo = HttpContext.Current.Session["CC_VendorInfo"] as ClsVendorInfo;
// I can see the session content being print out in the debug log
DebugLog(oSessVendorInfo,
string.Format("SetVendorInfoSession [{0}]: {1}",
HttpContext.Current.Session.SessionID,
oSessVendorInfo.Print()));
// ... ...
return true;
}
// ... ...
}
When the user requests the next page, here's the code to check the Login session:
public static int GetVendorInfo(HttpRequest oReq,
ClsDBAccess oDBAccess,
out ClsVendorInfo oVendorInfo,
[CallerFilePath] string sCallerFileName = "")
{
HttpContext context = HttpContext.Current;
ClsVendorInfo oSessionVendorInfo = context.Session["CC_VendorInfo"] as ClsVendorInfo;
if (oSessionVendorInfo != null &&
oSessionVendorInfo.iVendorID != 0)
{
// continue processing
//... ...
}
else
{
// No Session - go back to login
RedirectToLogin(HttpContext.Current);
}
}
If this isn't your issue, I can delete this answer.
Chrome's new SameSite change for cookies is about to drop or already did. If you don't have SameSite attribute on a cookie, chrome will just drop the cookie outright. If it is set to Lax, then all cross-domain iframes will drop the cookie. If this works fine in IE, then this is probably your issue. If you use SameSite=None, cross domain iframe works, but older browsers may stop working, too...
I have front app on angular 5 and backend api on c# using identity server.
The problem is that when I click logout button, the token is removed and i am redirected to logout page.
But when I try to refresh main page, I am redirected to microsoftonline.com
authenticated automatically and redirected back to main page
I am missing providing username and password here, and this occurs in chrome incognito.
What I noticed is that if I remove manually the cookie from microsoftonline.com
and repeat the process, this time I will be asked for username and password.
So first I tried to clean all cookies this way but it din't help
foreach (var key in HttpContext.Request.Cookies.Keys)
{
HttpContext.Response.Cookies.Append(key, "", new CookieOptions() { Expires = DateTime.Now.AddDays(-1) });
}
bellow is my accountcontroller logout method and cookie screen
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutViewModel model)
{
var idp = User?.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
var subjectId = HttpContext.User.Identity.GetSubjectId();
if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider)
{
if (model.LogoutId == null)
{
model.LogoutId = await interaction.CreateLogoutContextAsync();
}
try
{
await signInManager.SignOutAsync();
}
catch (NotSupportedException)
{
}
}
// set this so UI rendering sees an anonymous user
HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
// get context information (client name, post logout redirect URI and iframe for federated signout)
var logout = await interaction.GetLogoutContextAsync(model.LogoutId);
var vm = new LoggedOutViewModel
{
PostLogoutRedirectUri = logout?.PostLogoutRedirectUri,
ClientName = logout?.ClientId,
SignOutIframeUrl = logout?.SignOutIFrameUrl
};
await persistedGrantService.RemoveAllGrantsAsync(subjectId, "angular2client");
return View("LoggedOut", vm);
}
If I understand correctly you are federating to Microsoft from your IdentityServer4 service? If so when you sign out of your identity service you should also give the user the option to sign out of the external provider (if it supports the relevant feature - it'd need to define an end_session_endpoint in the discovery document).
This functionality is supported by the standard OIDC middleware so you should be able to initiate signout by calling SignoutAsync() and passing the name of the scheme for the MS federated sign in.
Another option is to always send prompt=login in your external sign in requests and then check the auth_time claim you get back. That way to you force interactive sign in always and also verify when it happened.
Try cleaning the cookies from the HttpContext itself, using the extension method, provided by Identity Server, like here.
Or try this:
await HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);
in your Logout controller method.
3rd option (what I have in one of my test MVC clients is):
public ActionResult Logout()
{
Request.GetOwinContext().Authentication.SignOut();
return Redirect("/");
}
public void SignoutCleanup(string sid)
{
var cp = (ClaimsPrincipal)User;
var sidClaim = cp.FindFirst("sid");
if (sidClaim != null && sidClaim.Value == sid)
{
Request.GetOwinContext().Authentication.SignOut("Cookies");
}
}
Where the Logout method is called on the button click, and the SignoutCleanup is the one that is passed to Identity Server, when registering the client as a Client.BackChannelLogoutUri (or Client.FrontChannelLogoutUri, or both, depending on your scenario).
PS: Now, in general I think that your approach is not right, but I don't know your full case, so I'm not judging you - just giving and advice.
For front-end clients (Angular, Vue, vanilla JS etc..) it is recommended to use the client-side oidc-client-js library. And here is the usage example. As I said - this is just an advice, but if you are in the very beginning of your authentication setup, I would recommend you to have a look.
I want to send pushnotifications to firefox web browser.......
<script>
function notifyMe() {
// Let's check if the browser supports notifications
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
}
// Let's check whether notification permissions have already been granted
else if (Notification.permission === "granted") {
// If it's okay let's create a notification
var notification = new Notification("Hi there!");
}
// Otherwise, we need to ask the user for permission
else if (Notification.permission !== 'denied') {
Notification.requestPermission(function (permission) {
// If the user accepts, let's create a notification
if (permission === "granted") {
var notification = new Notification("Hi there!");
}
});
}
// At last, if the user has denied notifications, and you
// want to be respectful there is no need to bother them any more.
} Notification.requestPermission().then(function (result) {
console.log(result);
}); function spawnNotification(theBody, theIcon, theTitle) {
var options = {
body: theBody,
icon: theIcon
}
var n = new Notification(theTitle, options);
}
</script>
whenever first time my website run permission popup will come.but when user click allow button how to get browser info like id.I want save that browser id into my database.next time I will send notification using that id. I did not find any code please help me.please anyone help me.
The Web Notifications API does not do what think it does.
It can only be used to display notifications from a web page that a user currently has open in their browser. It is comparable to alert(), except with a larger variety of formatting options.
It is not a push notification service, and cannot be used as one.
For our new Windows 10 application (C# + XAML) we are using the new https://github.com/Microsoft/winsdkfb/ login, however since we have migrated to this login I am having no luck with facebook login.
We are using FBResult result = await sess.LoginAsync(permissions); and I am getting this error all the time: "Not Logged In: You are not logged in. Please login and try again."
My code is litteraly a copy and paste from the samples they did on github:
I have checked my SID and FacebookAppId and they are the same on both the app and the Facebook website.
public async Task<string> LogIntoFacebook()
{
//getting application Id
string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
//// Get active session
FBSession sess = FBSession.ActiveSession;
sess.FBAppId = FacebookAppId;
sess.WinAppId = SID;
//setting Permissions
FBPermissions permissions = new FBPermissions(PermissionList);
try
{
// Login to Facebook
FBResult result = await sess.LoginAsync(permissions);
if (result.Succeeded)
{
// Login successful
return sess.AccessTokenData.AccessToken;
}
else
{
// Login failed
return null;
}
}
catch (InvalidOperationException ex)
{
SimpleIoc.Default.GetInstance<IErrorService>().ReportErrorInternalOnly(ex);
return null;
}
catch (Exception ex)
{
SimpleIoc.Default.GetInstance<IErrorService>().ReportErrorInternalOnly(ex);
return null;
}
return null;
}
by doing this:
//getting application Id
string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
it is generating me an SID that looks like this:
ms-app://s-1-15-2-0000-bla-bla-bla-667/
so I tried adding ms-app:// to the facebook developer settings page but it did not want it, so I tried removing ms-app:// from the SID when passing it to WinAppId but still no luck
I have filled the field Windows Store SID wih My FBAppId :
does anyone have this issue?
Edit 1:
My code is copy and paste from here: http://microsoft.github.io/winsdkfb/
Edit2: playing the samples from Microsoft my issues is coming from my Application Id.
I did follow step 6:
(Enable OAuth login)
Select the created app on developers.facebook.com.
Click “Settings” from the menu on the left.
Click on the “Advanced” tab.
Under the “OAuth Settings” section, enable “Client OAuth Login” and “Embedded browser OAuth Login”.
Click on “Save Changes”.
After trying everything and NOT wanting to use WebAuthentificationBroker I have found the solution.
Go on the Facebook Developer website: https://developers.facebook.com
Then:
Go to your app name -> Settings -> Advance:
Under: Valid OAuth redirect URIs
you need to add: https://www.facebook.com/connect/login_success.html
Save and you are good to go now!
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
}