Unable to retrieve current Parse user - javascript

I'm logging into my Parse app through the JavaScript SDK, it appears to be storing cookies however once it progresses to the next page it always displays the current user as being null despite having logged in successfully. I've cleared the cookies and it appears to be storing the cookies after login fine. This is the code I'm using however no matter what I seem to do it just won't collect the current user. Does anyone know if there's an issue with this or if there's something extra I have to do for it to be able to recall the cookie? If it's relevant the two site are on subdomains, could this be the problem?
Parse.initialize(JSDK, API);
var currentUser = Parse.User.current();
var currentUsername = currentUser.get('username');
alert(currentUsername);

You should use the getUsername() method instead of get('username').

Related

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.

Should localStorage persist when application is run via live server?

I am running an application via VSCode's Live Server extension.
This application (e-commerce website) saves items to a cartItems array that gets written to localStorage whenever an addToCart button is clicked. I can see in DevTools/Application/LocalStorage that the items are being saved correctly when the specified actions are taken.
However, my localStorage is cleared whenever I refresh the page or navigate to a different page within the same application.
When writing items to localStorage, I have tried invoking the localStorage short-hand, as well as the more explicit window.localStorage. Neither has worked for this issue.
Does localStorage not persist when an application is run locally or via a live server? I suspect it should and I am doing something else incorrectly.
The MDN documentation mentions:
The read-only localStorage property allows you to access a Storage
object for the Document's origin; the stored data is saved across
browser sessions. localStorage is similar to sessionStorage, except
that while data stored in localStorage has no expiration time, data
stored in sessionStorage gets cleared when the page session ends —
that is, when the page is closed. (Data in a localStorage object
created in a "private browsing" or "incognito" session is cleared when
the last "private" tab is closed.)
Could it be that each refresh or page change on live server represents an entirely new device history? (Again, this feels plausible but still unlikely. I am happy to be wrong, however.)
Thank you in advance for any guidance you can provide.
EDIT - Here is some of the relevant code:
In the global scope:
const cartItems = [];
localStorage.setItem('cartItemsKey', JSON.stringify(cartItems));
localStorage.getItem('cartItemsKey');
const cartItemsInStorage = localStorage.getItem('cartItemsKey');
Encapsulated - this function fires when an addToCart button is clicked. Omitting most of it, except the part pertaining to localStorage, for brevity:
function addToCart (button) {
// Create newCartItem object using relevant data
cartItems.push(newCartItem);
localStorage.removeItem('cartItemsKey');
localStorage.setItem('cartItemsKey', JSON.stringify(cartItems));
}
Again, I can see that the items are successfully being saved to localStorage, per the below screen recording. It's when I refresh or change pages that I have trouble.
Update:
I figured out what the issue was.
I have the following code in the global scope:
const cartItems = [];
localStorage.setItem('cartItemsKey', JSON.stringify(cartItems));
localStorage.getItem('cartItemsKey');
const cartItemsInStorage = localStorage.getItem('cartItemsKey');
Which gets called before this code:
function addToCart (button) {
// Create newCartItem object using relevant data
cartItems.push(newCartItem);
localStorage.removeItem('cartItemsKey');
localStorage.setItem('cartItemsKey', JSON.stringify(cartItems));
}
So I was effectively re-writing an empty array into localStorage every time the page reloaded.
I have resolved this issue by removing the .setItem line as follows:
const cartItems = [];
localStorage.getItem('cartItemsKey');
const cartItemsInStorage = localStorage.getItem('cartItemsKey');
Now, I will rewrite my initial const cartItems = []; as a conditional statement, where I first check to see if cartItemsKey exists in global storage. If so, I will set cartItems = JSON.parse(localStorage.getItem('cartItemsKey'). Otherwise, I will set cartItems = [];.
Thank you very much, #Alex Rasidakis, for your kind help.
Can you provide us with some code? I don't think that the Live Server has anything
to do with the local storage malfunction you are talking about.
I'm pretty sure it's a browser issue. Maybe you are using hard refresh somehow
each time you are refreshing. Maybe you have some setting that clears the local storage or some browser extension that cleans your page every time you refresh.
Try to open your localhost address from another browser like Mozilla, Edge etc.
and tell us about its behaviour.

how send server data in a multi page web application?

These days I made a standard home page, a login page, and a user information page. In my login page using method POST and Ajax(Fetch), I send the e-mail and password to the server, the server responses the correct json with the user information that belongs to that e-mail. BUT I don't have an idea how that user information in JSON can use in another HTML document like a user information page.
I have tried so many things but nothing helped me.
form.addEventListener('submit',(e)=>{
e.preventDefault();
const data={}
data1.correo=email.value;
data1.contrasenia=password.value;
const miinit={
method:'POST',
headers: {"Content-type":"application/json"},
body:JSON.stringify(data1)}
const url='https://localhost:44351/api/login';
const myrequest =new Request(url,miinit)
const requestpost=()=>{
fetch(myrequest).then(response=>{console.log(response);return response.json()}).then(response=>{console.log(response)})
}
requestpost()
})
I'm assuming you are doing this all without any library or anything. With that being said, I'm assuming that each page transition is going to be a full page refresh. This means that your object returned by the API is only as good as the lifetime of your Login Page.
You have two options that will work with your setup:
Use localStorage to store the current users JSON payload.
const payload = { userId: 1, name: 'Test' };
// The item being saved to localStorage must be
// a string. You serialize/deserialize as your
// set/get if need be.
localStorage.setItem('currentUser', JSON.stringify(payload));
// On some other page, calling localStorage.getItem
// will give you the object
console.log(localStorage.getItem('currentUser'));
Assuming you have control of your backend code and there is a session available, create a new API Method that will return the current user object. You can call the getCurrentUser method on every page and that will return that logged in user.
Both of these options have security points to think about, but that isn't what this question is about. I think for you, the easiest option is to just save the object to Local Storage, but I would not recommend that for a production setup. If you are trying to do something that is production ready, I would recommend that you look into JWT Authentication.
https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
https://jwt.io/introduction/
If you want to use the information coming back from the server in more than one page, you'd have to store it in LocalStorage or another persistent API. Data is not shared across pages.

Login with AAD MSAL - Login is already in progress

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

How to clear data after logout

I do use hawtio 1.5.5 for my website. I have an issue with user's credentials. User's name and password are stored in browser. When user performs logout, I would like to be this data wiped. I did some investigation, and there is called method doLogout() in index.html file (hawtio-web). I know these credentials are stored in localStorage but I don't know, which is the right spot to wipe them. Thanks.
Due to username and password being stored in browser instead of the localStorage cache for security reason, you need to use the browser feature to clean up the browser cache. You should be able to clear the cache by restarting the browser or use private browsing like Incognito.
I have found solution. You have to inject service into your plugin
module.run(..., preLogoutTasks) {
// your code
preLogoutTasks.addTask("clearCredentials", () => {
localStorage.removeItem('userName');
localStorage.removeItem('password');
});
}

Categories

Resources