How to catch wrong password/username response in angular? - angularjs

I’m trying to implement authentication in my angularjs app.
I’ve read some articles about doing this properly. Here is one, for instance: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec
But I can’t realize how to make it respond on wrong username/password pair.
Let’s have a look at this code :
authService.login = function (credentials) {
return $http
.post('/login', credentials)
.then(function (res) {
// populate user info
}
);
};
I’ve tried to add here a second callback to “then” method and use “success”/”error” methods instead of “then” and I’ve tried to response on $http.post request with different error like 400 and 500 via status, but in any case all the errors are handled by the success method and callback.
What am I doing wrong? How to catch wrong password/username response in angular?

It was actually my own fault. My custom Intereptor simply swallowed authenticaion errors.

Related

AngularJS $http get callback not being called with status code 401?

I have the following service that runs when I navigate to a products page:
app.factory('ProductService',['$http','$location',function($http,$location){
var factory = {};
factory.getAll = function(){
$http.get('/products').success(function(response){
console.log('success callback hit');
if(response.status === 401){
console.log(response);
$location.path('login');
}
}).error(function(){
console.log('error');
});
};
return factory;
}]);
In my express router, I check if req.isAuthenticated() and if not (which is the case I'm testing), I call:
return res.status(401).send("Not Authorized");
That's the only place in my server where I send a 401 response, so I know the $http.get(/products) is going to the right place, and I see the get request returning 401 in my console, but why aren't any of my callbacks being hit? (Nothing is logged to the console and I don't get redirected on the client.) I read something about needing to reject the promise if I'm using global interceptors, but I don't think I am using any interceptors? EDIT: This is why I don't think it's a duplicate of the question suggested since I'm not using custom interceptors.
UPDATE: My error handler was getting called, just nothing was logged in my node.js command window (duh, because it's on the client). Thanks for the help everyone!
My error handler was getting called, just nothing was logged in my node.js command window (duh, because it's on the client). Thanks for the help everyone!

Unexpected token u in Restangular Error Interceptor

I'm using Restangular interceptor to handle errors with status code as 412,409 etc.
But I'm not getting status in the requestInterceptor function.
I have declared the Restangular RequestInterceptor using Typescript.
In my app.ts file,
app.run(Restangular){
Restangular.setErrorInterceptor(function(response) {//code to handle error});
}
Error:
Restangular provides an option to access a full response access, probably setting up this might help. By using Restangular.setFullResponse(true) you should be able to access the status code in your interceptor.
So, I guess according to your snippet now it could look like this(since there is where you are injecting Restangular if you have any other configuration section that where the setting should go)
app.run(Restangular){
Restangular.setFullResponse(true);
Restangular.setErrorInterceptor(function(response) {//code to handle error});
}
It's important to point out that setting up this option, now the access to your responses will be sightly different for all your services unless you create something to handle the next .data behavior:
function(response){
var result = response.data;
var statusCode = result.status;
var responseData = result.myApiResponse;
}
For more information please check: https://github.com/mgonto/restangular#setfullresponse, and hope my post helps.

Error callback on resource method

I'm trying to do different actions when getting 409 response from the server on a resource's method.
Basically I have the same problem as in AngularJS service not invoking error callback on save() method, I've tried all the answers but I always get the success callback.
$scope.form.$save(function (data, headers) {
console.log(data, headers);
}, function(error) {
console.log('fail');
});
Can anyone give a definitive answer if this is fixed, and if / what I do wrong?
Turned out I had an custom debug-interceptor that didn't explicitly return a $q.reject(response).
Apparently every custom debug-interceptor completely overwrites the default behavior.
See https://github.com/angular/angular.js/issues/2609#issuecomment-44452795 for where I found the answer.

angularjs custom REST action and error handling

I'm having some trouble with error handling in a little angularjs application. I'm interacting with a Flask backend and a Postgres DB.
I have a factory service
appointServices.factory('Appointments', ['$resource', function($resource){
return $resource(someUrl, {}, {
query: { ... }
,
create: {
method: 'POST'
,url: 'http://somedomain:port/new/:name/:start/:end/:treatment'
,params: { start: '#start', end: '#end', name: '#name', treatment: '#treatment' }
,isArray:false
}
});
}
]);
Inside a controller I'm making the following call
Appointments.create($scope.appointment, function(value, responseHeaders) {
// success handler
console.debug('success: ', JSON.stringify(value));
}, function(httpResponse) {
// error handler
console.debug('error: ', JSON.stringify(httpResponse));
});
Here $scope.appointment contains the relevant parameters for the create action.
Now, in the backend I'm able to catch DB errors involving constraints and I'm trying to return an error code with a 'meaningful' message. So I have a python method
def create(name, start, end, treatment):
try:
...
transaction_status = 'ok'
code = 200
except IntegrityError as e:
...
transaction_status = 'IntegrityError'
code = 500
finally:
...
return make_response(transaction_status, code)
Everything works fine, I'm able to talk to the backend, create new data and insert this in the DB. As I said, any violation of the constraints is detected and the backend responds
curl -X POST "http://somedomain:port/new/foo/bar/baz/qux" -v
...
< HTTP/1.0 500 INTERNAL SERVER ERROR
...
IntegrityError
So, the problem is, no matter whether the action create was successful or not, the intended error handler specified inside the controller is always fired. Moreover, I always end up with a status code 404 in the httpResponse. Firebug shows correctly the code 500 as above, though.
Anybody has any idea of why I'm getting this behavior?
Any suggestions on how to improve the error handling mechanism are also welcome.
Thx in advance.
P.S. Following the documentation on $resource I have also tried variations on the factory service call, e.g.
Appointments.create({}, $scope.appointment, successCallback, errorCallback);
Appointments.create($scope.appointment, {}, successCallback, errorCallback);
with the same results.
Update:
Forgot to mention the important fact that I'm interacting with the backend via CORS requests. The POST request in create above is having place with the OPTIONS method instead. As I mentioned everything is working correctly except for the error response.
Under further investigation, I tried to isolate the factory service, in case I did something wrong, and I also tried the approach shown in the credit card example ($resource docs), but with no positive result.
However, I came up with two workarounds. Firstly, I was able to create a plain JQuery POST request, as in the example shown in the docs. This time, the request is not replaced by OPTIONS and I got the error code correctly.
I also managed to connect to the backend with the low-level $http service as follows:
var urlBase = 'http://somedomain:port/new/:name/:start/:end/:treatment';
var url = urlBase.replace(/:name/g, $scope.appointment.name);
url = url.replace(/:start/g, $scope.appointment.start);
url = url.replace(/:end/g, $scope.appointment.end);
url = url.replace(/:treatment/g, $scope.appointment.treatment);
// force method to be POST
var futureResponse = $http({ method: 'POST', url: url });
futureResponse.success(function (data, status, headers, config) {
console.debug('success: ', JSON.stringify(data));
});
futureResponse.error(function (data, status, headers, config) {
console.group('Error');
console.debug(JSON.stringify(status));
console.debug(JSON.stringify(data));
console.groupEnd();
});
This time, as in the case of JQuery, the request is done effectively with POST and error codes are correctly received.
Notice also that I'm not calling $http.post but I set the method to POST as part of the object parameter to $http, otherwise the connection takes places with OPTIONS as before.
Still trying to figure out what is happening with $resource.

303 redirection not working with Angular HTTP POST

I am calling an authentication service where I do a $http.post which returns a 303 resonse, redirecting to a get call returning the response.
When I make the post call using Postman, I get the desired response but when I do an angular $http.post call, it returns me a 401 error (which is user not authorized)
Am I missing something while making the angular call? The backend service seems to work fine as it works fine on Postman.
This is how the $http call looks:
$http.post(url, userData).success(function(data, status) {
//handle success
}.error(function(data, status) {
//handle error
});
The url and the user data is constructed absolutely fine in this case.
The reason that you get a GET call is that the browser handle the 303 response before the angular can reach that. And the handling sequence is first go to the browser and then go to the angular framework.
So briefly what happens is : you make call to the server --> the server return the 303 response -> your browser handle the 303 and make a request to some url (should be 'location' in the response header) --> the server receive the request and return the 401 authorized response --> again the browser receive the 401 response first but this time the browser redirect the response to the angular --> at last you can receive the data and status inside the error().
The solution for this could be switching to other response status code like 2xx, and you can get the location from the body. Then you can do the redirection manually. If you HAVE to use 303 or other 3xx as the response code I don't think there's any effective solution at this moment because you can't do much to the browser. As far as I know there might be a solution at browser level but don't know when that will happen.
Hope this can help anyone has the similar issue like this although it has been nearly one year since this issue raised.
Some other ref: https://groups.google.com/forum/#!topic/angular/GKkdipdMbdo
There's similar solution you can see from the link above.
I faced this issue and I found a redirect url in error object after lots of hours struggle.
loginWithLinkedIn() {
let data = {
// some kind of information here
}
return this.http.get(`https://www.someurl.com/oauth/v2/authorization`).subscribe(res => {
console.log(res)
}, err => {
console.log(err.url) // here is the redirect url
window.location.href = err.url
})
}
Note: when you make a request and you get 303 response which is considered as error, that's why we think we are getting error but error contains useful info.

Resources