I have created login page and for accessing data I have used JSON File. when I click on the login() btn , userdata should match with the server data. But I am getting error and I am not able to send the $http response to the client side from server. If the rows with that name and password matches it return true, if not return false. then the client should parse this response.
But I don't know how What I am doing wrong?
Any help / advice would be greatly appreciated.
AngualJS:
/* server-side */
app.factory('auth', function ($http, session) {
var authService = {};
authService.login = function (username, password) {
var response;
$http.post('http://localhost:3000/loginfo')
.then(
function successCallback(response) {
var user = response.data;
console.log(user);
if (user.username == username && user.password == password) {
var signinfo = response.data;
console.log(response.data);
} else {
console.log('Error');
}
})
};
authService.isAuthenticated = function () {
return {
isAuthenticated: false,
user: null
}
};
return authService;
});
/* client-side */
app.controller('credientials', function ($scope, $http, auth) {
$scope.userCred = {
username: '',
password: ''
};
/*-----Form Submition-----*/
$scope.log = function (userCred) {
auth.isAuthenticated = true;
auth.login(userCred.username, userCred.password, function (response) {
if (response.success) {
console.log('success');
} else {
console.log('Error');
}
})
};
});
Related
I am trying to achieve user login
and logout using angularJS and web Api
But the server always return badrequest (400)
exception
the error is coming from this bit of code
AuthApp.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
var authServiceFactory = {};
var _authentication =
{
isAuth: false,
userName: ""
};
// this is the login function
authServiceFactory.login = function (loginData)
{
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password; //is not working
//var data = { username: loginData.userName, password: loginData.password, grant_type: "password" }; // I try this and is not working too
//data = $.param(data);
// how should I format my data for the web API to understand
var deferred = $q.defer();
// alert(data);
$http.post('/token', data, {
header: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: response.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err) {
// _logout();
deferred.reject(err);
});
return deferred.promise;
}
authServiceFactory.logout = function ()
{
localStorageService.remove("authenticationData");
_authentication.isAuth = false;
_authentication.userName = "";
}
return authServiceFactory;
}]);
using postman to further see the error
this appears
{ "error": "unsupported_grant_type" }
I made google search but still no solution; how can I resolve this issue?
thanks in advance!!
I am trying to achieve user login
and logout using angularJS and web Api
But the server always return badrequest (400)
exception
the error is coming from this bit of code
AuthApp.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
var authServiceFactory = {};
var _authentication =
{
isAuth: false,
userName: ""
};
// this is the login function
authServiceFactory.login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
// alert(data);
$http.post('/token', data, {
header: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: response.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err) {
// _logout();
deferred.reject(err);
});
return deferred.promise;
}
authServiceFactory.logout = function ()
{
localStorageService.remove("authenticationData");
_authentication.isAuth = false;
_authentication.userName = "";
}
return authServiceFactory;
}]);
using postman to further see the error
this appears
{ "error": "unsupported_grant_type" }
I'm doing this login exercise where users can login and post notes, and view the notes that they've posted. My problem is when I logout and login with a different user I see the notes from the previous user.
Here's an illustration:
I log in with a different user then this shows up:
I restart the page and the appropriate note shows up:
The controller for this:
exports.homeController = function ($scope, $location, $q, $users, $window, $notes, $http) {
var auth = function () {
var userInfo = $users.getUserInfo()
if (userInfo) {
return $q.when(userInfo)
} else {
return $q.reject({ authenticated: false })
}
}
$scope.userInfo = auth()
myNotes($scope.userInfo.$$state.value.accessToken) // I invoke my function to get the notes for each specific user but it doesn't seem to work.
$scope.logout = function () {
$users.logout()
.then(function (results) {
$scope.userInfo = null
$scope.myNotes = null
$location.path('/')
}, function (err) {
console.log(err)
})
}
$scope.notes = {
notes: ''
}
$scope.postNote = function () {
$notes.postNotes($scope.userInfo.$$state.value.accessToken, $scope.notes)
.then(function (result) {
$scope.myNotes.push($scope.notes)
$scope.notes = ''
}, function (err) {
console.log(err)
})
}
function myNotes (user_id) {
$notes.getMyNotes(user_id)
.then(function (result) {
console.log(result)
$scope.myNotes = result.data
}, function (err) {
console.log(err)
})
}
}
This is the app https://login-sys.herokuapp.com/
I've found your non-minified code for the services.
Based on that I think the problem is that you declare var deferred = $q.defer() one time in the $notes service.
I think it should be "renewed" every time the service methods are called:
function getMyNotes (user_id) {
var deferred = $q.defer();
$http.get('/api/myNotes/' + user_id + '?access_token=' + user_id)
.then(function (result) {
deferred.resolve(result)
}, function (err) {
deferred.reject(err)
});
return deferred.promise
}
Similarly in postNotes.
The second time you return the same promise with the same value, so your homeController's getMyNotes function will get the same result despite the $notes service making a new request.
In the $users service's logout and signup functions you are already using it correctly.
Background: I am creating an app using node/express as my backend, mongo as the database, and angular as the front end. I am using jsonwebtoken to authenticate the user. Once the user logs in, a token is stored in the local storage, which is used to authenticate all requests. After the user logs in,
the name and username is retrieved via Auth.getUser(), which is an angular factory method that gets data from the backend. Each request
Problem: I am unable to get the user to redirect to the home page, because the following code does not run:
vm.login = function() {
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.then(function(data) {
Auth.getUser()
.then(function(data) {
vm.user = data.data;
});
if (data.success) {
$location.path('/');
} else {
vm.error = data.message;
console.log(vm.error);
}
});
}
I do not get redirected to the homepage, although I also do not get any message either in the dev console or my terminal.
When I check the local storage via the dev console, I do not have the token. However, I am able to login/signup/post data successfully using POSTMAN. I think the problem can be fleshed out via the following steps:
1. The user logs in, and the token is stored in the local storage
2. Auth.getUser() is suppose to request for the user data from the backend.
3.Each request requires the token to be verified via the jsonwebtoken.verify() method.
4.For some reason, the token is not sent to my backend, so this does not run:
api.use(function(req,res,next) {
console.log('someone tried to access a secure page');
var token =
req.body.token || req.param('token') || req.headers['x-access-token'];
if (token) {
//code
} else {
res.status(403).send({ success: false, message: "No Token Provided"});
Here are what I deem the relevant files:
backend:
var mongoose = require('mongoose');
var User = require('../models/user.js');
var Story = require('../models/story.js');
var config = require('../../config/config.js');
var jsonWebToken = require('jsonwebtoken');
var sessionSecret = config.sessionSecret;
function createToken(user) {
var token = jsonWebToken.sign({
id: user._id,
name: user.name,
username: user.username
}, sessionSecret, {expiresInMinutes: 1440});
return token;
}
module.exports = function(app, express) {
var api = express.Router();
api.post('/login', function(req,res) {
User.findOne({username: req.body.username})
.select('password').exec(function(err, user) {
if (err) {
res.send(err);
return;
} else {
if (!user) {
res.send('user does not exist!');
} else {
var isPasswordValid = user.comparePassword(req.body.password);
if (!isPasswordValid) {
res.send('wrong password!');
} else {
var token = createToken(user);
res.json(
{success:true,
message:'successfully logged in!',
token: token});
}
}
}
})
});
api.use(function(req,res,next) {
console.log('someone tried to access a secure page');
var token =
req.body.token || req.param('token') || req.headers['x-access-token'];
if (token) {
jsonWebToken.verify(token, sessionSecret, function(err, decoded) {
if(err) {
res.status(403).send({ success: false, message: "Failed to authenticate user"});
} else {
//
req.decoded = decoded;
next();
}
});
} else {
**//*****the message sent to my frontend*********
res.status(403).send({ success: false, message: "No Token Provided"});
}
});
api.get('/me', function(req,res) {
res.send(req.decoded);
})
app.use('/api', api);
}
frontend:
Angular factory: retrieves data from the backend
var authService = angular.module('authService', []);
authService.factory('Auth', function($http, $location, $q, AuthToken) {
var authFactory = {};
authFactory.login = function(username,password) {
return $http.post('/api/login', {
username: username,
password: password
}).success(function(data) {
AuthToken.setToken(data.token);
return data;
})
}
authFactory.getUser = function() {
if (AuthToken.getToken()) {
return $http.get('/api/me');
} else {
return $q.reject({message: 'unable to get data'});
}
}
return authFactory;
});
authService.factory('AuthToken', function($window) {
var authTokenFactory = {};
authTokenFactory.getToken = function() {
return $window.localStorage.getItem('token');
}
authTokenFactory.setToken = function(token) {
if (token) {
$window.localStorage.setItem('token', token);
} else {
$window.localStorage.removeItem('token');
}
}
return authTokenFactory;
});
authService.factory('AuthInterceptor', function($q, $location, AuthToken) {
var interceptorFactory = {};
interceptorFactory.request = function(config) {
var token = AuthToken.getToken();
if(token) {
config.headers['x-access-token'] = token;
}
return config;
};
interceptorFactory.responseError = function(response) {
if (response.status === 403) {
$location.path('/login');
return $q.reject(response);
}
}
});
mainController:
angular.module('MainController', [])
.controller('mainController', ['$rootScope','$location','Auth', function($rootScope,$location, Auth) {
var vm = this;
vm.isLoggedIn = Auth.isLogged();
$rootScope.$on('$routeChangeStart', function() {
vm.isLoggedIn = Auth.isLogged();
Auth.getUser().then(function(data) {
vm.user = data.data;
})
})
vm.login = function() {
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.then(function(data) {
Auth.getUser()
.then(function(data) {
vm.user = data.data;
});
if (data.success) {
$location.path('/');
} else {
vm.error = data.message;
console.log(vm.error);
}
});
}
index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<base href="/">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://code.angularjs.org/1.4.0-rc.1/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.0-rc.1/angular-route.min.js"></script>
<!--angular services -->
<script src="app/auth/authService.js"></script>
<!--angular controllers -->
<script src="app/controllers/mainController.js"></script>
<script src="app/app.routes.js"></script>
<script src="app/app.js"></script>
</head>
<body>
<div class="container">
<div ng-view></div>
</div>
</body>
</html>
login.html:
<div class="container" ng-controller="mainController as login">
<form method="post" ng-submit="login.login()">
username: <input type="text" name="username" ng-model="login.loginData.username">
password: <input type="password" name="password" ng-model="login.loginData.password">
<button type="submit" class="btn btn-success">submit</button>
</form>
</div>
further code will be made available upon request. I will be truly grateful for any help as I have spent countless hours trying to solve this problem.
I guess the redirection is happening before the getting the data:
vm.login = function() {
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.then(function(resp) { // <------changed the arg to 'resp'
Auth.getUser()
.then(function(data) {
vm.user = data.data;
if (resp.success) { // <------put the condition here with 'resp'
$location.path('/');
} else {
vm.error = resp.message;
console.log(vm.error);
}
});
});
}
Another change i can suggest you to use .then() instead of .success() here:
return $http.post('/api/login', {
username: username,
password: password
}).then(function(data) { // <--------change to `.then()`
AuthToken.setToken(data.token);
return data;
})
My friend and I are building an app - my friend is on the backend (Node.js) and I'm on the front.
He implemented sessions on his end and provided me with the URL I need to call to log in. For example, a POST request
http://ourapp.heroku.com/login
with which username and password are passed.
On my side, in the Angular app, I create a login page which calls an Angular service when Login is clicked. If this service receives a 200 from the server, it does:
$cookieStore.put(cookieNames.LOGGED_IN_COOKIE, true);
$state.go('home', {}, {reload: true});
The problem is that we're having weird issues with the app on the front end. For example logging in and out often don't work. Also, users are able to go to pages even after they log out. I figured out (at least I think) that I'm not properly storing the Cookie I receive from the server, I'm only storing my own.
This whole Angular thing is still weird to me, because in PHP or Python apps you get a page request from the client and verify if he's logged in before sending him the page he requested. In Angular it's different - the user has all of the pages already. So how do I limit what he can see without logging in and how to I properly keep track of the server's cookie?
If you use ui-router, you can do something similar to this:
First introduce some kind of access-levels to your states
$stateProvider
.state('admin', {
url: "/admin",
templateUrl: "/app/views/admin.html",
controller: "AdminController",
data: {
accessLevel: 'admin'
}
})
then you have to check on state change, if your logged in user has the required access-level:
You can create an auth service which implements your logic to log your user in, as example you can use this service
angular.module('app')
.factory("AuthService", ["$rootScope", "$http", "AuthSession", "AuthHttpBuffer", "AUTH_EVENTS", function ($rootScope, $http, AuthSession, AuthHttpBuffer, AUTH_EVENTS) {
function loginFailed() {
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginFailed);
};
AuthSession.load();
$rootScope.$on('$stateChangeStart', function (event, nextState) {
if (nextState.data && nextState.data.accessLevel && !service.isAuthorized(nextState.data.accessLevel)) {
event.preventDefault();
$rootScope.$broadcast('auth-change', AUTH_EVENTS.loginRequired, nextState.name);
}
});
var service = {
login: function (credentials) {
return $http
.post('/api/account/login', credentials)
.success(function (data, status) {
if ((status < 200 || status >= 300) && data.length >= 1) {
loginFailed();
return;
}
AuthSession.create(data.AccessToken, data.User);
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginSuccess);
AuthHttpBuffer.retryAll();
}).error(function (data, status) {
loginFailed();
});
},
cancel: function () {
AuthHttpBuffer.rejectAll();
},
logout: function () {
AuthSession.destroy();
$rootScope.$broadcast("auth-change", AUTH_EVENTS.logoutSuccess);
},
isAuthenticated: function () {
return (AuthSession.token !== null);
},
isAuthorized: function (accessLevel) {
if (!accessLevel) return true;
return (this.isAuthenticated() && AuthSession.user.UserRoles.indexOf(accessLevel) !== -1);
}
}
return service;
}]);
and your AuthSession service:
angular.module('app')
.factory("AuthSession", ["$rootScope", "$window", "AUTH_EVENTS", function ($rootScope, $window, AUTH_EVENTS) {
var sessionService = {
user: null,
token: null,
//load the stored session data
load: function () {
var user = ...yourdata... //TODO implement load user data;
var token = ...yourdata... //implement load user data;
if (!user || !token) return;
if (!this.checkTokenExpiration(token)) return;
this.user = user;
this.token = token;
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginSuccess);
},
//save the current data to the session storage
save: function () {
//TODO save your userdata/token etc.
},
//create the current user with the assosiated token
create: function (token, user) {
this.token = token;
this.user = user;
if (!angular.isArray(this.user.UserRoles))
this.user.UserRoles = [this.user.UserRoles];
this.save();
},
//destroy an user with all assosiated data
destroy: function () {
this.token = null;
this.user = null;
//TODO clear your saved data here
},
//check if the supplied access token data is expired
checkTokenExpiration: function (token) {
if (token === undefined || token === null) return false;
var retval = (new Date(token.TokenExpires).getTime() > new Date().getTime());
if (retval === false) {
sessionService.destroy();
$rootScope.$broadcast("auth-change", AUTH_EVENTS.sessionTimeout);
}
return retval;
}
}
return sessionService;
}]);
and the constants:
angular.module('app')
.constant('AUTH_EVENTS', {
loginSuccess: 'auth-login-success',
loginFailed: 'auth-login-failed',
logoutSuccess: 'auth-logout-success',
loginRequired: 'auth-login-required',
sessionTimeout: 'auth-session-timeout',
notAuthorized: 'auth-not-authorized'
});
If you want be able to catch urls, where you haven't the right accesrights, you can send the request to a http buffer:
angular.module('app')
.factory('AuthHttpBuffer', ["$injector", function ($injector) {
/** Holds all the requests, so they can be re-requested in future. */
var buffer = [];
/** Service initialized later because of circular dependency problem. */
var $http;
function retryHttpRequest(config, deferred) {
function successCallback(response) {
deferred.resolve(response);
}
function errorCallback(response) {
deferred.reject(response);
}
$http = $http || $injector.get('$http');
$http(config).then(successCallback, errorCallback);
}
return {
/**
* Appends HTTP request configuration object with deferred response attached to buffer.
*/
append: function (config, deferred) {
buffer.push({
config: config,
deferred: deferred
});
},
/**
* Abandon or reject (if reason provided) all the buffered requests.
*/
rejectAll: function (reason) {
if (reason) {
for (var i = 0; i < buffer.length; ++i) {
buffer[i].deferred.reject(reason);
}
}
buffer = [];
},
/**
* Retries all the buffered requests clears the buffer.
*/
retryAll: function () {
for (var i = 0; i < buffer.length; ++i) {
retryHttpRequest(buffer[i].config, buffer[i].deferred);
}
buffer = [];
}
};
}]);
and if you haven't enough you can also add an interceptor, that triggers an auth change event, if the server response is unauthorized:
angular.module('app')
.factory('AuthInterceptor', ["$rootScope", "$q", "AuthSession", "AuthHttpBuffer", "AUTH_EVENTS", function ($rootScope, $q, AuthSession, AuthHttpBuffer, AUTH_EVENTS) {
return {
request: function (config) {
config.headers = config.headers || {};
if (AuthSession.token) {
config.headers.Authorization = 'Bearer ' + AuthSession.token.TokenKey;
}
return config;
},
responseError: function (rejection) {
if (rejection.status === 401) {
var deferred = $q.defer();
AuthHttpBuffer.append(rejection.config, deferred);
if (AuthSession.token) {
$rootScope.$broadcast('auth-change', AUTH_EVENTS.notAuthorized);
} else {
$rootScope.$broadcast('auth-change', AUTH_EVENTS.loginRequired);
}
return deferred.promise;
}
return $q.reject(rejection);
}
}
}]);
this interceptor also adds a session token to all requests if available.
to use this interceptor, you have to add the following two lines to your app.config():
$httpProvider.defaults.withCredentials = true;
$httpProvider.interceptors.push("AuthInterceptor");