How can i get data from service in angular - javascript

I have LoginController and securityService.
This is LoginCtrl
// place the message if something goes wrong
$scope.authMsg = '';
$scope.login = function () {
$scope.authMsg = '';
var loginData = {email: $scope.account.email, password: $scope.account.password};
securityService.login(loginData);
};
This is securityService
login: function (logData) {
var _vm = this;
$http
.post('/api-token-auth/', logData)
.then(function (response) {
// assumes if ok, response is an object with some data, if not, a string with error
// customize according to your api
if (!response.data.token) {
_vm.authMsg = 'Incorrect credentials.';
} else {
$cookieStore.put('djangotoken', response.data.token);
$http.defaults.headers.common.Authorization = 'JWT ' + response.data.token;
$http.get('/api/account/restricted/').then(function (response) {
authService.loginConfirmed();
_vm.currentUser = response.data;
$rootScope.currentUser = response.data;
});
}
}, function (x) {
_vm.authMsg = 'Server Request Error';
});
},
This login is working fine but my problem is i don't know how can get the authMesg from service to controller because that is async. Everytime i get blank message in case of invalid login

you need to use promise service of angular to make you controller and service syn
login: function (logData) {
var _vm = this,d= $$q.defer();
$http
.post('/api-token-auth/', logData)
.then(function (response) {
// assumes if ok, response is an object with some data, if not, a string with error
// customize according to your api
if (!response.data.token) {
_vm.authMsg = 'Incorrect credentials.';
} else {
$cookieStore.put('djangotoken', response.data.token);
$http.defaults.headers.common.Authorization = 'JWT ' + response.data.token;
$http.get('/api/account/restricted/').then(function (response) {
authService.loginConfirmed();
_vm.currentUser = response.data;
$rootScope.currentUser = response.data;
});
}
d.resolve(vm.authMsg);
}, function (x) {
_vm.authMsg = 'Server Request Error';
d.reject(vm.authMsg);
});
},
In controller you need to resolve this promise
securityService.login(loginData).then(function(data){
consol.log(data); // get success data
},function(error){
consol.log(data); // get error message data
})
and inject $q in your service.

This will give you authMsg
securityService.login(loginData).authMsg
But follow #Vigneswaran Marimuthu comments, that is best practice.

Related

Pass functions to front-end angular from back-end node

Introduction
I need to verify if a email address is within a API, if so allow a user to enter a section someone cant if they are not a user.
I have built the back-end node code to verify this.
I have 3 functions build in my back-end (node, express).
The first
Gets data from a front-end form (Angular) post and then uses promise to make the value available to the third function.
The second
This function authenticates and gets my API key and using promise makes this function available to the third function.
The third
This function uses the data from the first (email address) and the API key from the second and post to a API endpoint, If the email is present on the API you get pass, if not fail.
Process
A user enters a email on the front end Angular, hits login then this email is passed to the three back-end functions, then it will pass or fail in the third function.
If this passes I wish to pass $scope.EmailTrue= true; to my Angular controller so that I can ng-hide or ng-show buttons on my front-end.
I was thinking of maybe a simple post to my front-end, but I am new to angular and node so I am unaware if there is a different way of doing this.
Node back-end (3 functions)
//---------------------------------- Grab the packages we need and set variables ---------------------------------------
//----------------------------------------------------------------------------------------------------------------------
var express = require('express');
var request = require('request');
var nodePardot = require('node-pardot');
var bodyParser = require('body-parser');
var rp = require('request-promise');
var app = express();
var port = process.env.PORT || 8080;
// Credential's for pardot API
var password = 'password';
var userkey = 'userkey';
var emailAdmin = 'admin#admin.com';
// Start the server
app.listen(port);
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({extended: true})); // support encoded bodies
console.log('Test server started! At http://localhost:' + port); // Confirms server start
//---------------------------------- Function to get front end form posted data LOGIN form ----------------------------------------
//----------------------------------------------------------------------------------------------------------------------
var firstFunction = function () {
return new Promise (function (resolve) {
setTimeout(function () {
app.post('/back-end/test', function (req, res) {
console.log(req.body);
var login = req.body.LoginEmail;
res.send(login);
resolve({
data_login_email: login
});
});
console.error("First done");
}, 2000);
});
};
//---------------------------------- Function to get API key from Pardot (AUTHENTICATION) ------------------------------
//----------------------------------------------------------------------------------------------------------------------
var secondFunction = function () {
return new Promise (function (resolve) {
setTimeout(function () {
nodePardot.PardotAPI({
userKey: userkey,
email: emailAdmin,
password: password,
DEBUG: false
}, function (err, client) {
if (err) {
// Authentication failed
console.error("Authentication Failed", err);
} else {
// Authentication successful
var api_key = client.apiKey;
console.log("Authentication successful !", api_key);
resolve({data_api: api_key});
}
});
console.error("Second done");
}, 2000);
});
};
//---------------------------------- Function to post data to Pardot ---------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
function thirdFunction(result) {
return new Promise (function () {
setTimeout(function () {
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded'
};
// Configure the request
var api = result[1].data_api;
var login_email = result[0].data_login_email;
var options = {
url: 'https://pi.pardot.com/api/prospect/version/4/do/read',
method: 'POST',
headers: headers,
form: {
'email': login_email,
'user_key': userkey,
'api_key': api
},
json: true // Automatically stringifies the body to JSON
};
// Start the request
rp(options)
.then(function (parsedBody) {
console.error("pass");
// $scope.FormLogin = true;
})
.catch(function (err) {
console.error("fail");
});
console.error("Third done");
}, 3000);
}
);
}
// sequence of functions
Promise.all([firstFunction(), secondFunction()])
.then(thirdFunction);
Angular controller
FirstModule.controller('LoginController', function TestController($scope, $http) {
$scope.LoginForm = function () {
var data = {
LoginEmail: $scope.formData.LoginEmail
};
$http({
url: 'http://localhost:8080/back-end/test',
method: "POST",
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (data) {
$scope.formData = data; // assign $scope.persons here as promise is resolved here
}).error(function (data, status) {
$scope.formData = status;
});
}
});
Angular view
<form class="col-sm-8 col-sm-offset-2">
<div>
<div class="form-group">
<label>Email*</label>
<input type="email" class="form-control col-sm-12" name="LoginEmail" placeholder="Enter valid E-mail">
</div>
<button class=""
ng-submit="LoginForm()">
Login<span class=""></span>
</button>
</div>
</form>
In Angular you can user the $http service to make an http request and then handle the response.
You can do:
$http.post('/login', {
email: 'user#email.com',
password: 'pwd'
}).then(response => {
// use http status code
if (response.status === 403) {
alert('forbidden')'
} else {
// do something
}
})

Asynchronous execution error on AWS Cognito registering method

I'm making an user management with the Amazon Web Service names Cognito.
It runs smoothly on local but it is not when I use it on a Wamp server.
I can not figure out why... maybe cause to asynchronous execution ?
I'm using $q and .then(function() { ... }); to wait for it's execution.
This is how I do in my controller :
$scope.validateForm = function() {
if (AuthService.getActifUser() == false) {
//clear local storage
$storage.remove('userData');
}
//getting the form attributes
var datafirstName = {
Name: 'custom:first_name',
Value: $scope.firstName
};
var dataLastName = {
Name: 'custom:last_name',
Value: $scope.lastName
};
var dataEmail = {
Name: 'email',
Value: $scope.email
};
var attributeFirstName = AuthService.setAttributes(datafirstName);
var attributeLastName = AuthService.setAttributes(dataLastName);
var attributeEmail = AuthService.setAttributes(dataEmail);
var attributeList = [];
attributeList.push(attributeFirstName);
attributeList.push(attributeLastName);
attributeList.push(attributeEmail);
// signing try
AuthService.signin($scope.username, $scope.password, attributeList)
.then(function(res) {
// save username in local storage
$storage.set('userData', $scope.username);
// go to the verification page
routeService.goToView('/users-confirmation');
}, function(res) {
console.log(res);
);
}
And in the AuthService Factory :
AuthService.signin = function(username, password, attributeList) {
var deferred = $q.defer();
userPool.signUp(username, password, attributeList, null, function(err, result) {
if (err) {
alert(err);
deferred.reject('registering failled.');
}
console.log('successfully registered.');
deferred.resolve('successfully registered.');
});
return deferred.promise;
};
Unfortunatelly the routeService.goToView() method is never called.
Hope someone know why ?
Could you please add a handler for the promise rejection to ensure that the promise is not being rejected?
It could be that your promise is being rejected and the error hidden. Also, where is invalidPassword being defined?

How to call angular service method from controller?

I'm bit new in angular. I've built 'Employee Search' Service module. Here is the code...
// Service for employee search
app.service('employeeSearchService', function($http, resourceServerAddress){
this.empList = [];
// Method for clearing search employee list
this.clearEmpList = function(){
this.empList = [];
}
// Method for fetching employee search list
this.fetchEmpList = function(){
return this.empList;
}
// Method for making employee search
this.searchEmpList = function(empName){
var postData = {
empName:empName,
};
$http({
method: 'POST',
url: resourceServerAddress,
data : postData
}).then(function successCallback(response) {
console.log('Response Data : '+response);
if(response['data']['status'] === 'success'){
console.log('Response received successfully with status=success');
if(response['data']['data'].length)
{
console.log('matches found for employee search');
this.empList = response;
}
else
{
console.log('no matches found for employee search');
this.empList = [];
}
}
if(response['data']['status'] === 'error'){
console.log('Response received successfully with status=error');
}
}, function errorCallback(response) {
console.log('Error occur at time of processing request');
});
}
});
Then, I'm using following code in my Controller to fetch data from this Service module.
employeeSearchService.searchEmpList(empName);
empSearchResponseList = employeeSearchService.fetchEmpList();
console.log('Search response from server module : '+empSearchResponseList);
I can see from my chrome console that, I'm getting data from my AJAX call with all console message from Service module. But, can't able to catch those data in Controller variable.
I think the way, I'm using 'searchEmpList()' & 'fetchEmpList()' in my controller it's not the right way. But, can't able to find out how to modify that one.
Need Some Guidance -.-
--- Controller Code updated ----
// Controller for application Home route
app.controller("HomeController", function($scope, $state, $location, $ionicHistory, $ionicSideMenuDelegate, $http, resourceServerAddress, employeeSearchService) {
console.log('At home controller');
// Check application session. If it's found not exist redirect user to login page
if(window.localStorage.getItem("access_token") === "undefined" || window.localStorage.getItem("access_token") === null) {
$ionicHistory.nextViewOptions({
disableAnimate: true,
disableBack: true
});
console.log('Redirecting user to login page-222');
$state.go("login");
}
$scope.empName = '';
$scope.alertMsgBox = false;
$scope.alertMsgText = '';
$scope.employees = [];
$scope.resourceServerAddress = resourceServerAddress;
var empSearchResponseList=null;
// Method for employee search
$scope.searchEmployee = function(form){
console.log('Employee name entered : '+$scope.empName);
console.log('Employee name character length : '+$scope.empName.length);
if($scope.empName.length >= 3 ){
var postData = {
Emp_Name:$scope.empName,
access_token:window.localStorage.getItem('access_token'),
session_id:window.localStorage.getItem('session_id')
};
$http({
method: 'POST',
url: resourceServerAddress,
data : postData
}).then(function successCallback(response) {
console.log('Response Data : '+response);
if(response['data']['status'] === 'success'){
console.log('Response received successfully with status=success');
if(response['data']['data'].length)
{
console.log('matches found for employee search');
$scope.employees = response['data']['data'];
$scope.alertMsgBox = false;
}
else
{
console.log('no matches found for employee search');
$scope.alertMsgBox = true;
$scope.employees = [];
$scope.alertMsgText = 'No matches found.';
}
}
if(response['data']['status'] === 'error'){
console.log('Response received successfully with status=error');
}
}, function errorCallback(response) {
console.log('Error occur at time of processing request');
});
}
}
// Method for showing employee profile
$scope.showEmpProfile = function(empId){
console.log('HomeCtrl - click on profile image of emp id : '+empId);
// Redirecting to home page
$state.go('app.emp-profile', {empId:empId});
}
});
this also seems confusing for me.
the $http call s done asynchronously so when you call fetch it fetches an empty array.
I would do something like this
this.searchEmpList = function(empName){
var postData = {
empName:empName,
};
return $http({
method: 'POST',
url: resourceServerAddress,
data : postData
}).then(function(response) {
console.log('Response Data : '+response);
if(response['data']['status'] === 'success'){
console.log('Response received successfully with status=success');
if(response['data']['data'].length)
{
console.log('matches found for employee search');
return response['data']['data'];
}
else
{
console.log('no matches found for employee search');
return [];
}
}
if(response['data']['status'] === 'error'){
console.log('Response received successfully with status=error');
}
}, function(response) {
console.log('Error occur at time of processing request');
});
}
and in the controller
employeeSearchService.searchEmpList(empName).then(function(data){
console.log('data is ready', data);
});
Also notice that you have to return the $http in order to use .then() in the controller ( returns a promise).
Fot a great styleguide for angular check
Are you sure that you service works?
I prefer this syntax:
.service('Service', function () {
var Service = {
//methods here
}
return Service;
});
And you don't need hard work with 'this'.

NodeJs - Retrieve user information from JWT token?

Node and Angular. I have a MEAN stack authentication application where I am setting a JWT token on successful login as follows, and storing it in a session in the controller. Assigning the JWT token to config.headers through service interceptor:
var token = jwt.sign({id: user._id}, secret.secretToken, { expiresIn: tokenManager.TOKEN_EXPIRATION_SEC });
return res.json({token:token});
authservice.js Interceptor(omitted requestError,response and responseError):
authServices.factory('TokenInterceptor', ['$q', '$window', '$location','AuthenticationService',function ($q, $window, $location, AuthenticationService) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
return config;
}
};
}]);
Now I wanted to get the logged in user details from the token, How can I do that? I tried as follows, not working. When I log the error from Users.js file it's saying "ReferenceError: headers is not defined"
authController.js:
$scope.me = function() {
UserService.me(function(res) {
$scope.myDetails = res;
}, function() {
console.log('Failed to fetch details');
$rootScope.error = 'Failed to fetch details';
})
};
authService.js:
authServices.factory('UserService',['$http', function($http) {
return {
me:function() {
return $http.get(options.api.base_url + '/me');
}
}
}]);
Users.js (Node):
exports.me = function(req,res){
if (req.headers && req.headers.authorization) {
var authorization =req.headers.authorization;
var part = authorization.split(' ');
//logic here to retrieve the user from database
}
return res.send(200);
}
Do i have to pass the token as a parameter too for retrieving the user details? Or save the user details in a separate session variable as well?
First of all, it is a good practice to use Passport middleware for user authorization handling. It takes all the dirty job of parsing your request and also provides many authorization options.
Now for your Node.js code.
You need to verify and parse the passed token with jwt methods and then find the user by id extracted from the token:
exports.me = function(req,res){
if (req.headers && req.headers.authorization) {
var authorization = req.headers.authorization.split(' ')[1],
decoded;
try {
decoded = jwt.verify(authorization, secret.secretToken);
} catch (e) {
return res.status(401).send('unauthorized');
}
var userId = decoded.id;
// Fetch the user by id
User.findOne({_id: userId}).then(function(user){
// Do something with the user
return res.send(200);
});
}
return res.send(500);
}
Find a token from request data:
const usertoken = req.headers.authorization;
const token = usertoken.split(' ');
const decoded = jwt.verify(token[1], 'secret-key');
console.log(decoded);
Your are calling the function UserService.me with two callbacks, although the function does not accept any arguments. What I think you want to do is:
$scope.me = function() {
UserService.me().then(function(res) {
$scope.myDetails = res;
}, function() {
console.log('Failed to fetch details');
$rootScope.error = 'Failed to fetch details';
});
};
Also, note that the $http methods return a response object. Make sure that what you want is not a $scope.myDetails = res.data
And in your Users.js file, you are using the variable headers.authorization directly, whereas it should be req.header.authorization:
var authorization = req.headers.authorization;
According to the documentation https://github.com/themikenicholson/passport-jwt, you could use request.user. Note, I'm supposing that you are using passport with passport-jwt.
It's possible because passport during the context of an authentication is setting the request object and populating the user property. So, just access that property. You don't need to do a middleware.
Anderson anzileiro is correct. If you return the full token in the middleware code, the request is indeed populated with the user property and you can access your profile.
passport.use(
new JWTstrategy(
{
secretOrKey: process.env.ACCESS_TOKEN_SECRET,
// jwtFromRequest: ExtractJWT.fromUrlQueryParameter('secret_token')
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken()
},
async (token, done) => {
try {
return done(null, token);
} catch (error) {
done(error);
}
}
)
);
req.user will return :
{
"user": {
"username": "admin"
},
"iat": 1625920948,
"exp": 1626007348
}

Can not seem to figure out how to set a token in my request header

I am following a book tutorial, I am currently building the authentication for the app. Whenever I login correctly, I can't seem to set the token back into the request. The error I am getting is:
Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'function () {
return $window.localStorage.getItem('token');
}' is not a valid HTTP header field value.
Any help would be greatly appreciated
authService.js
angular.module('authService', [])
// ===================================================
// auth factory to login and get information
// inject $http for communicating with the API
// inject $q to return promise objects
// inject AuthToken to manage tokens
// ===================================================
.factory('Auth', function($http, $q, AuthToken) {
// create auth factory obj
var authFactory = {};
// login user
authFactory.login = function(username, password) {
// return promise obj and its data
return $http.post('/api/authenticate', {
username: username,
password: password
})
.success(function(data) {
console.log(data);
AuthToken.setToken(data.token);
return data;
});
};
// logout user by clearing token
authFactory.logout = function() {
AuthToken.setToken();
};
// check if user is logged in
// checks for local token
authFactory.isLoggedIn = function() {
if (AuthToken.getToken())
return true;
else
return false;
};
// get logged in user
authFactory.getUser = function() {
if (AuthToken.getToken())
return $http.get('/api/me', { cache : true});
else
return $q.reject({ message : 'User has no token.'});
};
return authFactory;
})
// ===================================================
// factory for handling tokens
// inject $window to store token client-side
//
//
// ===================================================
.factory('AuthToken', function($window) {
var authTokenFactory = {};
// get token out of local storage
authTokenFactory.getToken = function() {
return $window.localStorage.getItem('token');
};
// function to set token or clear token
// if a token is passed, set the token
// if there is no token, clear it from local storage
authTokenFactory.setToken = function(token) {
if (token)
$window.localStorage.setItem('token', token);
else
$window.localStorage.removeItem('token');
};
return authTokenFactory;
})
// ===================================================
// application configuration to integrate token into requests
// ===================================================
.factory('AuthInterceptor', function($q, $location, AuthToken) {
var interceptorFactory = {};
// this will happen on all http requests
interceptorFactory.request = function(config) {
// grab token
var token = AuthToken.getToken;
// if token exists add it to the header as x-access-token
if (token)
config.headers['x-access-token'] = token;
return config;
};
// happens on response errors
interceptorFactory.responseError = function(response) {
// if 403 from server
if (response.status == 403) {
AuthToken.setToken();
$location.path('/login')
}
//return the errors from server as promise
return $q.reject(response);
};
return interceptorFactory;
});
app.js
var app = angular.module('userApp', [
'ngAnimate', 'app.routes', 'authService', 'mainCtrl', 'userCtrl', 'userService']);
// app config to integrate token into req
app.config(function($httpProvider) {
// attach our auth interceptor to the http reqs
$httpProvider.interceptors.push('AuthInterceptor');
});
app.controller('mainController', function($http) {
// Bind this to view / vm-view model
var vm = this;
// define variables and objects on this
// this lets them be available to our views
// define a basic variable
vm.message = 'Hey! Message';
$http.get('/api/users')
.then(function(data) {
// bind users to vm.users
vm.users = data.users;
});
});
In custom interceptor factory
interceptorFactory.request = function(config) {
// grab token
var token = AuthToken.getToken;
// if token exists add it to the header as x-access-token
if (token)
config.headers['x-access-token'] = token;
return config;
};
change AuthToken.getToken; to AuthToken.getToken();
and your error was quite clear that you were passing function into header instead of value
Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'function () {
return $window.localStorage.getItem('token');
}' is not a valid HTTP header field value.

Categories