integrating linkedin login with angularjs application - angularjs

I am new to angular js .I would like to know the procedure to get api key and integrating linked in sign in ,sign up with angularjs application.

You can use LinkedIn SDK to handle authorisation and sing up or sing off users.
Documentation: https://developer.linkedin.com/docs/getting-started-js-sdk
You have to initial SDK. You will need to create an app in your LinkedIn Developer panel. Then you get an API Key there.
Then in your app you have to create a service that will call LinkedIn API.
Something like this:
export class LinkedIn {
constructor($q, $window) {
'ngInject';
this.$q = $q;
this.$window = $window;
};
get() {
let doc = this.$window.document;
let script = doc.createElement('script');
let deferred = this.$q.defer();
script.src = 'http://platform.linkedin.com/in.js';
script.innerHTML = [
'api_key: ' + YOUR_API_KEY,
'authorize: ' + 'true',
'lang: ' + 'en-US',
'onLoad: onLinkedInApiLoad',
'scope: ' + YOUR_APP_SCOPE
].join('\n');
this.$window.onLinkedInApiLoad = () => {
deferred.resolve(this.$window.IN);
};
doc.body.appendChild(script);
return deferred.promise;
};
}
Next you need to decide where and when you want to initial this call. You can do that in .run block or made some middleware to handle it. After that you will receive LinkedIn API object.
When you have got your LinkedIn API object you can request authorisation, check if user has been already logged in and etc. Options are describe in documentation. You can authorise user calling IN.User.authorize(handler || angular.noop) or logout IN.User.logout(handler || angular.noop)
There is also options to do a callback on Event where user log in or log out for example:
IN.Event.on(IN, eventName, callback, callbackScope, extraData);
IN.Event.onOnce(IN, eventName, callback, callbackScope, extraData);

You can use angular module for linkedIn authentication. angular-social-login

Related

Calling API from JavaScript Frontend: 401 unauthorized using angularfire

I am following this tutorial on adding firebase authentication to my webapp using endpoints v2 (migrated from v1 yesterday).
I previously had google accounts authentication only but want to switch to firebase for adding e.g. facebook.
When I call my API from my JavaScript Frontend (built with angularJS & angularfire) I get a 401 unauthorized.
I feel, I am missing a logical step:
I can log-in on the client-side (pop-up opens and my facebook-name is displayed).
Missing step?
endpoints.get_current_user() does not get a user.
Where am I going wrong?
This is what I want to initialize the page where I want to get a profile from the backend:
`/**
* Initialize profile page.
* Update the profile if the user's profile has been stored.
*/
$scope.init = function () {
var retrieveProfileCallback = function () {
$scope.profile = {};
$scope.loading = true;
gapi.client.myapi.getProfile().execute(function (resp) {
$scope.$apply(function () {
$scope.loading = false;
if (resp.error) {
// Failed to get a user profile.
} else {
// Succeeded to get the user profile.
$scope.profile.displayName = resp.result.displayName;
$scope.profile.someOtherProperty = resp.result.someOtherProperty;
$scope.initialProfile = resp.result;
}
});
}
);
};
if (!firebaseUser) {
//TODO
} else {
retrieveProfileCallback();
}
};`
This is the start of the method that is ultimatively called from getProfile()-endpoint:
def _getProfileFromUser(self):
"""Return user Profile from datastore, creating new one if non-existent."""
## Make sure user is authed
user = endpoints.get_current_user()
if not user:
raise endpoints.UnauthorizedException('Authorization required')
Here is my API decorator (openapi.json has been deployed):
# - - - - firebase - - - - - - - - - - - - - - - - - -
firebase_issuer = endpoints.Issuer(
issuer='https://securetoken.google.com/appname-123456',
jwks_uri='https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken#system.gserviceaccount.com')
# - - - - Endpoints API - - - - - - - - - - - - - - - - - - -
#endpoints.api(name='myapi',
version='v1',
scopes=[EMAIL_SCOPE],
issuers={'firebase': firebase_issuer})
class MyApi(remote.Service):
I feel like I am massively misinterpreting the tutorials. It seems too easy and does not work.
E.g. for the google accounts authorization I initialized the oauth2 api like so in the index.html:
`<script>
function init() {
gapi.client.load('myapi', 'v1', null, '//' + window.location.host + '/_ah/api');
gapi.client.load('oauth2', 'v2', function () {
angular.bootstrap(document, ['conferenceApp']);
});
};
</script>`
I took that out because I figured I am switiching to firebase.
Like so:
`<script>
/**
* Initializes the Google API JavaScript client. Bootstrap the angular module after loading the Google libraries
* so that Google JavaScript library ready in the angular modules.
*/
function init() {
gapi.client.load('myapi', 'v1', null, '//' + window.location.host + '/_ah/api', function () {
angular.bootstrap(document, ['myApp']);
});
};
</script>`
The openapi configuration looks fine. The problem is with the client code, which handles sign-in flow to get a Firebase auth token. You need to use Firebase web SDK instead of Google JS SDK. You can take a look at the instructions at https://firebase.google.com/docs/auth/web/google-signin.

Angular-permission define permissions retrieved via API

I am trying to use angular-permission to implement permission-based authentication but I don't know where to define those permissions which are retrieved from my back-end via API which requires token-based access.
First, let me give a bit background about how my app looks like. On my back-end, my system portal, I define permissions to allow different APIs to be called. Permissions won't change all the time. Only when I add new features(APIs), new permissions will be added. For example.
permission1: api1,api2,api3
permission2:api4,api5,api6
permission3:api7,api8,api9
On the front-end, customers login the front-end web portal and create customized roles themselves which group some permissions together, for example:
admin: permission1,permission2,permission3
auditor:permission 3
The angular-permission doc says (https://github.com/Narzerus/angular-permission/blob/development/docs/1-manging-permissions.md#multiple-permissions) I can use PermissionStore.defineManyPermissions to define permissions which are retrieved from API after user login. That's all clear.
So I have two modules. One is the Authentication module which handles user login. The other one is the Permission module which handles the permission validation. On the Permission module .run() phase, I define the permissions like this:
var getPermissions = function () {
var deferred = $q.defer();
system.permissions.get(
function () {
return deferred.resolve(system.permissions._permissions);
},
function (error) {
console.log("error if can't load permissions");
console.log(error);
}
);
return deferred.promise;
};
var loadPermissions = function () {
var promise = getPermissions();
promise.then(function (permissions) {
var arrayPermissions = formatPermissionArray(permissions);
//var arrayPermissions=['viewSeed','viewAuthentication'];
PermissionStore.defineManyPermissions(arrayPermissions, checkPermission);
console.log("from permission run service");
console.log(arrayPermissions);
}, function (reason) {
console.log('Failed: ' + reason);
}, function (update) {
console.log('Got notification: ' + update);
});
};
loadPermissions();
var formatPermissionArray = function (sourceData) {
var formatedPermissionArray = [];
for (var i = 0; i < sourceData.length; i++) {
formatedPermissionArray.push(sourceData[i].permissionId);
};
return formatedPermissionArray;
};
But during the bootstrap of the app, this module already loaded and the arrayPermissions will be empty since user hasn't logged in yet.
I tried to use oclazyload to load the Permission module from the login controller of the Authentication module, that actually works but if user refresh/reload their page, the Permission module won't be loaded anymore.
I am new to web development and also new to AngularJs. Just a few months experience. I don't know if I am doing it in a complete wrong way.
My questions are:
The API for retrieving a permission list should require authentication? Since I will need to put those authentication on the UI-router routes. Anyone can see it anyway. If I should not protect that API, then my problem is solved.
If I should keep my api protected, how should I address the issues I described above and that is where to define the permissions for angular-permission and how to use API to retrieve the permissions.
I hope I have managed to describe my issues clearly. Any help or guidance are greatly appreciated.
Regards,
Lola
I'm using angular-permission with angular-satellizer. PermRoleStore or PermPermissionStore needs to be in run block. You can add data to JSON WEB TOKEN add use it at the run block like I did.
$auth.getPayload()This function returns payload from JWT in localStorage. And in that payload it has data with role key which I saved in backend. I hope this helps your issue.
.run(function (PermRoleStore, $auth, Yollar) {
PermRoleStore
.defineRole('ADMIN', function () {
if($auth.getPayload()) {
if ($auth.getPayload().data.role === 'ADMIN') {
return true;
}
else {
return false;
}
}
else {
return false;
}
});
PermRoleStore
.defineRole('MODERATOR', function () {
if($auth.getPayload()) {
if ($auth.getPayload().data.role === 'MODERATOR') {
return true;
}
else {
return false;
}
}
else {
return false;
}
});
})

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.

How to save the google login as an app user?

So I have some code that authenticates the user to my app using google which works out fine. What I want to do is then save that user info to the firebase and then have that user be able add data specifically under their account that will then reload the next time they log in. What's the best way to do that? I'm getting very lost.
(function() {
'use strict';
angular.module('life-of-a-story')
.controller('UserController', function($scope, $firebaseAuth) {
var ref = new Firebase('https://life-of-a-story.firebaseio.com/');
// create an instance of the authentication service
var auth = $firebaseAuth(ref);
// login with Google
this.login = function() {
auth.$authWithOAuthPopup("google").then(function(authData) {
console.log(authData);
console.log("Logged in as:", authData.uid);
var user = {
'name': authData.google.displayName,
'image': authData.google.profileImageURL,
'uid': authData.uid
}
console.log(user);
}).catch(function(error) {
console.log("Authentication failed:", error);
});
};
});
})();
AngularFire is a (relatively) thin UI binding library on top of Firebase's regular JavaScript SDK. So when something is not explicitly documented in the AngularFire documentation, you can sometimes find the answer in the documentation for the regular Firebase JavaScript SDK.
Most Firebase Authentication developers store each user's data under a /users node. If that is what you're trying to do, you can read how to accomplish it in the section called Storing user data in the Firebase documentation for JavaScript.
The relevant code from there:
// we would probably save a profile when we register new users on our site
// we could also read the profile to see if it's null
// here we will just simulate this with an isNewUser boolean
var isNewUser = true;
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(function(authData) {
if (authData && isNewUser) {
// save the user's profile into the database so we can list users,
// use them in Security and Firebase Rules, and show profiles
ref.child("users").child(authData.uid).set({
provider: authData.provider,
name: getName(authData)
});
}
});
// find a suitable name based on the meta info given by each provider
function getName(authData) {
switch(authData.provider) {
case 'password':
return authData.password.email.replace(/#.*/, '');
case 'twitter':
return authData.twitter.displayName;
case 'facebook':
return authData.facebook.displayName;
}
}

bacbkone router redirect if not authenticated

I am trying to implement a simple app that needs a login and user authentication. As I am new to backbone and marionette, I have been trying to follow the example for this tutorial: https://github.com/davidsulc/marionette-gentle-introduction
Generally I have set up a new app:
var App = new Marionette.Application({});
App.addRegions({
headerRegion : "#nav-region",
mainRegion : "#main-region"
});
App.navigate = function(route, options){
options || (options = {});
Backbone.history.navigate(route, options);
};
App.getCurrentRoute = function(){
return Backbone.history.fragment
};
App.on("start", function(){
if(Backbone.history){
Backbone.history.start();
}
});
And routers are defined in modules, e.g.:
App.module("ContentManagementApp", function(ContentManagementApp, App, Backbone, Marionette, $, _){
ContentManagementApp.Router = Marionette.AppRouter.extend({
appRoutes : {
"contentmanagement/:dsid(/:dspageclassid)": "showContentMananagement",
}
});
var API = {
showContentMananagement : function(dsid, dspageclassid){
// If not set, set to frontpage
ContentManagementApp.Show.Controller.showDSPage(dsid, dspageclassid);
App.execute("set:active:header", "contentmanagement");
},
};
App.on("contentmanagement:show", function(dsid, dspageclassid){
App.navigate("contentmanagement/" + dsid + "/" + dspageclassid);
API.showContentMananagement(dsid, dspageclassid);
});
App.addInitializer(function(){
new ContentManagementApp.Router({
controller : API
});
});
});
I would like to test if the user is logged and redirect to the login page when the app starts, but it seems like App.addInitializer is called before. Does it mean I have to do the check in each module, or can I get by it somehow?
How do you determine if the user is logged or not?
If it's a call to an API that could fail (due to the user being unauthenticated), it will probably return an HTTP error code 403. I usually do this using a global jQuery ajax.error() handler, I check if it's a 403 (Forbidden) for any of my normal API calls (model fetching and so on) and if it is, I redirect to a login url.
Otherwise, if you want to check for a cookie or similar, you should do it before calling Backbone.history.start(). Only start the app if the user is logged. :)
I just set this up in my app - in your backend when the user is logged in create a cookie/destroy it when they sign-out. Then I use the jquery-cookie-rails gem to access the cookie as $.cookie('cookie_name') and if it isn't there I route them to the signin path.
I would note - I also check to see if the user is signed on the backend when hitting different controller actions and route them appropriately. I just like the extra protection :).

Resources