How to have multiple passport for different user types in MEAN stack - mean-stack

In my project, I am using the passport feature in MEAN stack for user authentication. I have logins for 4 different user types(patient , doctor , and so on.) Can I have multiple passports for all different user types??
Below mentioned is the code for User(patient) Passport. I tried creating different passports, but I don't know how to link them to the project.
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
var User = mongoose.model('User');
passport.use(
new localStrategy({ usernameField: 'email' },
(username, password, done) => {
User.findOne({ email: username },
(err, user) => {
if (err)
return done(err);
// unknown user
else if (!user)
return done(null, false, { message: 'Email is not registered' });
// wrong password
else if (!user.verifyPassword(password))
return done(null, false, { message: 'Wrong password.' });
// authentication succeeded
else
return done(null, user);
});
})
);

Related

How to access laravel API with VUE JS?

so i want to use mylogin api but its not working,it keep push the route to dashboard even the email and the password incorrect
here is my code
export default {
data(){
return{
form: {
email: null,
password: null
},
user: {},
error: false
}
},
methods: {
login() {
this.user.append("email", this.form.email);
this.user.append("password", this.form.password);
this.axios.post('http://127.0.0.1:8000/api/login', this.user).then(response => {
localStorage.setItem("Name", response.data.first_name);
this.$router.push('/userDashboard/Dashboard')
});
},
register() {
this.$router.push('/RegisterPage')
}
},}
my laravel route api
Route::post('/login', 'UserController#login');
Login function
public function login(Request $request, User $user)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user) {
return response()->json(['success'=>false, 'message' => 'Login Fail, please check email']);
}
if (!Hash::check($password, $user->password)) {
return response()->json(['success'=>false, 'message' => 'Login Fail, pls check password']);
}
return response()->json(['success'=>true,'message'=>'success', 'data' => $user]);
}
sorry for my english
This is because your laravel app always return 200 HTTP responses and this causes the .then( ... ) in the frontend to always be executed.
Either in the .then( ... ) your check the success value on the response that your Laravel has set, like this:
this.user.append("email", this.form.email);
this.user.append("password", this.form.password);
this.axios.post('http://127.0.0.1:8000/api/login', this.user).then(response => {
if (response.data.success === false) {
// handle the error and stop the code with a return
this.handleError();
return;
}
localStorage.setItem("Name", response.data.first_name);
this.$router.push('/userDashboard/Dashboard')
});
OR, you can also in Laravel throw a 401 or 400 response to say the login failed which will throw an exeception in the frontend, that you can catch with .then( ... ).catch( ... ).
That is the most clean way, because no need to send 'success' => true true anymore, since the HTTP code will be the source of truth with what happend.
public function login(Request $request, User $user)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user || !Hash::check($password, $user->password)) {
// never tell the person if it's email or password, always say it's one of both for security reasons
return response(401)->json(['message' => 'Login Fail, please check email or password']);
}
return response()->json(['data' => $user]);
}
Last thing, I don't understand how this.user.append("email", this.form.email); works, because this.user seems to just be a simple object, so there isn't any append method on it.
So unless I'm missing something here, the best thing should just be to do:
const user = {
email: this.form.email,
password: this.form.password
}
// OR, make a copy
const user = { ...this.form }
// then send the user var to axios
this.axios.post('your url', user).then( ... )

Why does promise go into the .then() when the response is an error? - Laravel

I am making a SPA in Laravel with vue.js and vuex and vue router. I made an action in my store for logging, but when I log in with invalid credentials something really strange happens. It works fine when I log in with the right credentials.
So it debugs the following
login
app.js:279 POST http://127.0.0.1:8000/api/auth/login 401
(Unauthorized)
app.js:58018 login succes
app.js:58023 login failed
app.js:43201 Uncaught (in promise) NavigationDuplicated {_name:
"NavigationDuplicated", name: "NavigationDuplicated", message:
"Navigating to current location ("/") is not allowed", stack: "Error↵
at new NavigationDuplicated (http://127.…)↵ at
http://127.0.0.1:8000/js/app.js:57159:12"} message: "Navigating to
current location ("/") is not allowed" name: "NavigationDuplicated"
_name: "NavigationDuplicated" stack: "Error↵ at new NavigationDuplicated (http://127.0.0.1:8000/js/app.js:43124:14)↵ at
HTML5History.confirmTransition
(http://127.0.0.1:8000/js/app.js:43240:18)↵ at
HTML5History.transitionTo (http://127.0.0.1:8000/js/app.js:43184:8)↵
at HTML5History.push (http://127.0.0.1:8000/js/app.js:43515:10)↵ at
http://127.0.0.1:8000/js/app.js:43929:22↵ at new Promise
()↵ at VueRouter.push
(http://127.0.0.1:8000/js/app.js:43928:12)↵ at
http://127.0.0.1:8000/js/app.js:57159:12"
proto: Error
The thing that is crazy to me is that the promise goes into the .then() and console.logs "login succes"? It shouldn't ever get in the .then() right? Because the credentials are wrong, so it should just go for the .catch(). But what is even more strange is that it does nog debug the second console.log(response.data) in the .then()???? Also I do not understand the Navigation Duplicated.
Credentials is just an {username, password}. I am using JWT and the /login route leads to the standard jwt authcontroller login method.
Login.vue component method
methods: {
login() {
this.$store
.dispatch("tryLogin", this.form)
.then(response => {
this.$router.push({ path: "/home" });
})
.catch(error => {
this.logginError = error;
});
}
}
Store action
tryLogin(context, credentials) {
context.commit("login");
console.log("login");
return new Promise((resolve, reject) => {
axios
.post("/api/auth/login", credentials)
.then(response => {
console.log("login succes");
console.log(response.data);
context.commit("loginSucces", response.data);
resolve(response.data);
})
.catch(error => {
console.log("login failed");
context.commit("loginFailed", error);
reject(error);
});
});
}
AuthController login function
/**
* Get a JWT via given credentials.
*
* #return \Illuminate\Http\JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (!$token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
Ok, I will try to explain (sorry for my english) The following is working fine, when you login with wrong credential it will return a nice JSON response:
if (!$token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
That is is not a failure, for that reason it enters to .then and print 401 (Unauthorized)
then it print console.log("login succes") and then when it try to call the context.commit("loginSucces", response.data); it fails and will go to the catch and say app.js:58023 login failed.
You can fix this just asking in the .then
axios
.post("/api/auth/login", credentials)
.then(response => {
if (response.data.status === "error") {
console.log(response.data);
}
else{
context.commit("loginSucces", response.data);
resolve(response.data);
}
})

Laravel API - Authentication works just after reloading the page

I am trying to build a Single Page Application (SPA) using VueJS as a front-end and Laravel as a back-end.
I am using laravel's passport to manage the authentication tokens etc.
The problem: After login I have to reload the page to be successfully authenticated.
Login method
data() {
return {
email: '',
password: '',
}
},
methods: {
login() {
var data = {
client_id: 2,
client_secret: '****************************',
grant_type: 'password',
username: this.email,
password: this.password
}
// send data
this.$http.post('oauth/token', data)
.then(response => {
// authenticate the user
this.$store.dispatch({
type: 'authenticate',
token: response.body.access_token,
expiration: response.body.expires_in + Date.now()
})
// redirect after successful login
if (this.$route.query.from)
this.$router.push(this.$route.query.from)
else
this.$router.push('/feed')
})
}
}
Get the user information from the backend (just works after refreshing the page)
setUser () {
// this route throws 'unauthenticated' error
// and works only after refreshing the page
this.$http.get('api/users/')
.then(response => {
this.$store.dispatch({
type: 'setUser',
id: response.body.id,
email: response.body.email,
name: response.body.name
})
})
}
}
Vuex store
export default new Vuex.Store({
state: {
isAuth: !!localStorage.getItem('token'),
user: {
id: localStorage.getItem('id'),
email: localStorage.getItem('email'),
name: localStorage.getItem('name')
}
},
getters: {
isLoggedIn(state) {
return state.isAuth
},
getUser(state) {
return state.user
}
},
mutations: {
authenticate(state, { token, expiration }) {
localStorage.setItem('token', token)
localStorage.setItem('expiration', expiration)
state.isAuth = true
},
setUser(state, { id, email, name }) {
localStorage.setItem('id', id)
localStorage.setItem('email', email)
localStorage.setItem('name', name)
state.user.id = id
state.user.email = email
state.user.name = name
}
},
actions: {
authenticate: ({ commit }, { token, expiration }) => commit('authenticate', { token, expiration }),
setUser: ({ commit }, { id, email, name }) => commit('setUser', { id, email, name })
}
})
Laravel route
Route::group(['middleware' => 'auth:api'], function() {
Route::get('/users', 'UsersController#users');
});
Laravel function
public function users(Request $request)
{
return $request->user();
}
The error message
When I reload the page the error message disappears and I am successfully authenticated.
I would be very happy for any kind of help!
Thanks to Frank Provost I figured out the answer. In case anybody else comes across the same problem:
I was not passing the token with every request.
I had to change this
Vue.http.headers.common['Authorization'] = 'Bearer ' + Vue.auth.getToken()
to this
Vue.http.interceptors.push((request, next) => {
request.headers.set('Authorization', 'Bearer ' + Vue.auth.getToken())
request.headers.set('Accept', 'application/json')
next()
})
Now, everything works as expected - no need to refresh the url.

Laravel 5.2: Ajax login not working on live server, but working fine on localhost. Auth not working on live server

I am making a project in laravel 5.2
I have an issue.
this is a school management system where admin/teachers/students login to see their dashboard.
I have made a login page where username and email is given and users can login.
I have my own table for site users named "systemusers".
login is working fine on localhost but its not working on live server.
Auth is not working and users are redirected to login page again
JQUERY CODE:
function loginForm(formID){
//Empty validation errros
$(".errors").html("");
$(".failure").html("");
//Form error flag
var form_error = false;
var form_id = document.getElementById(formID);
var form_data = new FormData(form_id);
$("#"+formID+" input").each(function(key,value){
//Get ids
var id = $(this).attr('id');
if($.trim(this.value) == '' )
{
$("."+id).html("Empty");
form_error = true;
}
else{
if( id == 'username' )
{
var email = $("#username").val();
if( !isEmail(email) )
{
$("."+id).html("Email not Valid");
form_error = true;
}
}
else{
$("."+id).html("");
}
}
});
if( form_error === false )
{
$("#login-btn").prop("disabled", true);
//Run Ajax
$.ajax({
url:'loginFormSubmit',
method:'POST',
data:form_data,
cache:false,
contentType:false,
processData:false,
success:function(html)
{
//alert(html);
if($.trim(html) == 'ERROR-PASS')
{
$(".failure").html("Ivalid Password");
$("#login-btn").prop("disabled", false);
}
else if($.trim(html) == 'ERROR-EMAIL')
{
$(".failure").html("Email not Registered");
$("#login-btn").prop("disabled", false);
}
else
{
//alert(html);
window.location.replace("schoolsys/dashboard/");
}
}
});
}
return false;
}
LOGIN CONTROLLER FUNCTION CODE
public function postLoginUser()
{
//Get the email address posted via Ajax request.
$ajax_email = $_POST["email"];
$ajax_pass = $_POST["password"];
//Check if the email is registered.
$user = $this->systemuser->where("email", "=", $ajax_email)->first();
//If email is matched
if($user )
{
//Match the passwords
if( Hash::check($ajax_pass, $user->password) )
{
$loggedIn = Auth::login($user);
echo "LOGIN-SUCCESS";
}
else{
echo "ERROR-PASS";
}
}
else{
echo "ERROR-EMAIL";
}
DASHBOARD CONROLLER FUNCTION:
public function index()
{
if(!Auth::check())
{
return redirect()->route("login")->withErrors(["Please Login First"]);
}else{
return view("Dashboard");
}
}
ROUTES:
<?php
//Dashboard Route
Route::group(["middleware" => ["web", "auth"]], function(){
Route::get("/dashboard",
[
"as" => "dashboard",
"uses" => "DashboardController#index"
]);
});
//Login View Route
Route::group(["middleware" => ["web"]], function(){
Route::get("/login",
[
"as" => "login",
"uses" => "ajaxLoginController#loginView"
]);
//Ajax - Login Form
Route::post('/loginFormSubmit', 'ajaxLoginController#postLoginUser');
});
//Post Login Form - Double check
Route::post("/post-user-login",
[
"as" => "postLogin",
"uses" => "DashboardController#doubleCheckpostLoginUser"
]);
//Logout Route
Route::get("/logout",
[
"as" => "logout",
"uses" => "DashboardController#logout"
]);
//Add Admin Route
Route::get("/add-admin",
[
"as" => "add-admin",
"uses" => "DashboardController#addAdmin"
]);
//Ajax - Add Admin Form
Route::post("/create-admin", "DashboardController#ajaxPostAdmin")
?>

Parse Javascript - Relation is not a function

I'm trying to understand how relation works and i did wrote this simple script:
var Parse = require('parse/node');
Parse.initialize('myAppId');
Parse.serverURL = 'http://localhost:1337/parse';
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('username', 'the_username');
userQuery.find()
.then(user => {
return user;
})
.then(user => {
var Systems = Parse.Object.extend("systems");
var systemQuery = new Parse.Query(Systems);
systemQuery.equalTo('customer', 'myCustomer');
systemQuery.find()
.then(system => {
var relation = user.relation('systems_ref'); // HERE I GET RELATION IS NOT A FUNC
relation.add(system);
console.log('Adding relation');
user.save()
.then(response => console.log('user saved'))
.catch(error => console.log('Error saving', error));
}).catch(error => console.log('Error find system', error));
});
But in the line where i try to get user.relation i have the error "Relation is not a function".
I have look others example on how to create a relation, but i dont see difference in my code...
I have the user (that is a sublcass of ParseObject), and on it i'm trying to access relation method...
You may use it as follows:
To add the Post to User with the JavaScript SDK:
var user = Parse.User.current();
var relation = user.relation("posts");
relation.add(post);
user.save();

Resources