I am using angularAMD with require js and I have written an interceptor service which I want to register with $httpProvider.interceptors in my app config file but it throwing error as
Error: [$injector:unpr]
http://errors.angularjs.org/1.4.8/$injector/unpr?p0=cookieInjectorProvider%…eInjector%20%3C-%20%24http%20%3C-%20%24templateRequest%20%3C-%20%24compile(…)
Below is my implimentation
define(["angularAMD", "angular-route", "ui-bootstrap","ngCookies","common/service/interceptor-service"], function(angularAMD){
"use strict";
var app = angular.module("app", ["ui.router", "ui.bootstrap","ngAnimate","ngTouch","angular-carousel","ngCookies"]);
//route
app.config(["$stateProvider", "$urlRouterProvider", "$locationProvider","$httpProvider", function($stateProvider, $urlRouterProvider, $locationProvider,$httpProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state("home", angularAMD.route({
url: "/",
views: {
'header':{
/*...*/
},
},
'content': {
/*...*/
},
'footer': {
/*...*/
}
}));
**//angular is not able to find 'cookieInjector' service**
$httpProvider.interceptors.push('cookieInjector');
}]);
// Bootstrap Angular when DOM is ready
return angularAMD.bootstrap(app, false, document.getElementsByTagName("body")[0]);
});
and my "cookieInjector file is" this service requires another service and it is also implemented in a similar way
define([
'angularAMD',
"common/service/cookie-service"
], function(angularAMD){
angularAMD.service("cookieValidator",[function(){
this.isLoggedIn = false;
this.getIsLoggedIn = function(){
return this.isLoggedIn;
};
this.setIsLoggedIn = function(status){
this.isLoggedIn = status;
};
}])
.factory('cookieInjector', ['$q','cookieValidator', 'cookieService',function($q,cookieValidator,cookieService) {
var cookieInjector = {
request: function(config) {
var cookie = cookieService.getCookie();
if(!cookie){
cookieValidator.setIsLoggedIn(false);
//$location.path('/login');
}else{
cookieValidator.setIsLoggedIn(true);
}
config.headers['Token'] = cookie ? cookie : null;
return config;
},
response: function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
},
responseError: function(response) {
// Cookie has expired
if(response.status === 401 || response.status === 403) {
cookieService.destroyCookie();
cookieValidator.setIsLoggedIn(false);
}
return $q.reject(response);
}
};
return cookieInjector;
}]);
})
I am stuck completely. Thanks for any help.
angular is not able to find 'cookieInjector' service
This is probably because cookieInjector is not available at the moment app.config run. From what I remember angularAMD.factory() will only enject your factory/service into you app after app.config() has been ran.
So in this case, another global angular module should be used instead of using angularAMD
create a file cookieInjector.js
angular.module('cookieModule', []).facotry('cookieInjector', ['$q', 'cookieValidator', 'cookieService', function($q, cookieValidator, cookieService) {
var cookieInjector = {
request: function(config) {
var cookie = cookieService.getCookie();
if (!cookie) {
cookieValidator.setIsLoggedIn(false);
//$location.path('/login');
} else {
cookieValidator.setIsLoggedIn(true);
}
config.headers['Token'] = cookie ? cookie : null;
return config;
},
response: function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
},
responseError: function(response) {
// Cookie has expired
if (response.status === 401 || response.status === 403) {
cookieService.destroyCookie();
cookieValidator.setIsLoggedIn(false);
}
return $q.reject(response);
}
};
return cookieInjector;
}]);
Then init can config your app.
// requireJS config
requirejs.config({
path:{
cookieInjector: 'path/to/cookieInjector'
}
// ... your codes
shim: {
// ... your codes
// make sure cookie injector only load after angularJS is loaded.
cookieInjector: ["angular"];
}
});
// your app.js (?) file
define(["angularAMD", "cookieInjector", "angular-route", "ui-bootstrap", "ngCookies", "common/service/interceptor-service"], function(angularAMD) {
"use strict";
var app = angular.module("app", ["cookieModule", "ui.router", "ui.bootstrap", "ngAnimate", "ngTouch", "angular-carousel", "ngCookies"]);
//route
app.config(["$stateProvider", "$urlRouterProvider", "$locationProvider", "$httpProvider", function($stateProvider, $urlRouterProvider, $locationProvider, $httpProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state("home", angularAMD.route({
url: "/",
views: {
'header': {
/*...*/
},
},
'content': {
/*...*/
},
'footer': {
/*...*/
}
}));
// It should be loaded now
$httpProvider.interceptors.push('cookieInjector');
}]);
// Bootstrap Angular when DOM is ready
return angularAMD.bootstrap(app, false, document.getElementsByTagName("body")[0]);
});
Related
Hey guys I am trying to send a variable from a service from auth.service.js to a factory which is in app.js. I am kind of new to angular so I appreciate any help.
(function() {
'use strict';
angular
.module('app')
.service('authService', authService);
authService.$inject = ['$rootScope', 'lock', 'authManager', 'jwtHelper'];
function authService($rootScope, lock, authManager, jwtHelper) {
var userProfile = JSON.parse(localStorage.getItem('profile')) || {};
function login() {
lock.show();
}
// Logging out just requires removing the user's
// id_token and profile
function logout() {
localStorage.removeItem('id_token');
localStorage.removeItem('profile');
authManager.unauthenticate();
userProfile = {};
}
// Set up the logic for when a user authenticates
// This method is called from app.run.js
function registerAuthenticationListener() {
lock.on('authenticated', function(authResult) {
localStorage.setItem('id_token', authResult.idToken);
authManager.authenticate();
var pubkey = KEYUTIL.getKey('-----BEGIN CERTIFICATE-----MIIC8DCCAdigAwIBAgIJVUYCZUQdreDfMA0GCSqGSIb3DQEBBQUAMB8xHTAbBgNVBAMTFHN3aXRjaC1hcHAuYXV0aDAuY29tMB4XDTE2MTAwNTE5MzczM1oXDTMwMDYxNDE5MzczM1owHzEdMBsGA1UEAxMUc3dpdGNoLWFwcC5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTG7oTPof81dqHqDKT8Mi/umpKgALMHJRwXSVIPBtPZGrgyOubi1oPsWZQrYOwla/3fMhstV/g6ZclVLGg9YHwNZl7uZYaOhAX1CjaTnDUe85R0lvFMRO42N5ZdbhXQASPPrMNZL7gov3eBQcj2n+Jb2k7OWYpN2mevw1fd6iah0eKAeoUcoWGjYwkB9DLmN7HizRsMHeVRyx3BJisI1PmFMkR+Ewbdu+HtOf7yavaVS6KmJti/U/192mXDgakRBLeODrZ+AxwedYcaF4CtGyS52SKkkHsbi6KsjDjfc9CbRRM+51VffVNzTsMTHYtADG34KHigGry/x/5QfsCAEXnAgMBAAGjLzAtMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFOUsGT48yyeHc6a/RdMAlasaM3p7MA0GCSqGSIb3DQEBBQUAA4IBAQAeqkTdeYqE1gSauYr/h30OSjxvHgskUOueWvFBnFveiEQWV3eVyu/psn2YG/2QgCeNSWUMsd8SXCAOBilFy6GL27bUmGKoZEDYsm0dUFTxZiTHgJZNMMQIpPtCLw48Ly1BVQQvi21DZnS9G5ZdWbTEwjNK4M+Fil5zgaiJaObRH4+oAXpgwngT+ZoEO3Z38urbs/Gcp1VKvHjEdY18JxyDChQfIDQNb6bc2zoOR62JTx75fC7khQesJ2jcxJhE1VLsvMRr1bVaVgBeEAdq+fC6WQsJA08209JmJfO4/OYscSe9RxnDEXa6UOQpNO34x5Tr8AImQTLy3jdFoNg1/fSL-----END CERTIFICATE-----');
var isValid = KJUR.jws.JWS.verifyJWT(authResult.idToken, pubkey, {alg: ['RS256']});
console.log(isValid);
// Used for decoding the message returned form auth0
var decoded = jwt_decode(authResult.idToken);
// The encoded message returned from auth0
console.log(authResult.idToken);
//The decoded message returned from auth0
console.log(decoded);
lock.hide();
// Redirect to default page
location.hash = '#/app/home';
lock.getProfile(authResult.idToken, function(error, profile) {
if (error) {
console.log(error);
}
localStorage.setItem('profile', JSON.stringify(profile));
});
});
}
function checkAuthOnRefresh() {
var token = localStorage.getItem('id_token');
if (token) {
if (!jwtHelper.isTokenExpired(token)) {
if (!$rootScope.isAuthenticated) {
authManager.authenticate();
}
}
}
}
return {
userProfile: userProfile,
login: login,
logout: logout,
registerAuthenticationListener: registerAuthenticationListener,
checkAuthOnRefresh: checkAuthOnRefresh
}
}
})();
I want to send from the function registeredAuthentificationListener() the authResult.idToken to a factory in
app.js
(function () {
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if (iOS) {
var isApple = 'isApple';
}else{
var isApple = 'notApple';
}
'use strict';
var app = angular
.module('app', ['ionic', 'auth0.lock', 'angular-jwt'])
.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider', 'lockProvider', 'jwtOptionsProvider','$httpProvider'];
function factory() {
return {
request : function (config) {
config.headers['X-switch-using'] = isApple;
return config;
}
}
}
function config($stateProvider, $urlRouterProvider, lockProvider, jwtOptionsProvider,$httpProvider) {
$stateProvider
// setup an abstract state for the tabs directive
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'components/menu/menu.html',
})
.state('app.home', {
url: '/home',
views: {
'menuContent': {
templateUrl: 'components/home/home.html'
}
}
})
.state('app.dashboard', {
url: '/dashboard',
views: {
'menuContent': {
templateUrl: 'components/template/template.html'
}
}
})
.state('app.signin', {
url: '/login',
views: {
'menuContent': {
templateUrl: 'components/login/login.html'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/home');
$httpProvider.interceptors.push(factory);
lockProvider.init({
clientID: AUTH0_CLIENT_ID,
domain: AUTH0_DOMAIN,
options: {
auth: {
redirect: false,
params: {
scope: 'openid',
device: 'Mobile device'
}
}
}
});
// Configuration for angular-jwt
jwtOptionsProvider.config({
tokenGetter: function() {
return localStorage.getItem('id_token');
},
whiteListedDomains: ['localhost'],
unauthenticatedRedirectPath: '/login'
});
}
})();
Thank you for your help!
It's my bad, you can send the variable using localStorage.getItem('id_token') and use that straight in the app.js
I am using Facebook SDK to build an application however I am faced with a challenge, I try to get the login status of the user before I redirect him to his profile page, however during the call to get the login status I get the error that
ReferenceError: FB is not defined
now the SDK is being loaded asynchronously so the error makes sense, how can i resolve the problem. Here is my code:
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: "Views/ListPages.html",
controller: 'MainCtrl',
resolve: {
authentication:["$location", "LoginFactory", function($location, LoginFactory){
console.log("in resolve");
LoginFactory.getLoginStatus()
.then(function(response){
if(response){
$location.path('/login');
}
else{
$location.path('/');
}
});
}]
}
})
.when('/login', {
templateUrl: "Views/Login.html",
controller: 'LoginCtrl'
})
.otherwise
({redirectTo: '/'});
});
loginApp.factory("LoginFactory", function ($rootScope, $q, $location, UserInfo) {
return {
getLoginStatus: function () {
var deferred = $q.defer();
FB.getLoginStatus(function (response) {
if(!response || response.error){
deferred.reject(new error("User Not logged in."));
}
else{
deferred.resolve(response);
}
});
return deferred.promise;
},
login: function () {
FB.login(function (response) {
if (response.authResponse === "connected") {
$rootScope.$broadcast('fb_connected', {facebook_id:response.authResponse.userID});
} else {
$rootScope.$broadcast('fb_login_failed');
}
}, {scope: "read_insights, publish_pages, manage_pages"});
},
logout: function () {
FB.logout(function (response) {
if (response) {
$rootScope.$broadcast('fb_logout_succeded');
$location.path('/login');
} else {
$rootScope.$broadcast('fb_logout_failed');
}
});
}
};
angular.module("LoginCtrlModule", ["FacebookLogin"])
.controller("LoginCtrl", ["$scope", "$location", "LoginFactory", function ($scope, $location, LoginFactory) {
$scope.login = function () {
LoginFactory.login();
$scope.on("fb_connected", function () {
$location.path("/");
});
$scope.on("fb_login_failed", function(){
$location.path("/login");
});
}
}]);
app.run(function ($rootScope, $location, LoginFactory) {
window.fbAsyncInit = function () {
FB.init({
appId: '',
status: true,
cookie: true,
xfbml: true
});
};
(function (d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
});
I was following these posts:
AngularJS- Login and Authentication in each route and controller
http://www.sitepoint.com/implementing-authentication-angular-applications/
But the problem i am facing is different.
Thanks for the help.
I think the solution is to not call the FB.getLoginStatus() but rather have an object that contains the User information and the access token, each time I try to route I should check if the User info object is null, in case if its not null then call the check login status method and accordingly take the route or not to take the route.
I have included my code below. Basically, when I am loading my view, I am using resolve to get some data. In my service, if my promise is rejected - on error - the resolve gets infinitely called. Is there a better way I should be performing this?
(function () {
function AppService($q, $http, $log, $timeout, pageOptionsModel) {
return {
getPageOptions: function () {
var deferred = $q.defer();
var pageOptions = pageOptionsModel.getPageOptions();
if (pageOptions === null) {
$http.get("api/HomeApi/GetPageOptions")
.success(function (response) {
deferred.resolve(response);
$log.info("Successfully retriedved page options from service.");
})
.error(function (response) {
deferred.reject("Error");
$log.error("Errored while retrieving page options from service.");
});
}
else {
deferred.resolve(pageOptions);
}
return deferred.promise;
}
}
};
function AppConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise("line");
// Now set up the states
$stateProvider
.state('line', {
url: "/line",
templateUrl: "app/line/lineTemplate.html",
controller: "lineController",
controllerAs: "line",
resolve: {
pageOptions: function (appService) {
return appService.getPageOptions();
}
}
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
};
angular.module("app", ["ui.router", "ui.bootstrap", "app.line", "app.modal"])
.config(AppConfig)
.factory("appService", AppService);
})();
Here is my Line Controller which never initializes if my promise is rejected.
(function () {
function LineController($scope, pageOptions) {
var self = this;
// INITIALIZE
self.pageOptions = pageOptions;
};
angular.module("app.line")
.controller("lineController", LineController);
})();
My goal is cancel a xhr request if
the lastest has a 401 status.
With the code below I can cancel
the next request but if I try
to do
an other request (ie do login) is aborted
(it need like canceller.reject(reason))
The flow
1 set a parent route (auth) to check if the login is required
2 set a child root which inheriting the auth state
3 when the app hits the route cancel the request to articles and show a modal login
(function() {
'use strict';
function Auth($http) {
return {
isLoggedIn: function() {
return $http.get('/api/auth/isloggedin');
},
signin: function(data) {
return $http.post('/api/auth/signin', data);
}
};
}
function loginModal($modal, $rootScope,$templateCache) {
function successCallback (data) {
console.log('success',data);
}
function errorCallback (data) {
console.log('fail',data);
}
return {
open : function(){
var modalInstance = $modal.open({
template: $templateCache.get('auth/templates/modal-login.html'),
controller: 'LoginModalController',
controllerAs: 'auth'
});
return modalInstance.result.then(successCallback).catch(errorCallback);
}
};
}
function HttpInterceptor($rootScope,$q) {
var canceller = $q.defer();
return {
'request': function(config) {
config.requestTimestamp = new Date().getTime();
config.timeout = canceller.promise;
return config;
},
'response': function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
},
'responseError': function(rejection) {
if (rejection.status === 401) {
$rootScope.$emit('no-auth', rejection);
canceller.resolve('Unauthorized');
}
return $q.reject(rejection);
}
};
}
angular.module('auth.services', [])
.factory('Auth', Auth)
.factory('HttpInterceptor', HttpInterceptor)
.factory('loginModal', loginModal);
})();
(function() {
'use strict';
angular.module('auth',
['auth.services','auth.controllers','auth.routes'])
.run(function($rootScope,loginModal,HAS_MODAL_LOGIN){
$rootScope.$on('no-auth', function(event, data) {
if(HAS_MODAL_LOGIN){
loginModal.open();
}
});
});
})();
(function() {
'use strict';
function config($stateProvider,$httpProvider) {
$stateProvider
.state('auth', {
abstract: true,
template: '<ui-view/>',
resolve:{
auth : function(Auth){
return Auth.isLoggedIn();
}
}
});
//Http Intercpetor to check auth failures for xhr requests
$httpProvider.interceptors.push('HttpInterceptor');
}
angular.module('auth.routes', [])
.config(config);
})();
(function() {
'use strict';
function config($stateProvider) {
$stateProvider
.state('auth.articles', {
url: '/articles',
templateUrl: 'articles/templates/index.html',
controller:'ArticlesController as articles',
resolve:{
articlesData : function(Articles){
return Articles.get();
}
}
});
}
angular.module('articles.routes', [])
.config(config);
})();
You do not need to reject. If you have 401 error, then you may simply open login dialog right there. And if user closed dialog, navigate to home.
Please read this article by Gabe Scholz
http://brewhouse.io/blog/2014/12/09/authentication-made-simple-in-single-page-angularjs-applications.html
This is exactly what you try to do but much cleaner way.
I'm trying to redirect my user to Dashboard after Third Party Login. But when success callback is fired, the application still on Login Page, nothing happened. If I refresh the browser my interceptor catch already login and change to Dashboard... My Login Controller looks like this:
ThirdParty.login(function(result){
callbackSUCCESS(result);
},function(){});
function callbackSUCCESS(result){
AuthenticationService.login(result).then(
callbackServerSUCCESS(), function(reject) {
callbackServerERROR(reject);
});
}
function callbackServerSUCCESS() {
$scope.$apply(function() {
$state.go('dashboard');
});
}
My route in app.js
$stateProvider
.state('dashboard', {
url: '/dashboard',
views: {
'': {
templateUrl: 'views/dashboard/dashboard.html',
controller: 'DashboardCtrl'
}
}
});
My Header Controller
.controller('HeaderCtrl', ['$scope', 'AuthenticationService', '$state',
function($scope, AuthenticationService, $state) {
$scope.logout = function() {
AuthenticationService.logout().then(callbackServer(), callbackServer());
};
function callbackServer() {
$state.go('login');
}
}
]);
Authentication Controller Angular Factory
var headersConfig = {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
};
return {
login: function(credentials) {
var deferred = $q.defer();
$http.post('/api/users/sign_in', sanitizeCredentials(credentials), {
headers: headersConfig,
timeout: deferred.promise
}).then(function(result) {
if (result.status === 200) {
UserSessionService.cacheSession(result.data);
deferred.resolve();
} else {
deferred.reject();
}
}, function(reject) {
UserSessionService.clean();
deferred.reject(reject);
});
$timeout(function() {
deferred.resolve();
}, 15000);
return deferred.promise;
}
};
I can't remember the exact semantics of $state.go, but usually you need to use $scope.$apply in some manner when responding to events Angular isn't aware of, to ensure a digest cycle occurs. I.e. you could try:
ThirdParty.login(function(result) {
$scope.$apply(function() {
$state.go('dashboard');
});
}, function() {});
You need to get a reference to a scope from somewhere, but one shouldn't be hard to find in an Angular app.
Get rid of both () in
then(callbackServer(), callbackServer())