I am trying to use angular-jwt in service but it does not append authorization on http call:
angular.module('TestApp')
.config(function Config($httpProvider, jwtInterceptorProvider) {
jwtInterceptorProvider.tokenGetter = ['merchantService', function(merchantService) {
merchantService.doSomething();
return localStorage.getItem('token');
}];
$httpProvider.interceptors.push('jwtInterceptor');
})
.service('Merchant', ['$http', function($http) {
var baseUrl = "http://test.com";
return {
terminal: function(success, error) {
$http.jsonp(baseUrl + '/tests?callback=jsonp_callback').success(success).error(error)
}
}
}]);
Related
I use cordovaFileTransfer for image upload in my ionic app. Also i use ng-token-auth for authorization. It exchanging tokens with devise through headers.
Problem is that ng-token-auth intercepting http service where tokens are updated, however cordova does not use http service.
So how is possible to handle reponse after file upload to update tokens that are in headers.
Updated.
Here i call file upload.
#cordovaFileTransfer.upload(
upload_path,
file_uri,
httpMethod: method,
headers: #auth.retrieveData('auth_headers')
)
Here is ng-token-auth code which intercepts http:
$httpProvider.interceptors.push([
'$injector', function($injector) {
return {
request: function(req) {
$injector.invoke([
'$http', '$auth', function($http, $auth) {
var key, val, _ref, _results;
if (req.url.match($auth.apiUrl())) {
_ref = $auth.retrieveData('auth_headers');
_results = [];
for (key in _ref) {
val = _ref[key];
_results.push(req.headers[key] = val);
}
console.log("REQUEST_NEW_HEADERS")
console.log(req)
console.log($auth.retrieveData('auth_headers'))
console.log(_results)
return _results;
}
}
]);
return req;
},
response: function(resp) {
$injector.invoke([
'$http', '$auth', function($http, $auth) {
if (resp.config.url.match($auth.apiUrl())) {
console.log('[RESP_SUCCESS]')
console.log(resp.headers())
return updateHeadersFromResponse($auth, resp);
}
}
]);
return resp;
},
responseError: function(resp) {
$injector.invoke([
'$http', '$auth', function($http, $auth) {
if (resp.config.url.match($auth.apiUrl())) {
console.log('[RESP_ERROR]')
console.log(resp.headers())
return updateHeadersFromResponse($auth, resp);
}
}
]);
return $injector.get('$q').reject(resp);
}
};
}
]);
I tried to prepare http request url in interceptors rather than adding it to the object passed in $http. Here is the sample of code I tried:
angular.module('myapp', [])
.service('myservice', function() {
this.myfunction = function() {
var req = {method: 'POST', reqName: 'getInfo'};
return $http(req);
}
})
.factory('myInterceptor', function() {
var interceptor = {
'request': function(config) {
config.url = "http://www.myapi.com/demo/"+config.reqName;
return config;
}
}
return interceptor;
})
.config(function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
})
But I'm getting an error, which says:
Error: [$http:badreq] Http request configuration url must be a string.
Received: undefined
Any help?
Let me show some tests that proof AngularJS documentation is correct.
Some details about Interceptor - http://docs.angularjs.org/api/ng/service/$http#interceptors
angular.module('myApp', [])
.service('service', function($http) {
this.myfunction = function() {
var req = {
method: 'POST',
reqName: 'getInfo'
};
return $http(req);
}
})
.factory('myInterceptor', function() {
var interceptor = {
'request': function(config) {
config.url = "http://www.myapi.com/demo/" + config.reqName;
return config;
}
}
return interceptor;
})
.config(function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
})
describe("myApp", function() {
beforeEach(module("myApp"));
it("executes intercpetor that changes request", inject(function(service, $httpBackend) {
$httpBackend.expectPOST("http://www.myapi.com/demo/getInfo").respond(201, []);
service.myfunction().then(function(r) {
expect(r.config.url).toBe('http://www.myapi.com/demo/getInfo')
})
$httpBackend.flush();
}));
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-resource.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>
Using AngularJS for my application and for http post the server needs a token that we can get by http get. But I want to run the token_generate() function before each http call, because sometimes the token expires
token = function() {
var api = AuthService.getToken();
api.success(function (response) {
var token = response.token;
$http.defaults.headers.common['X-CSRF-TOKEN'] = token;
});
};
token();
You need to register an $http interceptor:
(function(window, angular) {
function tokenizerConfig($httpProvider) {
function registerInterceptors($q, $http, AuthenticationService) {
var interceptors = {};
interceptors.request = function(configs) {
if(AuthenticationService.isTokenValid) {
return $q.when(configs);
}
var qs = {};
return $http
.get(TOKEN_API, { cache: false, params: qs})
.then(function(result) {
AuthenticationService.setToken(result.data.token);
return configs;
})
;
};
return interceptors;
}
$httpProvider.interceptors.push(['$q', '$http', 'AuthenticationService', registerInterceptors]);
}
angular
.module('tokenizer', [])
.config(['$httpProvider', tokenizerConfig])
})(window, window.angular);
I'm building my (first) angular app that will have tokens inserted into headers (the content shown is for the most part taken from here)
angular.module('myApp')
.factory('sessionInjector', ['SessionService', function(SessionService) {
var sessionInjector = {
request: function(config) {
config.headers['x-session-token'] = SessionService.getToken();
return config;
}
};
return sessionInjector;
}])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('sessionInjector');
}])
The trouble I'm having is with SessionService - how can I initialize this with call to the server?
For example, this didn't work:
.factory('SessionService', ['$injector', function($injector){
var token = "";
return {
getToken: function () {
var http = $injector.get('$http');
if (token === "") {
http.get('http://localhost/api/auth/getToken').success(function (ret) {
token = ret;
});
}
return token;
//I can see a $q/deferred/promise should be used somehow here...
//but I'm not sure it solves the problem I'm having...
}
}
}]);
because it just overloads my cpu to 100%...
Since it's my first angular app, I'm sure I'm missing something, but... what?
EDIT:
Another take on the matter... still doesn't work though... (again, uses up cpu, probably infinite loop)
.factory('sessionData', function () {
var currentToken = '[uninitialized-token]';
return {
getToken: function () {
return currentToken;
},
setToken: function (token) {
currentToken = token;
}
}
})
.factory('sessionInjector', ['sessionData', '$injector', '$q', function (sessionData, $injector, $q) {
var sessionInjector = {
request: function (config) {
var deferred = $q.defer();
var http = $injector.get('$http');
http.get('http://localhost/api/auth/getToken').success(function (ret) {
sessionData.setToken(ret);
console.log("successfully authenticated with token " + sessionData.getToken());
config.headers['x-header-sessionID'] = sessionData.getToken();
deferred.resolve(config);
})
.error(function(){
console.log("failed to authenticate");
deferred.resolve(config);
});
return deferred.promise;
}
};
return sessionInjector;
}])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('sessionInjector');
}])
.run(['$http', 'sessionData', function ($http, configs, sessionData) {
$http.get('http://localhost/api/auth/testMethod').then(function (ret) {
//do something...
});
}])
Check whether this modified code fragment will solve your issues.
.factory('SessionService', ['$http', '$q', function($http, $q) {
var token = null;
var sessionService = {};
var differred = $q.defer();
sessionService.readToken = function() {
return $http.get('http://localhost/api/auth/getToken')
.success(function (res) {
console.log('Auth Success and token received: ' + JSON.stringify(res.data));
// Extract the token details from the received JSON object
token = res.data;
differred.resolve(res);
}, function (res) {
console.log('Error occurred : ' + JSON.stringify(res));
differred.reject(res);
}
)
};
sessionService.getToken = function() {
return token;
};
sessionService.isAnonymous = function() {
if (token)
return true;
else
return false;
};
return sessionService;
}])
.factory('sessionInjector', ['SessionService', function(SessionService) {
var sessionInjector = {
request: function(config) {
if (!sessionService.isAnonymous) {
config.headers['x-session-token'] = SessionService.getToken();
return config;
}
}
};
return sessionInjector;
}])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('sessionInjector');
}])
Answer was actually pretty straight forward - if the targeted URL is for login, then don't inject anything (look for the comment the fix):
.factory('sessionData', function () {
var currentToken = '[uninitialized-token]';
return {
getToken: function () {
return currentToken;
},
setToken: function (token) {
currentToken = token;
}
}
})
.factory('sessionInjector', ['sessionData', '$injector', '$q', function (sessionData, $injector, $q) {
var sessionInjector = {
request: function (config) {
//The fix:
if(config.url === 'http://localhost/api/auth/getToken')
return config;
var deferred = $q.defer();
var http = $injector.get('$http');
http.get('http://localhost/api/auth/getToken').success(function (ret) {
sessionData.setToken(ret);
console.log("successfully authenticated with token " + sessionData.getToken());
config.headers['x-header-sessionID'] = sessionData.getToken();
deferred.resolve(config);
})
.error(function(){
console.log("failed to authenticate");
deferred.resolve(config);
});
return deferred.promise;
}
};
return sessionInjector;
}])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('sessionInjector');
}])
.run(['$http', 'sessionData', function ($http, configs, sessionData) {
$http.get('http://localhost/api/auth/testMethod').then(function (ret) {
//do something...
});
}])
I am trying to follow this tutorial
http://www.codeproject.com/Articles/784106/AngularJS-Token-Authentication-using-ASP-NET-Web-A
I don't know which angularjs package to download so that I could use localStorageService and ngAuthSettings in my angularjs code.
I am getting the following err when I run the mvc 5 asp.net vs2013 web api app.
Unknown provider: localStorageServiceProvider <- localStorageService <- authInterceptorService <- $http <- $templateRequest <- $compile
Here is my code.
var appointmentReminderApp = angular.module('appointmentReminderApp', ["ngRoute", "ui.bootstrap"]);
appointmentReminderApp.config(function ($routeProvider, $locationProvider,$httpProvider) {
$httpProvider.interceptors.push('authInterceptorService');
$locationProvider.html5Mode(true);
$routeProvider
.when("/home", {
templateUrl: "App/Home.html",
controller: "HomeController"
})
.when("/Register", {
templateUrl: "App/AuthForm/templates/register.html",
controller: "authRegisterController"
})
.when("/Login", {
templateUrl: "App/AuthForm/templates/login.html",
controller: "authLoginController"
})
.otherwise({ redirectTo: "/home" });
});
appointmentReminderApp.factory('authInterceptorService', ['$q', '$injector', '$location', 'localStorageService', function ($q, $injector, $location, localStorageService) {
var authInterceptorServiceFactory = {};
var _request = function (config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
var _responseError = function (rejection) {
if (rejection.status === 401) {
var authService = $injector.get('authService');
var authData = localStorageService.get('authorizationData');
if (authData) {
if (authData.useRefreshTokens) {
$location.path('/refresh');
return $q.reject(rejection);
}
}
authService.logOut();
$location.path('/login');
}
return $q.reject(rejection);
}
authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
return authInterceptorServiceFactory;
}]);
appointmentReminderApp.factory('authService', ['$http', '$q', 'localStorageService', 'ngAuthSettings', function ($http, $q, localStorageService, ngAuthSettings) {
var registerUser = function (auth) {
return $http.post("/api/Account/Register", auth);
};
var loginUser = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.Password;
if (loginData.useRefreshTokens) {
data = data + "&client_id=" + ngAuthSettings.clientId;
}
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
if (loginData.useRefreshTokens) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName, refreshToken: response.refresh_token, useRefreshTokens: true });
}
else {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName, refreshToken: "", useRefreshTokens: false });
}
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
_authentication.useRefreshTokens = loginData.useRefreshTokens;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
return {
registerUser: registerUser,
loginUser: loginUser
};
}
]);
Have you downloaded the angular local storage service module? do you have this line
<script src="scripts/angular-local-storage.min.js"></script>
in your index.html?
The required JS file doen't come bundled with Angular.
You can get it from here.
I was unable to find the CDN, will update if I find one.