How to auto login in angularjs application with url - angularjs

Can anyone say me how to auto login with angularjs 1.x .I will be sending the email with url and when they click on that url it should autoredirect to home page.
The url will be having email and encrypted password:
http://localhost:8080/login/amg1.2.3#outlook.com/$2a$08$cZPWmzta7Gn9Mj14r7zGWeMPKNKkkg8JS3gWNL2fQaFuBwrhgKQC
Clicking on this url should redirect me to home page without any login page.
I am using passport for login functionality.
can you explain me how,iam using passport with form post like this
app.get('/login/:email/:pwd', function(req, res) {
console.log(req.params.email);
console.log(req.params.pwd);
var request = require('request');
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: 'http://localhost:8080/login/',
form: { email: req.params.email,password:req.params.pwd }
}, function(error, response, body){
console.log(error);
console.log(body);
console.log(response);
});
});
Please check the gist how I am doing and tell me how can i improve the code gist.github.com/agupta330/0fb55b50eecf4b1305ebfe15869b295d

It has nothing to do with angular, because it is serverside.
You should not use the encryted password, because your link will never expire. It is better to generate a random key and store it in your database like you do it with sessions ids.
If the user clicks on the link an the key is valid and not expires, you generate a new session and send the session cookie together with the redict to your angular page to the user.
For the angular page you not have to change anything, because it seems like the user is loggedin like normal (with the session in the cookie)

Related

Query the db from Angular to Nodejs with passportjs

I am able to authenticate with passport-facebook and store the userid and username from facebook to my db. I am querying nodejs from angular controller :
MyApp.controller("FacebookLogin", function($scope, $http){
$scope.login = function(){
$http.get("/facebooklogin").then(function(response){
if(response.data){
console.log(response.data); // nothing is logged here
} else {
console.log("No Data");
}
});
}
});
In node :
app.get('/facebooklogin', passport.authenticate('facebook'));
app.get('/auth/facebook/callback', passport.authenticate('facebook', function(err, user, info){
console.log(err, user, info);
if(err) throw err;
// res.send(user); //Do I send the user info from here?
}));
I want to send the userid to angular to store in localStorage and use that to query the db for future requests. Is that the proper way to do it? It's a SPA. I see a connect.sid cookie is created in my browser. How do i extract the userid from it if it has the userid or what do i send in my post/get that nodejs recognizes thru the session?
I did read but did not understand what these two things do exactly :
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
Many Thanks.
The facebook Auth mechanism (oAuth) is asynchronous, and so it works differently to what you are expecting.
You don't do a $http.get("/facebooklogin"). Rather you should redirect your browser to '/facebooklogin'
The way the oauth process works in a nutshell is
User clicks a 'Login with facebook' button, which should do a hard redirect to 'http://youserver/facebooklogin' (you can also do fancy stuff with iframes, dialogs, etc.)
The server side call app.get('/facebooklogin', passport.authenticate('facebook')); will respond with a redirect to facebook.com passing through your apps credentials. At this stage, the user has effectively left your application. Facebook handles the login for the user so that you never get to see their username/password etc.
If successful, facebook will redirect the browser back to your callback URL, passing through a session id. This is received at http://yourserver/facebook/callback. The server side code would then typically store this in the user session in some way, ie. in the DB, a cookie, or just redirect to a page in your app that can receive the session info and save it in local storage.

Receive response from Instagram API call with AngularJS

To authenticate a user in an app using the Instagram API, you redirect the user to the URL https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code.
Once the user signs in on this page, Instagram then makes a GET request to the redirect URI (REDIRECT-URI in the above URL). This call to the redirect URI contains a code which you must then include in a POST request to https://api.instagram.com/oauth/access_token to exchange for an access token which is sent in a JSON form in the response.
So I'm receiving the redirect call and making the request for the access token with my Express API and this works fine and I get the form with the access token.
app.get('/redirect', function(req, res){
if(req.query.error){
console.log('Error authenticating user');
console.log(req.query.error);
}
else{
request.post(
'https://api.instagram.com/oauth/access_token',
{form:{
client_id: 'my_client_id',
client_secret: 'my_client_secret',
grant_type: 'authorization_code',
redirect_uri: 'http://localhost/redirect',
code: req.query.code
}
},
function(error, response, body){
if(!error && response.statusCode == 200){
console.log(body);
//HOW DO I GET THIS RESPONSE TO ANGULAR?
res.json({
access_token: body.access_token,
full_name: body.full_name,
username: body.username,
profile_picture: body.profile_picture,
id: body.id
});
return;
}
else{
console.log(response);
console.log(body);
}
}
);
};
My question is: how to I send the access token (or error response) back to Angular?
In other words, how does Angular receive the response from a request it did not make (since the response I want to receive is from the request made with NodeJS's request)?
Initially I tried to make the first GET to https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code with Angular but I don't think this can be done because the user should be directed to the Instagram URL to sign in.
Update:
When Instagram makes the GET /redirect?code=xxxxxx, it sends the request to my API but also changes the page URL to http://localhost/redirect?code=xxxxxx. I can receive the access token in my API and send it to my client-side but because of the above URL, the page is just displayed as the text of the response and not my index.html with ng-view. How do I get the page to be my index.html in this situation?
I've tried with angular-router the following ways but neither worked:
.when('/redirect', {
templateUrl: 'views/success.html',
controller: 'Controller'
})
and
.when('/success', {
templateUrl: 'views/success.html',
controller: 'Controller'
})
.when('/redirect', {
redirectTo: '/success'
})
What I ended up doing (and I'm not sure this is optimal):
Once I receive the response from the call made from Node, I store the access token from the response, body.access_token, in the req.session.user object provided by the express-session npm package and then I redirect the user to the home page with res.redirect('/#/home');.
app.get('/redirect', function(req, res){
if(req.query.error){
console.log('Error authenticating user');
console.log(req.query.error);
}
else{
request.post(
'https://api.instagram.com/oauth/access_token',
{form:{
client_id: 'my_client_id',
client_secret: 'my_client_secret',
grant_type: 'authorization_code',
redirect_uri: 'http://localhost/redirect',
code: req.query.code
}
},
function(error, response, body){
if(!error && response.statusCode == 200){
console.log('Success making POST to Insta API for token, making new session object');
console.log('token:', (JSON.parse(body).access_token), '\n');
req.session.user = {};
req.session.user.token = JSON.parse(body).access_token;
req.session.save();
res.redirect('/#/home');
}
else{
console.log(error);
res.redirect('/#/login');
}
}
);
};
This way, Angular doesn't need to receive the access token after redirecting the user to Instagram's authorization page because the access token is saved in the req.session.user object which is then accessible on the backend for the duration of the session.
You can then use the access token in any requests to the Instagram API from your backend (initiated by a call to your API from Angular), e.g. by concatenating it to whatever the endpoint is for your Instagram API call like so:
var endpoint = 'https://api.instagram.com/v1/users/self/follows?access_token=' + req.session.user.token;
This method also works well with the session management functionality of express-session since a session is only created when the user can be authenticated by Instagram. See here for a quick tutorial on how to integrate session management into your app.

Why angular post does not send jsessionid to redirect_uri

I've downloaded the JWT version of the oauth2 server (https://github.com/spring-guides/tut-spring-security-and-angular-js/tree/master/oauth2) and I've been trying to replace the default login form to another using angularjs.
That I made was:
Create a request mapping for the new login form
`
#RequestMapping(value = {"/login"})
public String redirect(#RequestParam(required = false) String code, #RequestParam(required = false) String state) {
return "redirect:/#/login";
}
`
Call to the login endpoint using $http.post (XSRF-TOKEN has been injected with an interceptor):
`
var params = {username: credentials.username, password: credentials.password};
var config = {
headers: {'content-type': 'application/x-www-form-urlencoded; charset=utf-8'}
};
CoreService.httpPost('login', $httpParamSerializer(params), config)
.then( function(data) {...});
`
All looks ok, Angular send the information, the client info is obtained from our BD, the user is searched in our Data Base or LDAP. When the user is founded and the login process finish ok, the symtem redirect to the zuul server, but the jsessionid it's not present, so the Zuul server can't validate the token.
However, If I refresh the IU page, the token validation works perfectly
So, could you tell me what I have to do or what I'm doing wrong?
Thanks a lot

Node API - How to link Facebook login to Angular front end?

Rewriting this question to be clearer.
I've used passport-facebook to handle login with facebook on my site.
My front end is in Angular so I know now need to understand whats the correct way of calling that api route. I already have several calls using Angular's $http service - however as this login with facebook actually re-routes the facebook page can i still use the usual:
self.loginFacebook = function )() {
var deferred = $q.defer();
var theReq = {
method: 'GET',
url: API + '/login/facebook'
};
$http(theReq)
.then(function(data){
deferred.resolve(data);
})
return deferred.promise;
}
or is it perfectly ok/secure/correct procedure to directly hit that URL in a window location:
self.loginFacebook = function (){
$window.location.href = API + '/login/facebook';
}
Furthermore, from this how do I then send a token back from the API? I can't seem to modify the callback function to do that?
router.get('/login/facebook/callback',
passport.authenticate('facebook', {
successRedirect : 'http://localhost:3000/#/',
failureRedirect : 'http://localhost:3000/#/login'
})
);
Thanks.
I was stacked on the same problem.
First part:
I allow in backend using cors and in frontend i use $httpProvider, like this:
angular.module('core', [
'ui.router',
'user'
]).config(config);
function config($httpProvider) {
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
};
The second part:
<span class="fa fa-facebook"></span> Login with facebook
This call my auth/facebook route that use passport to redirect to facebook page allowing a user to be authenticated.
If the user grant access, the callback /api/auth/facebook/callback is called and the facebook.strategy save the user with the profile data.
After saving the user, i create a special token with facebook token, id and email. This info is used to validate every time the user access to private states in the front.
My routes are something like this:
router.get('/facebook', passport.authenticate('facebook',
{ session: false, scope : 'email' }));
// handle the callback after facebook has authenticated the user
router.get('/facebook/callback',
passport.authenticate('facebook',
{session: false, failureRedirect: '/error' }),
function(req, res, next) {
var token = jwt.encode(req.user.facebook, config.secret);
res.redirect("/fb/"+token);
});
In frontend i catch the /fb/:token using a state and assign the token to my local storage, then every time the user go to a private section, the token is sent to backend and validate, if the validation pass, then the validate function return the token with the decoded data.
The only bad thing is that i don't know how to redirect to the previous state that was when the user click on login with facebook.
Also, i don't know how you are using the callback, but you need to have domain name to allow the redirect from facebook. I have created a server droplet in digitalocean to test this facebook strategy.
In the strategy you have to put the real domain in the callback function, like this:
callbackURL: "http://yourdomain.com/api/auth/facebook/callback"
In the same object where you put the secretId and clientSecret. Then, in your application in facebook developers you have to allow this domain.
Sorry for my english, i hope this info help you.
Depending on your front-end, you will need some logic that actually makes that call to your node/express API. Your HTML element could look like
<a class='btn' href='login/facebook'>Login</a>
Clicking on this element will make a call to your Express router using the endpoint of /login/facebook. Simple at that.

angular redirect to route + cache

I have a login form at my homepage. When an user submit form angular send post request to auth/login (laravel's default auth system -> it doesn't matter). It logs the user but then I want to refresh homepage view. I tried this:
$http({
data: {},
method: 'POST',
..
}).success(function(data) {
..
$templateCache.remove('/');
$location.path('/');
});
But it's not working. In console I see new request at homepage, but it doesn't change any data(when the user logs in he can see his nick instead of login form).
Where can be problem? (maybe problem can be that I'm changing location to the current? when I set $location.path('/something-else') it works).
I thought it's possible to remove 1 certain template from cache, but it's. You can only remove all templates with $templateCache.removeAll();

Resources