Angular firebase, cant login using factory - angularjs

I get an error when i try to login using this code. The part of creating the user works perfectly and the login methods I used are nearly identical. But chrome gives me this error message:
TypeError: undefined is not a function
at Object.loginUser (http://localhost:8080/js/app.js:28:10)
at Scope.HomeController.$scope.loginUser (http://localhost:8080/js/app.js:197:9)
This is the html:
<button ng-click="createUser(email, password)">Create user</button>
<button ng-click="loginUser(email, password)">Login</button>
In the controller:
$scope.createUser = function(email, password) {
Auth.createUser(email, password);
}
$scope.loginUser = function(email, password) {
Auth.loginUser(email, password);
}
And the factory:
(function () {
angular
.module("myQuiz")
.factory("Auth", ["$firebaseAuth", function($firebaseAuth) {
var ref = new Firebase("https://angularquiz.firebaseio.com/");
return {
createUser: function(email, password) {
ref.createUser({
email: email,
password: password
}, function(error, userData) {
if(error) {
console.log("Error creating user: ", error);
} else {
console.log("Succesfully created an account with uid: " + userData.uid);
}
});
},
loginUser: function(email, password) {
ref.authwithPassword({
email: email,
password: password
}, function(error, authData) {
if(error) {
console.log("Login failed! " + error);
} else {
console.log(authData + "Succesfully authenticated!");
}
});
}
}
}]);
})();

typo, its authWithPassword not authwithPassword!
it works now

Related

How to retrieve user profile to the frontend | PassportJs

I'm trying to log in a user using Passport Js (Google Auth), I configured Passport Js and i'm getting the user profile in my console, but I didn't know how to show the user profile in frontend, the configure for PassportJs goes like:
passport.use(
new GoogleStrategy(
{
clientID: "",
clientSecret: "",
callbackURL: "/auth/google/callback",
scope: ["profile", "email"],
},
async (accessToken, refreshToken, profile, done) => {
// find current user in UserModel
const currentUser = await User.findOne({
googleId: profile.id
});
// create new user if the database doesn't have this user
if (!currentUser) {
const newUser = await new User({
googleId: profile.id,
email: profile.emails[0].value,
displayName: profile.displayName,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
profilePic: profile.photos[0].value,
}).save();
if (newUser) {
done(null, newUser);
}
}
console.log("CURRNT USER: ", currentUser);
done(null, currentUser);
}
)
);
// serialize the user.id to save in the cookie session
// so the browser will remember the user when login
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id)
.then(user => {
done(null, user);
})
.catch(e => {
done(new Error("Failed to deserialize an user"));
});
});
And in the Auth.js route:
// when login is successful, retrieve user info
router.get("/login/success", (req, res) => {
if (req.user) {
res.status(200).json({
error: false,
message: "succesfull",
user: req.user,
cookies: req.cookies
});
} else {
res.status(403).json({ error: true, message: "Not Authorized" });
}
});
// auth with google
router.get("/google", passport.authenticate("google", ["profile", "email"]))
// redirect to home page after successfully login via google
router.get(
"/auth/google/callback",
passport.authenticate("google", {
successRedirect: "http://localhost:3000/",
failureRedirect: "/login/failed"
})
);
I'm using Context to let the app knows if the user is logged in or not.
**Login.jsx: Normal Logging Using express and Mongodb **
const handleSubmit = async (e) => {
e.preventDefault();
dispatch({ type: "LOGIN_START" });
try {
const res = await axios.post("/login", {
email: userRef.current.value,
password: passwordRef.current.value,
});
dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
} catch (err) {
dispatch({ type: "LOGIN_FAILURE" });
setError(true)
}
};
//Now I tried this code to log in a user using Google Auth but it didn't work
useEffect(() => {
fetch(`http://localhost:4000/login/success`, {
method: 'GET',
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Credentials': true,
},
})
dispatch({ type: "LOGIN_START" })
.then((response) => {
if (response.status === 200) return response.json();
throw new Error('failed to authenticate user');
})
.then((responseJson) => {
dispatch({ type: "LOGIN_SUCCESS", payload: responseJson.data });
})
.catch((error) => {
dispatch({ type: "LOGIN_FAILURE" });
console.error("Failed to authenticate user", error)
});
}, []);
const google = () => {
window.open("http://localhost:4000/auth/google/callback", "_self");
};
The full code is here: https://codesandbox.io/s/nervous-mountain-e5t9d4?file=/api/routes/auth.js
let me share with you the perfect code.
passportStratergy.js
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const User = require('../model/user');
const { USER_TYPES } = require('../constants/authConstant');
const googlePassportStrategy = passport => {
passport.serializeUser(function (user, cb) {
cb(null, user);
});
passport.deserializeUser(function (user, cb) {
cb(null, user);
});
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENTID,
clientSecret: process.env.GOOGLE_CLIENTSECRET,
callbackURL: process.env.GOOGLE_CALLBACKURL
}, async function (accessToken, refreshToken, profile, done) {
if (profile){
let userObj = {
'username':profile.displayName,
'ssoAuth': { 'googleId': profile.id },
'email': profile.emails !== undefined ? profile.emails[0].value : '',
'password':'',
'userType':USER_TYPES.User
};
let found = await User.findOne(User,{ 'email': userObj.email });
if (found) {
const id = found.id;
await User.updateOne(User, { _id :id }, userObj);
}
else {
await User.create(User, userObj);
}
let user = await User.findOne(User,{ 'ssoAuth.googleId':profile.id });
return done(null, user);
}
return done(null, null);
}
));
};
module.exports = { googlePassportStrategy };
auth.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const { socialLogin } = require('../services/auth');
router.get('/auth/google/error', (req, res) => {
res.loginFailed({ message:'Login Failed' });
});
router.get('/auth/google',passport.authenticate('google', {
scope: ['profile', 'email'],
session:false
}));
router.get('/auth/google/callback',
(req,res,next)=>{
passport.authenticate('google', { failureRedirect: '/auth/google/error' }, async (error, user , info) => {
if (error){
return res.send({ message:error.message });
}
if (user){
try {
//let result = await socialLogin(user.email);
// here your business logic for login user.
return res.send({
data: result.data,
message:'Login Successful'
});
} catch (error) {
return res.send({ message: error.message });
}
}
})(req,res,next);
});
module.exports = router;
index.js
const passport = require('passport');
const { googlePassportStrategy } = require('./passportStrategy');
googlePassportStrategy(passport);

What is the best way to use Google 0Auth

I'm trying to use Google OAuth in my App, on the Log In page and the Sign Up page, I'm looking for the best way and the easiest! I tried Passport Js, but I'm stuck right now.
I'm using Mongoose right now and I'm signing up and in users perfectly, but now i want to add a feature where the user can sign in using his google account, I'm looking for a way where the app can get the Email the user is using for his google account and then look if the email is already registered if so redirect him to the home page and if not sign his email up, save it to database, and then redirect to the home page.
This is how my Auth.js looks like
//REGISTER
router.post("/register", async (req, res) => {
try {
//generate new password
const salt = await bcrypt.genSalt(10);
const hashedPass = await bcrypt.hash(req.body.password, salt);
//create new user
const newUser = new User ({
username: req.body.username,
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: hashedPass,
repeatPassword: hashedPass,
birthday: req.body.birthday,
});
//save user and respond
const user = await newUser.save();
res.status(200).json(user);
} catch (err) {
res.status(500).json(err);
}
});
//LOGIN
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
// if(!user) return res.status(400).json("Wrong credentials!");
!user && res.status(400).json("Wrong credentials!");
const validated = await bcrypt.compare(req.body.password, user.password);
// if(!validated) return res.status(400).json("Wrong credentials!");
!validated && res.status(400).json("Wrong credentials!");
const { password, ...others } = user._doc;
return res.status(200).json(others);
} catch (err) {
return res.status(500).json(err);
}
});
PassportJs configuration I used: but didn't work
passport.use(
new GoogleStrategy(
{
clientID: "MyClientId",
clientSecret: "Myclientsecret",
callbackURL: "/api/auth/google/callback",
},
function (accessToken, refreshToken, profile, done) {
User.find(
{
social: profile.provider,
social_id: profile.id,
},
(err, user) => {
if (user.length === 0) {
const user = new User({
email: profile.email,
username: profile.displayName,
profilePic: profile.photos[0],
social: profile.provider,
social_id: profile.id,
});
const userModel = new User(data);
userModel.save();
done(null, profile);
}
if (err) {
return done(err);
}
},
);
return done(null, profile);
}
)
);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
router.get("/login/success", (req, res) => {
if (req.user) {
res.status(200).json({
success: true,
message: "successfull",
user: req.user,
// cookies: req.cookies
});
}
});
router.get("/login/failed", (req, res) => {
res.status(401).json({
success: false,
message: "failure",
});
});
router.get("/google", passport.authenticate("google", { scope: ["profile"] }));
router.get(
"/google/callback",
passport.authenticate("google", {
successRedirect: CLIENT_URL,
failureRedirect: "/login/failed",
})
);

Cannot read property 'message' of undefined

I develop method of login in my website, but i have problem in login.controller.js
I have this error:
TypeError: Cannot read property 'message' of undefined .
at login.controller.js:35
'use strict';
export default class LoginController {
user = {
name: '',
email: '',
password: ''
};
errors = {
login: undefined
};
submitted = false;
/*#ngInject*/
constructor(Auth, $state) {
this.Auth = Auth;
this.$state = $state;
}
login(form) {
this.submitted = true;
if(form.$valid) {
this.Auth.login({
email: this.user.email,
password: this.user.password,
rememberme: this.user.remember
})
.then(() => {
// Logged in, redirect to home
this.$state.go('main');
})
.catch(err => {
this.errors.other = err.message;
});
}
}
}
export default class LoginController {
/* #ngInject */
constructor(Auth, $state) {
this.Auth = Auth;
this.$state = $state;
this.user = {
name: null,
email: null,
password: null
};
this.errors = {
login: null,
others: null // This was needed;
};
this.submitted = false;
}
login(form) {
this.submitted = true;
if (form.$valid) {
this.Auth.login({
email: this.user.email,
password: this.user.password,
rememberme: this.user.remember
})
.then(() => {
return this.$state.go('main');
})
.catch((err) => {
console.log(err); // see what 'err' looks like here
this.errors.other = err.message;
})
.finally(() => {
// Logged in, redirect to home
console.log('last thing');
});
}
}
}
I moved your variables into the constructor. Put a console.log in to see what err looks like. It's possible 'message' simply does not exist on err. Also this.errors.others needed to be declared.

create password and access with password only

Trying to make an admin panel where the admin user can create passwords for the access page. You'll need the password to access the login/register page. I've been trying to make this with json web tokens. I've used the MEAN-stack for this:
access Schema
var accessSchema = new mongoose.Schema({
password: String
});
create jwt
function createAccessToken(password) {
var payload = {
sub: password._id,
iat: moment().unix(),
exp: moment().add(7, 'days').unix()
};
return jwt.encode(payload, config.ACCESSCODE_TOKEN_SECRET);
}
Login and signup
app.post('/auth/loginaccess', function (req, res) {
Access.findOne({ password: req.body.password }, function (err, access) {
if (!access) {
return res.status(401).send({ message: 'Invalid password' });
}
access.comparePassword(req.body.password, function (err, isMatch) {
if (!isMatch) {
return res.status(401).send({ message: 'Invalid password' });
}
res.send({ tokenauth: createAccessToken(access) });
});
});
getPasswords();
});
app.post('/auth/signupaccess', function (req, res) {
Access.findOne({ password: req.body.password }, function (err, existingPw) {
if (existingPw) {
return res.status(409).send({ message: 'Password is already taken' });
}
var access = new Access({
password: req.body.password
});
access.save(function (err, result) {
if (err) {
res.status(500).send({ message: err.message });
}
res.send({ tokenauth: createAccessToken(result) });
});
});
});
ComparePassword and save schema
accessSchema.pre('save', function (next) {
var access = this;
bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash(access.password, salt, function (err, hash) {
access.password = hash;
next();
});
});
});
accessSchema.methods.comparePassword = function (password, done) {
bcrypt.compare(password, this.password, function (err, isMatch) {
done(err, isMatch);
});
};
the creation of the password works and is correctly encrypted and inserted into the database. But when I try to login it throws the 401 error inside app.post('/auth/loginaccess').
Why is this happening?
And any tips to improve this is highly appreciated.

Redirect after email authentication

I'm having trouble redirecting the user after successful login, i've read the documentation for Firebase and tried several things but no luck so far
Can anyone point me into the right direction ?
Thanks in advance,
Jérémie.
Here's the controller.js
.controller('LoginCtrl', function($scope, $ionicPopup, $state, Auth) {
$scope.data = {};
$scope.login = function() {
Auth.login($scope.data.email, $scope.data.password).then(function() {
$state.go("tab-discover");
})
.error(function() {
var alertPopup = $ionicPopup.show({
title: 'Mauvais identifiants',
template: 'Veuillez recommencer'
});
});
}
$scope.signup = function() {
Auth.signup($scope.data.email, $scope.data.password)
.error(function() {
var alertPopup = $ionicPopup.show({
title: 'Erreur',
template: 'Un probleme est survenu'
});
});
}
})
And the services.js
.factory("Auth", function(FURL, $firebaseAuth) {
var ref = new Firebase(FURL);
var auth = $firebaseAuth(ref);
var Auth = {
user: {},
login: function(email, password){
console.log("loginService", email, password);
return ref.authWithPassword({
"email": email,
"password": password
}, function(error, authData) {
if (error) {
console.log("La connexion a echoué!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
})
},
signup: function(email, password){
console.log("signupService", email, password);
return ref.createUser({
"email": email,
"password": password
}, function(error, userData) {
if (error) {
switch (error.code) {
case "EMAIL_TAKEN":
console.log("The new user account cannot be created because the email is already in use.");
break;
case "INVALID_EMAIL":
console.log("The specified email is not a valid email.");
break;
default:
console.log("Error creating user:", error);
}
} else {
console.log("Successfully created user account with uid:", userData.uid);
}
}).then(function(){
return Auth.login(email, password);
})
}
}
return Auth;
})
It looks like firebase is using callbacks where you're trying to return it as a promise with then. A simple fix would be to pass a callback to your login function and call it inside the firebase callback:
login: function(email, password, callback, onError){
console.log("loginService", email, password);
ref.authWithPassword({
"email": email,
"password": password
}, function(error, authData) {
if (error) {
onError(error);
} else {
callback(authData);
}
})
Then call it like this:
Auth.login($scope.data.email, $scope.data.password, function (data) {
console.log("Authenticated successfully with payload:", data);
$state.go("tab-discover");
}, function (error) {
console.log("La connexion a echoué!", error);
});

Resources