how to wait until localStorage.setItem finishes in angular 4 - javascript

i am developing an angular 4 application. once the user wants to log in to the system it sends a http request to the server and server validate the user and it sends a reposnce with a authentication key and other user details. i use local storage to save these information
login() {
if (this.loginForm.valid) {
this.serviceUserService.authenticate(this.loginForm).subscribe(response => {
if (response.message != "_err") {
//saving the current user in localstorage
localStorage.setItem('currentUser', JSON.stringify(response.body));
this.router.navigateByUrl('/');
} else {
alert("invalid login. Please try again")
}
}, err => {
console.log(err);
})
}
}
it seems like that localStorage.setItem() is an asynchronous function. so before it save the curent user in the local storage it redirect to the main page. but since the token is not saved in the local storage no http requests will work. how do i wait until localStorage.setItem() finish it's task and then send the user to home page.

You are wrong , all localStorage calls are synchronous. Probably you can add a check before navigating to the next page.
localStorage.setItem('currentUser', JSON.stringify(response.body));
this.router.navigateByUrl('/');

In case anyone is getting the same kind of a issue... the reason for this was I have created a variable in my service class to save the current user and set the value for that variable inside the constructor. So, in the login page when the authenticate method gets called it tries to initialize the variable but since user is not logged in yet it is still null. That was causing the issue.

Related

Keycloak js not executing THEN after init

I am trying to integrate Keycloak login into my React app and I'm trying to get the JWT from keycloak. Here is the code:
const [keycloakState, setKeycloakState] = useState<any>();
const login = () => {
const keycloak = Keycloak("/keycloak.json");
keycloak.init({onLoad: 'login-required'}).then(authenticated => {
console.log('kk', keycloak)
console.log('at', authenticated)
setKeycloakState({ keycloak: keycloak, authenticated: authenticated });
}).catch(err => {
alert(err);
});
console.log('log after')
}
The login function is triggered when a button is clicked. It redirects properly to keycloak, I can log in and I am properly redirected to the app. The problem is that after the redirect back to the app with proper login the code in the then part of the chain is not executed, and even the 'log after' does not appear in the logs. The catch error part works fine.
Why might this be happening? I have keycloak-js added to my project.
I used to face this problem before. The way that I passed is separating the "init" function and then invoke it later.
Here is my example on jsFiddle: 'https://jsfiddle.net/gzq6j3yu/1/'
Our solution was to use the functions onAuthSuccess and onAuthError avaliable on the KeycloakInstance keycloak-js provides. (The documentation around this is a little shaky but you can find them if you check out the source code.) As the names imply these functions get called when an auth attempt is successful or unsuccessful, respectively.
note: in the following snippets this._instance replaces OP's keycloak constant.
Basic code snippet:
import Keycloak from 'keycloak-js';
...
// pulled from a class's init function from a custom Keycloak helper class so won't translate one for one but you get the point.
this._instance = Keycloak(configObject);
this._instance.onAuthSuccess = () => {
// code to execute on auth success
};
this._instance.onAuthError = () => {
// code to execute on auth error
};
this._instance.init(initOptions)
...
We also had a getter to get the token on the KeycloakInstance (or empty string) on the same class. This is an easy way to refer to the token in your code to check if it actually exists, etc. Here's what that'd look like inside the class.
get token() {
return this._instance ? this._instance.token : '';
}
Hope this can help out some folks.
I think the reason your fulfilled callback is not executed is the way your app interacts with Keycloak. You initialize the Keycloak-Adapter with onLoad: 'login-required' which will redirect the user to Keycloak - which means the Javascript execution is interrupted at this point. Keycloak will redirect the user back to your app and since you wrapped the Keycloak-Adapter in a function which is only executed when a button is clicked, the promise callback is not executed.
Simple example:
// do this on page load
keycloak.init({onLoad: 'login-required'}).then((authenticated) => {
console.log('authenticated', authenticated)
})
You will not see a "authenticated", false in your console when you open up your app. If the user is not authenticated, he will be redirected (so no chance to execute that callback). If he then comes back and is authenticated, the callback will be executed and authenticated should be true.
If you want the user to click a button, a setup like this should work:
// do this somewhere early in your App or main.js and in a way that this code is executed on page load
const keycloak = new Keycloak(configuration);
keycloak.init({onLoad: 'check-sso'}).then((authenticated) => {
if (authenticated) {
// do what needs to be done if sign in was successful, for example store an access token
} else {
// handle failed authentication
}
}).catch(err => {
alert(err);
});
const login = () => { // this could be an on-click event handler
keycloak.login();
};
check-sso won't redirect the user to Keycloak if unauthenticated, so the user can trigger the login when needed.
Keep in mind that your JavaScript code will run twice and you have to cover both cases, first the user is not authenticated and needs to be redirected to Keycloak and a second time once the user comes back from Keycloak (then we should get the information that the user is authenticated in .then().

Firebase for web: telling whether user is logged in or not

I have a web app built on Firebase's web library. I want to restrict some pages to only users who are logged in.
This code triggers when firebase detects the user is logged in, which is good.
firebase.auth().onAuthStateChanged(function (user) {
console.log('User is logged in');
});
But I can't get anything to reliably check whether the user is not logged in without leaving the page before the above code has a chance to check...
var check_firebaseReady == false;
function local_initApp() {
if (check_firebaseReady == false) {
if (typeof firebase !== 'undefined') {
check_firebaseReady = true;
console.log(firebase.auth().currentUser); //not reliable becuase it may return an empty user before it has a chance to get an existing user
}
setTimeout(function () {
local_initApp();
}, 300);
}
}
local_initApp();
I think for single page apps, you have to use the onAuthStateChanged listener and enforce access via security rules on specific data. If you want to block access to a complete page, you are better off using a cookie system. Firebase Auth provides that option: https://firebase.google.com/docs/auth/admin/manage-cookies
With cookies, you would check and verify the cookie server side, otherwise, not serve the page and show some error or redirect to login page instead.

Firebase seems to attempt to begin listening for snapshot updates before authentication sequence is run. any way to fix this?

It seems that before firebase is able to get the current user authentication data such as the email used for login, it attempts to call
firestore.collection("users").doc(firebase.auth().currentUser.email).onSnapshot(function(doc) {
console.log("check")
});
the thing is, it requires the current user's email to access the correct document in the collection from within the database.
is there any way to circumvent this and to wait until currentUser defined?
If your code depends on having an authenticated user, you should run it in an onAuthStateChanged callback. For example:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
firestore.collection("users").doc(firebase.auth().currentUser.email).onSnapshot(function(doc) {
console.log("check")
});
}
});
Also see the Firebase documentation on getting the authenticated user.

Logged out of Facebook but it still reconginizes $user

All,
I'm using Facebook Connect (JS SDK) to authenticate a user to my site. I'm checking to see if a logged in session variable is set on my site before even hitting code to check to see if a user is logged into facebook. This all works great however, when the user logs out of facebook and logs out of my site and I try and go back to my login back it still thinks that the user is logged into facebook even though I know they aren't. How can I prevent this from happening? I tried to set autologoutlink=true on my login button but it doesn't seem to be working.
Any ideas?
Thanks!
The solution provided by #Madan worked for me. Since my application is ajax based, therefore I can't reload the browser. I run a setInterval() call back function every minute to check if user is still logged in to facebook.
setInterval(function (){
FB.getLoginStatus(function(response){
if(response.status ==='unknown' && FB_LOGIN==1){
alert('Your Facebook session has been expired');
member_logout();
}
}, true);
},60000);
it worked like a charm.
Always give second parameter in FB.getLoginStatus( callback, true) as true...this is because facebook response is cached in SDK. So use alway true param for current user session check.
I've always had excellent results when calling FB.getLoginStatus() and redirecting the user to the appropriate content based upon those results. Three conditions (although for an app, the second two are quite the same in my opinion)
https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
// the user is logged in and connected to your
// app, and response.authResponse supplies
// the user's ID, a valid access token, a signed
// request, and the time the access token
// and signed request each expire
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
} else if (response.status === 'not_authorized') {
// the user is logged in to Facebook,
//but not connected to the app
} else {
// the user isn't even logged in to Facebook.
}
});
$facebook->destroySession();
or u can go to this link
Facebook getUser() function returning user ID after logout

backbone.js - handling if a user is logged in or not

Firstly, should the static page that is served for the app be the login page?
Secondly, my server side code is fine (it won't give any data that the user shouldn't be able to see). But how do I make my app know that if the user is not logged in, to go back to a login form?
I use the session concept to control user login state.
I have a SessionModel and SessionCollection like this:
SessionModel = Backbone.Model.extend({
defaults: {
sessionId: "",
userName: "",
password: "",
userId: ""
},
isAuthorized: function(){
return Boolean(this.get("sessionId"));
}
});
On app start, I initialize a globally available variable, activeSession. At start this session is unauthorized and any views binding to this model instance can render accordingly. On login attempt, I first logout by invalidating the session.
logout = function(){
window.activeSession.id = "";
window.activeSession.clear();
}
This will trigger any views that listen to the activeSession and will put my mainView into login mode where it will put up a login prompt. I then get the userName and password from the user and set them on the activeSession like this:
login = function(userName, password){
window.activeSession.set(
{
userName: userName,
password: password
},{
silent:true
}
);
window.activeSession.save();
}
This will trigger an update to the server through backbone.sync. On the server, I have the session resource POST action setup so that it checks the userName and password. If valid, it fills out the user details on the session, sets a unique session id and removes the password and then sends back the result.
My backbone.sync is then setup to add the sessionId of window.activeSession to any outgoing request to the server. If the session Id is invalid on the server, it sends back an HTTP 401, which triggers a logout(), leading to the showing of the login prompt.
We're not quite done implementing this yet, so there may be errors in the logic, but basically, this is how we approach it. Also, the above code is not our actual code, as it contains a little more handling logic, but it's the gist of it.
I have a backend call that my client-side code that my static page (index.php) makes to check whether the current user is logged in. Let's say you have a backend call at api/auth/logged_in which returns HTTP status code 200 if the user is logged in or 400 otherwise (using cookie-based sessions):
appController.checkUser(function(isLoggedIn){
if(!isLoggedIn) {
window.location.hash = "login";
}
Backbone.history.start();
});
...
window.AppController = Backbone.Controller.extend({
checkUser: function(callback) {
var that = this;
$.ajax("api/auth/logged_in", {
type: "GET",
dataType: "json",
success: function() {
return callback(true);
},
error: function() {
return callback(false);
}
});
}
});
Here is a very good tutorial for it http://clintberry.com/2012/backbone-js-apps-authentication-tutorial/
I think you should not only control the html display but also control the display data. Because user can use firefox to change your javascript code.
For detail, you should give user a token after he log in and every time he or she visit your component in page such as data grid or tree or something like that, the page must fetch these data (maybe in json) from your webservice, and the webservice will check this token, if the token is incorrect or past due you shouldn't give user data instead you should give a error message. So that user can't crack your security even if he or she use firebug to change js code.
That might be help to you.
I think you should do this server sided only... There are many chances of getting it hacked unit and unless you have some sort of amazing api responding to it

Categories

Resources