Firebase 3. authentication doesn't persist - angularjs

I'm working with firebase in a angularJS app, using the email and password authentication.
I just update my app from Firebase 2.x to 3.x and AngularFire from 1.x to 2.x.
I followed these 2 docs to do the migration :
https://firebase.google.com/support/guides/firebase-web
https://github.com/firebase/angularfire/blob/master/docs/migration/1XX-to-2XX.md
But now, each time I refresh my page, I need to re-authenticate, like there is no persistent session.
I've checked the localStorage key firebase:authUser I have an expirationTime in the past (actually it's set with the timestamp of my login).
To check if the user is loggedin I use : $firebaseAuth().$getAuth()
EDIT
Here is a working example of my problem (login: toto#mail.fr / password: toto123)
https://plnkr.co/edit/463Hse?p=preview
Does anybody know why this behavior ?

I am gonna guess that you are checking the currentUser directly without waiting for the initial auth state to resolve. You need to add an observer:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
https://firebase.google.com/docs/auth/web/manage-users
Also, auth state is stored in web storage so make sure you have that enabled. (state will not persist in safari private mode browsing for example).

Related

saving userType in ReactJs thorughout the session

I am using ReactJs and Nodejs with mysql as my backend, I am maintaining user session via express-session and setting cookie header in my browser. The problem is that I want to display components based on role (eg.admin or user). I am sending the userType from database to React app,in response to the successful login.
How can I maintain and store this userType througout the session so that I can manage my roles.
I dont think local Storage is a good option.
P.S: I have also key:value pair of userType inside the cookie which I am receiving in my browser.but I dont know how to extract userType from the cookie
If you are having a single cookie, ie userType, you can simple do this in componentDidMount or any other applicable control location:
let userType = document.cookie.split("=")[1]
console.log(userType) //your cokkie value
Else, if there are many cookies, you can follow this:
var cookies= {};
document.cookie.split(/\s*;\s*/).forEach(function(pair) {
pair = pair.split(/\s*=\s*/);
cookies[pair[0]] = pair.splice(1).join('=');
});
console.log(cookies.userType)
Storing in a cookie/local storage is fine you just have to make sure the user is authenticated server-side for a certain privilege.

Preventing Direct URL to views in angular + firebase web app

I'm not an expert as I started working in firebase and angularjs a few weeks ago. I'm building a server based web application using firebase, nodejs(for server) and angularjs and I've a login scenario for my web application, Now I want to prevent direct URL access, after checking that a user is login or not. I want to redirect it to login page if user try to access via direct URL.
I tried using this but it doesn't seems to work.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
Can some provide me a working example of preventing access to URLs using angularjs and firebase?
Thanks in Advances

Angularfire Auth session persistence

This is my first time using AngularJs, not sure whether my authentication handle correctly or not.
I expect $firebaseAuth() will keep the authentication status even if I refresh the app. But every time I refresh the app, $firebaseAuth() will not re-authenticate the user, and I need to re-login.
I read through the document and search in the source code, but can't find the function that allows me to configure the session persistence. Only 2 parameters email and password are accepted.
versions:
angularjs v1.4.10
angularfire v2.0.1
firebase v3.0.3
my authenticationService litcoffee script
app.factory "authenticationService", [
"$firebaseAuth"
"$location"
"$rootScope"
($firebaseAuth, $location, $rootScope) ->
login: (email, password, redirectUrl = "/") ->
$rootScope.authObj.$signInWithEmailAndPassword(email, password)
.then(
(firebaseUser) ->
console.log firebaseUser
$rootScope.firebaseUser = firebaseUser
return true
(error) ->
$rootScope.firebaseUser = null
console.log error
alert error.message
return false
)
logout: (redirectUrl = "/login") ->
$rootScope.authObj.$signOut()
$location.path redirectUrl
isLogged: () ->
if $rootScope.authObj.$getAuth()
return true
else
return false
]
I check user authentication status on a controller which will call authenticationService.isLogged(), it will redirect to login page if user is not logged.
What I want to achieve is just a simple authentication, user will remain authentication status even if they refresh.
Please correct my if I'm on the wrong direction. Any help would be greatly appreciated.
It's my fault actually.
Firebase and AngularFire keep the authentication session persistence by default.
What I did wrong is check the authentication status immediately when the page loaded. At the moment AngularFire hasn't fired yet, it will take some time to re-authenticate the application.
Thus, $firebaseAuth.$onAuthStateChanged can be very helpful.
Listen to it when your page loaded. Once the event fired, it will notify you whether the user authenticated.

Integrating Laravel, Facebook and Angular with token-based-authentication

My use case:
User is already logged in automatically server side using Facebook with laravel and Socialite.
I check if the user exists in the db and if not create it and log them into laravel.
Then I need to start an Angular app and make sure they are logged in with Laravel / Facebook.
After reading this article, it looks like this token based approach is what I should take.
In the tutorial you serve a login form with Angular, and then pass the email and password to an authenticate controller (Laravel), which returns a token (create by JWT-Auth).
Once the token is in Angular all is well, my problem is that I want to get the token directly into Angular without a login form since the user is already logged in as mention above.
I'm wondering if I could just output the token in markup somewhere and then pick it up from Angular or would that somehow be a security risk? I guess people will only be able to view source and see their own token?
If this is the wrong way to do this, then how should I do it? Do I need to authenticate with Facebook with Javascript, and then create a new laravel user with ajax?
Thanks so much!
One approach you could take is to add something to your .config block that checks for the presence of a JWT in local storage and if there isn't one there, makes a request to the API to see if the user is logged in on the Laravel side. If the user is logged in, a JWT is returned which can be picked up and saved in local storage. Since the .config block is run when the Angular app loads, this will only happen once, which is probably what you're looking for.
Here's what that might look like. First the Laravel side:
// AuthenticateController.php
...
// Simulates a user being logged in on the Laravel side through something
// other than credentials sent from the front-end. Obviously you would use
// Socialite
public function authenticate()
{
$user = User::find(1);
$token = JWTAuth::fromUser(1);
return response()->json(compact('token'));
}
...
Then the Angular:
// app.js
...
.run(function($rootScope, $state, $auth) {
if(!$auth.isAuthenticated()) {
// No credentials provided because the user is already logged in on the server
$auth.login().then(function() {
$state.go('users');
}
}
$rootScope.$on('$stateChangeStart', function(event, toState) {
...
This would just run when the Angular app loads, which will be after your user has logged in with Socialite. It's essentially just checking whether there is a user logged in on the back end and if so, the token is retrieved. It's a bit hacky and the interface isn't obvious, so it might not be the best solution.
You would need to arrange your authenticate controller on the Laravel side such that it returns the token if the user has logged in via socialite or require credentials if he/she hasn't (which is the traditional login).
You could also look at this approach to see if it works for you: https://github.com/barooney/jot-bot/tree/socialite
Let me know if that works out!

Keycloak: Update user password in AngularJS application

I'm building an AngularJS application protected by Keycloak.
Each user should update his password within his user profile.
Calling the Keycloak API for password
GET /auth/realms/{realm_name}/account/password
returns HTML content from Keycloak.
I would like to build my own form to update a user's password.
In the Keycloak documentation I found
POST /auth/realms/{realm_name}/account/password
which requires the attributes
{
'password' => user's current password
'password-new' => new password
'password-confirm' => new password again
'stateChecker' => token from keycloak
}
Calling
POST /auth/realms/{realm_name}/account/password
without the 'stateChecker' attribute causes an error. This attribute is needed.
So here are my questions:
How do I get the value for stateChecker from keycloak for the logged in user (in Keycloak it's in a hidden input field)?
Is there another possibility to change a user's password with a REST API call?
Thanks in advance.
Note:
Calling:
POST /auth/realms/{realm_name}/account/password
with hard coded attributes and values
{
'password': 'somepasswd',
'password-new': 'someNEWpasswd',
'password-confirm': 'someNEWpasswd',
'stateChecker': '<token copied and pasted from keycloak>',
}
is working!
My advice would be to overwrite the keycloak theme (check this out: http://docs.jboss.org/keycloak/docs/1.2.0.Beta1/userguide/html/themes.html).
You can extend and modify the existing forms to look like the rest of your application.
Finally I ended up with an own implementation of a rest endpoint using keycloaks admin rest api.
Building an own theme could be a solution too, as Lisa stated.

Resources