I have a web application for which I am trying to use Twitter's OAuth functionality. This application has a link that prompts a user for their Twitter credentials. When a user clicks this link, a new window is opened via JavaScript. This window serves as a dialog. This is accomplished like such:
MainPage:
<div id="promptDiv">Provide Credentials</div>
...
function launchDialog(url) {
var specs = "location=0,menubar=0,status=0,titlebar=0,toolbar=0";
var dialogWindow = window.open(url, "dialog", specs, true);
}
When a user clicks the link, they are redirected to Twitter's site from the prompt.aspx page. On the Twitter site, the user has the option to enter their Twitter credentials. When they have provided their credentials, they are redirected back to my site. This is accomplished through a callback url which can be set for applications on Twitter's site.
When the callback happens, the user is redirected to "/twitter/confirm.aspx" on my site in the dialog window. When this happens I want to update the contents of "promptDiv" to say "You have successfully connected with Twitter" to replace the link and close the dialog. This serves the purpose of notifying the user they have successfully completed this step. I can successfully close the dialog window. However, when I am try to update the HTML DOM, I receive an error that says "Error: Permission denied to get property Window.document". In an attempt to update the HTML DOM, I tried using the following script in "/twitter/confirm.aspx":
// Error is thrown on the first line.
var confirmDiv = window.opener.document.getElementById("confirmDiv");
if (confirmDiv != null)
{
// Update the contents
}
window.close();
I then just tried to read the HTML to see if I could even access the DOM via the following script:
alert(window.opener.document.body.innerHTML);
When I attempted this, I still got a "Permission denied" error. I know this has something to do with cross-site scripting. However, I do not know how to resolve it. How do I fix this problem? Am I structuring my application incorrectly? How do I update the HTML DOM after a user has been redirected back to my site?
Thank you for your help!
When the popup opens the Twitter auth page, you are losing your original ability to communicate with the winodw because its document domain has changed and the window.opener has been reset.
To get around this for SitePen's NetFlix Queued, I used a timer and polled the popup window for changes to its location (which you can continue to access). If it went to an error page or a success page, I knew that and could close the popup (you have control of the window, but not the DOM) and change the content in the main page to reflect the status of authorization.
We also checked for the window closing – in the case of the user not authorizing and closing the popup.
We couldn't make use of the callback because this was done in Adobe AIR, and there was no server to "call back to", which created an extra hurdle.
Related
I have a ASP.net website, that uses MSAL to login.
The issue I keep having is that, whenever the user logs in, then logs out again the user is redirected to a logout page.
This page implements the new Msal.UserAgentApplication(msalConfig).logout() function, and redirects the user back to the login page.
This all works perfectly. The login page will then automatically redirect the user back to the AAD login page.
If the user then decides to login again, the result of MyMsalObject.GetAccount() returns null, and an error occurs that mentions the following:
ClientAuthError: Login_In_Progress: Error during login call - login is already in progress.
At first I used one js file to handle log in & logout, I then realised that that probably wasn't he best solution, as it attempted a login on load.
So I decided to split them up into two separate JS files but this hasn't fixed my problem.
msalObject definition:
var msalConfig = {
auth: {
clientId: "my_client_id",
authority: "my_authority_url",
redirectUri: "http://localhost:port"
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var myMSALObj = new Msal.UserAgentApplication(msalConfig);
login code:
$(document).ready(function(){
if (!myMSALObj.getAccount()) {
myMSALObj.loginRedirect(msalConfig);
acquireTokenRedirectAndCallMSGraph();
}
});
Edit:
Some extra details.
I've now made it so that users must click on a button before being redirected to Microsoft to login.
The above unfortunately still applies. After logging in succesfully for the first time & logging out, a secondary login attempt will not yield a value in the function getaccount() even though, it works perfectly the first time.
The error I get after I've logged in is still the same namely:
ClientAuthError: Login_In_Progress: Error during login call - login is already in progress.
Even though I just logged in..
Does anyone have a solution?
Edit 2:
There is a little bit of progress.. sort of, I've been able to fix the error above by changing way I log the user out.
The config file is now a definition within document ready & I've moved the log out function in there aswell.
Although I now face a new challenge..
Refused to display 'https://login.microsoftonline.com/{{}}' in a frame because it set 'X-Frame-Options' to 'deny'.
And im not entirely sure if this is a step forward or backwards. The reproduction scenario remains the same, you log in, then you log out & back in again, when microsoft sends the user back to the login page I get the error mentioned in this edit, but I don't get this error on the 1st login attempt.
The answer stated on: https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/FAQs#q6-how-to-avoid-page-reloads-when-acquiring-and-renewing-tokens-silently doesn't help at ALL, I'm using chrome but it still doesn't work..
Check session/local storage and cookies for any dangling msal information. We had the same problem, and I stumbled into this link.
https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/1069
It suggests clearing storage and cookies, but if you dig into using your browser tools, you'll see several entries like "msal...interactive...". Those will have values of "in progress", and that's what is causing the error.
Deleting those entries clears up the problem.
First, when using loginRedirect, you need to put the code you want to run when the user is redirected back to your app inside myMsalObj.handleRedirectCallback(callback) instead of inside the function where you initiate the redirect process. Also note, that handleRedirectCallback should be registered on initial page load.
Example:
const myMSALObj = new Msal.UserAgentApplication(msalConfig);
$(document).ready(function(){
myMSALObj.handleRedirectCallback(function(error, response) {
var account = myMSALObj.getAcccount();
if (account) {
// user is logged in
}
});
});
I am a little confused about your app though. Are you saying you have page in your app that just calls myMSALObj.logout()?
I am using chrome.identity.launchWebAuthFlow to retrieve an authentication code from my Rails app which is set up as an OAuth2 provider using the Doorkeeper gem (the Doorkeeper side of things is working).
So I send then request to my server with this method from the Chrome extension:
requestGrant: function(){
chrome.identity.launchWebAuthFlow(
{
'url': authService.grantEndPoint(),
'interactive': true
}, function(redirect_url){
/* Extract auth code from redirect_url */
var code = authService.extractCode(redirect_url);
alert(code);
authService.getAccessToken(code);
}); //launchWebAuthFlow ends here
}
And my server receives the request and redirects to
https://<my_chrome_extension_name>.chromiumapp.org/oauth2?code=<access_code_generated_by_oauth>
with a 302 found.
But, the Chrome extension immediately closes, and the callback function of launchWebAuthFlow does not run. I know it is not running because I call alert() in the callback (doesn't run), and make another request to my server for the access token (server does not receive the request).
I think part of the problem is that the chrome extension might be closing right when launchWebAuthFlow is called, because the window launchWebAuthFlow opens is a web view of the servers authorization flow, and the extension closes (or is the auth flow just being displayed through the extension?)
For some reason launchWebAuthFlow's default behavior is to close the window according the documentation, but the callback still isn't running.
How can I get the callback function to run, and prevent the chrome extension window from closing?
I was running the launchWebAuthFlow in non background script. I moved the auth logic to a background script and it works fine.
I too was experiencing almost the same issue. I was trying to launch the webauthflow from my popup.html but the popup.html would close once the auth flow began, aborting the code that would execute upon succesful return of a token.
My suggestion is to instead take care of authentication in options.html.
(https://developer.chrome.com/extensions/optionsV2)
This will launch a popup modal that stays open even after your auth flow opens, (as opposed to popup.html closing when it loses focus), meaning the rest of your code will execute.
Hope this helps.
I am developing a enterprise application using spring and struts. But, i'm getting issue on Tab close. how to force user logging out when close the browser tab or open same page on another tab.
i have been try using onbeforeunload but i am getting issue when application running on mobile browser. and i also have seen following sample but No one has clear explanation.
How to kill session when user closed the browser without logout
How to Detect Browser Window /Tab Close Event?
is there any solution to achieve this problem using javascript or from server?
Thanks
Finally I found a solution that worked!
When the user logs in I use sessionStorage to store that a user has been logged in:
sessionStorage.setItem('logged', true)
SessionStorage will hold that property until the tab or the browser closes.
So inside the application, I check if the SessionStorage still holds that property. If not then I logout the user and I redirect him to the login.
if (!sessionStorage.getItem('logged')) {
localStorage.removeItem('token')
navigator.sendBeacon('api/logout')
window.location.replace("/login") //redirect to login
}
For those who wonder what is navigator.sendBeacon you can read here to learn more. Practically I use it because I want the api/logout to be accessed even if the tab closes.
You may start a ajax request by page onload, and get a tracking session id/serial from server.
Later force all of the requests operations to include the tracking session you just gave to the page using the ajax call above.
If user opens up a new tab, the ajax load starts again. and As far as you check the live session tracks in the server with associated user, you may redirect the user to somewhere else or etc.
I don't think you may rely on onbeforeunload, just the same thing you experience.
As others stated, http is stateless, and cookies and requests are only stuffs you can check the state of the user.
At the server, session cookies could be invalidated by session timeout(if we assume user going to brew some coffee, e.g. it closes the page/tab).
And as explained in above solution, if he/she opens a new tab, the new ajax call might block him/her to perform a new login or etc.
I suggest you may find another solution instead of this approach you are trying to get. It's much easier and more senseful to sync the page state with the last opened page. Let the user opens 5 same page, and just sync them all with each other(simplest solution: refresh others when one gets updated)
You may have a javascript function and invoke it on "onunload" of body and in that script invoke backend code to invalidate the user session.
localStorage can be use to keep idle time for the application with multiple tabs are opened.
// Check browser support
if (typeof(Storage) !== "undefined") {
// Store an item to localStorage
localStorage.setItem("timeIdle", "0");
console.log(localStorage.getItem("idleTime"));
// Retrieve the added item
} else {
//display this message if browser does not support localStorage
console.log("Sorry, your browser does not support Web Storage.");
}
function func(){
$(this).keypress(function(e) {
localStorage.setItem("timeIdle", "0");
});
$(this).click(function(e) {
localStorage.setItem("timeIdle", "0");
});
timerIncrement();
}
function timerIncrement() {
var timeIdle = localStorage.getItem("timeIdle");
timeIdle = parseInt(timeIdle) + 1;
if (timeIdle >= 1) {
logoutCall();
window.location = window.location.origin+"/riskoffice-ui/Login";
}
localStorage.setItem("timeIdle", timeIdle.toString());
}
setInterval(func,1800000); //Runs the "func" function every second
I have written a meteor application with user login. After a user logs out, the application redirects to the user login page. However, when they are multiple tabs in the browser (or multiple browser windows) where the application is active (and the user is logged in), only the active tab or browser window goes back to the user login page. In the other window it seems the user is still logged in. However, when the user does some further work in the other window, nothing is synced with the db on the server anymore. I thought Meteor.logout() is reactive, so how is it possible that the other browser tabs or windows don't refresh?
I have the folowwing in my router?js file:
var filters = {
isLoggedIn : function(pause) {
if(!Meteor.user()){
this.render('login');
} else {
this.next();
}
}
....
}
Router.onBeforeAction(filters.isLoggedIn);
After pushing the logout button the following js code is executed
Meteor.logout();
Thanks for the help.
Try this:
Meteor.logoutOtherClients
Meteor.logoutOtherClients should log out all sessions. It is designed for situations where the user is logged in on multiple devices and wants to log out on all of them simultaneously.
In my app I didn't want to use a global redirect on logout, but on some templates to redirect to another template if logout happens.
Following Autumn Leonard's comment, I made this work by having the particular template reactive by creating a template.mytemplate.onCreated function and inside there put an autorun function checking Meteor.user() and doing the redirect.
I hope this approach helps others :)
There is a website which has a login screen, and when the submit is hit, it goes to a new page and logs in the user.
Here's a screenshot :
Now, Suppose I have a similar login screen in my android app, like this :
Now, Is there a way to link both of them, so that, when I hit login in the android app, it actually registers a submit at that website and logs in the user, and obviously, then again, binding the next webpage that shows up after logging in. How dlink the urlfrom the webpage to the js and elements in an android app?
I know there has to be javascript, but how?
Have you Checked this : http://developer.android.com/guide/webapps/webview.html
and this : http://www.codeproject.com/Articles/392603/Android-addJavaScriptInterface
While login we sends the form data from Android application to the Server-side page (JSP, Servlet,ASP or PHP), then those page will compile the required operation for login validation using any database , then it returns “1” if the login is valid else return “0”.
Hence you have to find out all the parameters that are working around once you click the login or register in that website.Also login page may contain cookies and other temp storage that will be required at each login.Also you need to find the methods used.
So understanding the webpage configurations ,parameters and functionality will help you achieve using android tools like webview(just a tool,not logic).
First make a detailed study on all the required parameters and functionality of the webpage then get started with the app.
Below is a list of reference links that may help you to tackle the issue :
Refer 1,
Refer 2,
Refer 3,
Refer 4,
Refer 5
You can also see this site to solve ur probelm ...
https://wowjava.wordpress.com/2011/01/16/login-application-for-android/
or
http://webdesignergeeks.com/mobile/android/android-login-authentication-with-remote-db/