Login with AAD MSAL - Login is already in progress - javascript

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()?

Related

Displaying HTML page only to logged in users using Firebase (Continuation...)

I saw a question at this link because I have a similar situation and I wanted to comment but unfortunately I do not have enough rep to do so. I would like some clarification on it.
in Tor Arne Falk's question : He displayed a script that he used to manage logged in users and logged out users like so ⬇️
<script>
const auth = firebase.auth()
auth.onAuthStateChanged((user) => {
if (user) {
document.getElementById("body").style.display = "block";
} else {
window.location.replace("/login.html");
}
});
</script>
My question is do you put that script in every html after auth ( & except auth) to check if a user is logged in or not to display content in that page after logging in or redirect them to the auth page
further more Firebase is a type="module" so a common issue with modules is that we cant import firebase outside a module meaning we cant read data from the firebase.js (handling auth & database) to a different script, example: using Tor Arne Falk script (as is) on different html pages for the same cause I believe it will not work.
please share some ideas on if it possible to read data outside the module I would like an example to help me get started if not what should I do within my firebase.js file to ensure a user is logged in across every other page to prevent them from hitting the back button and seeing that that they are still logged in or link jumping (skipping my auth page and going to a page only logged in users are supposed to see without logging in) I hope I make sense!🤔

Google oauth session lost after page reload (javascript)

I recently moved from the deprecated gapi.auth2 to the new Google Identity Services, using the javascript client library, and noticed a big difference: if someone signs in, and then reloads the page, the session is lost, and has to sign in again, every time the page is loaded. This was not the case with the deprecated library.
The problem can be easily reproduced with the Calendar API example.
Is there any configuration option to keep the session persistent? Or do I need to store the access tokens somehow? I could not find anything relevant in the official docs.
UPDATE:
The migration guide states the following:
Previously, Google Sign-In helped you to manage user signed-in status using:
Callback handlers for Monitoring the user's session state.
Listeners for events and changes to signed-in status for a user's Google Account.
You are responsible for managing sign-in state and user sessions to your web app.
However there's absolutely no information on what needs to be done.
UPDATE 2
To be more specific, the actual issue is not making the session persistent. Managing the sign in state and user session is something I can solve.
The real problem is the access token used to call the Google APIs.
As mentioned in the comments, the access tokens are 1) short lived 2) are not stored anywhere, so even if not expired, they do not persist between page reloads.
Google provides the requestAccessToken method for this, however even if I specify prompt: '', it opens the sign-in popup. If I also specify the hint option with the signed in user's email address, than the popup opens, displays a loading animation briefly, and closes without user interaction. I could live with this, however this only works if triggered by a user interaction, otherwise the browser blocks the popup window, meaning that I cannot renew the token without user interaction, e.g. on page load. Any tips to solve this?
I faced all the same issues you described in your question.
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.

Other browser windows don't go back to user login page after Meteor.logout()

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 :)

Firebase error after logout

I'm currently developing a little Website with Firebase. I got a couple of HTML files and each file contains a logout button which calls the function
function logout(){
auth.logout();
console.log("logout successfull");
location.href="index.html";
}
After getting redirected I tried to login again but it always failed with the following error message:
Error: FirebaseSimpleLogin: An unknown server error occurred.
It took me some time to realise that the redirection to the index page caused the problem. When I delte the location.href="index.html"; line, everything works fine.
Problem is, I really need something that redirects me to the front page, when the user isn´t loged in. Is this a known problem and/or can someone come up with a solution to this problem?
Thanks in advance :)
PS.: I realised that I could "fix" the problem (after getting redirected to the index page) when I cause an error (f.e. calling a undefined function). Idk if this information helps...
Ok, thanks for your reply Kato!
I changed quite a lot, since I started the "project". Instead of using mutliple HTML files I copied everything into the index.html and work now with mutliple (hidden) DIVs.
But unfortunatly, the problem still exists.
I offer two different Login possibilites. One with Facebook (works 100% of the time for me) and one with the SimpleLogin (works barely).
I´m pretty sure I did the initialization the same way like it´s done in the tutorials on firebase.com.
This is how I connect to the Firebase DB
var ref = new Firebase('https://partyfinder-db.firebaseio.com/');
var auth = new FirebaseSimpleLogin(ref, function(error, user) {
if (error) {
// an error occurred while attempting login
alert(error);
} else if (user) {
// Here I work with user.id etc.
} else {
// user is logged out
}
});
And that is how I try to login the user...
function login() {
//I probably should use jQuery here...
var _email = document.getElementById("emailLogin").value;
var _pw1 = document.getElementById("passwordLogin").value;
var _rememberMe = document.getElementById("rememberMe").checked;
auth.login('password', {
email: _email,
password: _pw1,
rememberMe: _rememberMe
});
showMain(); //Hide and show DIVs and stuff...
}
I call this function on the SignIn Button. The whole Javascript file is linked in the head part of the HTML file.
So, calling this function is normally causing the following error
Error: FirebaseSimpleLogin: An unknown server error occurred.
I already figured out that this message only shows up when the connection to the DB already was successful. For example, when I type in an invalide email adress, the following message appears:
Error: FirebaseSimpleLogin: The specified user does not exist.
There are a few things that can "fix" the problem. For example, when I use the Facebook Login and logout after this was successful, I can sign in using firebase simpleLogin. Sometimes (unfortunatly not always) it helps when I`m causing an error, f.e. calling a non existing function. After the error message is displayed in the console, I can continue logging in (successfully).
But to be honest I`ve absolutly no idea what this tells me about the error and if this is somehow a hint to the solution. I also tried to set some breaking points and debug through the relevant code (using google chrome) but didn´t find anything.
I uploaded the page to a free webspace, where you can test this whole thing by yourself.
But please note, this project is just for testing purpos. I´m not planning to release it somehow, it´s just for me to figure out multiple things and I find it easier to learn something when I can set it in a context. I´m pretty sure it´s quite bad coded and contains many mistakes, etc. But I´m always grateful for feedback beside the actual problem :)
For the login you can use
email: user#email.com
password: user
If you use the FB-Login, your Name and your email adress will be saved to the Database (but I can delete this section of the code if you want/need to use it and feel uncomfortable about it).
http://partyfinder.lima-city.de/
Most of the comments are in german, sorry for that...

Facebook Connect Javascript API failing to maintain connected state after page reloads

I have a Facebook Connect site using the Javascript API - I'm not using any FBML tags. It was working fine until a couple of days ago and now I have a problem with reloading the page while the user is logged in.
The user can log in fine, and I can get the user's Facebook ID. They can refresh the page and they're still logged in (and I still get the ID). But if they refresh the page again (and subsequently), then FB.Connect.get_loggedInUser() always returns 'None', rather than the Facebook ID, even though FB.Connect.get_status().waitUntilReady() has said they're logged in.
Here's my basic code... can anyone see anything wrong?
FB_RequireFeatures(['Api'], function() {
FB.init('MY_API_KEY', '/xd_receiver.htm', {});
FB.ensureInit(function() {
FB.Connect.get_status().waitUntilReady( function( status ) {
switch (status) {
case FB.ConnectState.connected:
FB.Connect.requireSession(function() {
if (FB.Connect.get_loggedInUser()) {
var uid = FB.Connect.get_loggedInUser();
// Some more stuff here with the user's ID, displaying info in the page, etc.
}
}
break;
case FB.ConnectState.appNotAuthorized:
case FB.ConnectState.userNotLoggedIn:
// Display FB Connect button in page.
}
});
});
});
Is there something wrong with that? I can't work out how to ensure I get the user's logged in ID. Many thanks.
So, after much testing with various apps and domains and... it seems there was some conflict going on between the JavaScript Facebook code and some pyFacebook code in the Django back-end. Some confusion between the sessions stuff (yet to be figured out) was causing Safari to throw errors. So, we don't know the solution, but the JavaScript code above should, on its own, work fine.

Categories

Resources