witoldsz / angular-http-auth

MIT License
2.38k stars 417 forks source link

Failed Login 401 Response Problem #25

Closed ChristianKohler closed 11 years ago

ChristianKohler commented 11 years ago

Problem

It's not possible to evaluate the response in case of a failed login if the server responsed with a 401.

Quick Fix

Set the ignoreAuthModule flag on the server response in case of a failed login attempt.

Better Fix

I have two ideas how to improve the interceptor

What do you think?

witoldsz commented 11 years ago

Hi, I was investigating path-based white-list and finally decided to go with ignoreAuthModule flag.

What I do not like about the white-list is that the behavior of particular promise would be (could be) spread around. It could cause something like butterfly effect: you do a minor refactoring of URL address in one place, forget to check the white-list specified elsewhere and suddenly your promise is handled differently. The difference would be quite hard to figure out by someone is not familiar with the secrets of the white-list and it's influence to every $http call in the system

The ignoreAuthModule flag is very explicit and defined right on the spot. No comments on the "lastResponse" method.

laurelnaiad commented 11 years ago

In PR https://github.com/witoldsz/angular-http-auth/pull/28 I added the response.data that comes from the server with the 401 (or 403) to the event that is broadcasted (auth-loginRequired or auth-forbidden) ... would that help with this issue?

latkins commented 11 years ago

Hey,

I was wondering how it was possible to set this flag in the config itself? The docs on $http seem to indicate that it isn't possible to set custom params, but the code checks for !response.config.ignoreAuthModule. Is this a bug, or am I missing something?

Cheers.

witoldsz commented 11 years ago

@exicer I am sorry, but I do not get your question. Where does $http docs indicate that is is not possible to set custom parameter on a configuration object? This is just a plain object and we can examine it in filter.

latkins commented 11 years ago

Ah, sorry you are quite right. I am just getting to grips with angular, and misread the docs!

jscti commented 11 years ago

I don't understand how to use the ignoreAuthModule flag.. do you have an example ? Thanks

laurelnaiad commented 11 years ago

I use it so that when I post my login info, it doesn't intercept 401s when the user supplies incorrect credentials.

If I didn't do this, the interceptor would intercept failed logins and thus I would stack up retry requests in the interceptor's buffer while the user sorts out his/her credentials. That is why I use ignoreAuthModule.

Apologies for the Coffeescript, I just recently became hooked.

In my session manager service's login function -- I pass the ignoreAuthModule parameter as true to my AJAX service (data) -- note "model" is the credentials and "d" is an outer deferred promise. This is the only AJAX request that I set the flag for.

data.postDoc(model, ignoreAuthModule = true).then(
          ( response ) ->
            setSession response
            d.resolve()
          ( reason ) ->
            d.reject reason
        )

In my generalized data service, I pass through the parameter, which almost all of the time is undefined. In the case of login, since I set the flag, it comes out true, and thus I can handle incorrect logins without interference from the interceptor.

      $http({
        method: 'POST'
        url: '/v1/' + doc.url
        cache: false
        data: data
        ignoreAuthModule: ignoreAuthModule
      }).success(
        (data, status) ->
          d.resolve(data)
      ).error(
        (data, status) ->
          handleError d, data, status
      )
jscti commented 11 years ago

Thanks for your (quick) reply. I'm exactly in the same case here but I'm using ngResource services functionnalities ... and well I've tried to inject the "ignoreAuthModule" param everywhere without success :

angular.module('my.services', [ 'ngResource' ])
.factory('Login', function($resource, $rootScope) {
  return $resource($rootScope.externalHost + '/auth.json', {}, {
    query : {
      method : 'GET',
      params : {
        login : null,
        password : null
      },
      isArray : true
    }
  });
});

Any clue ?

Sorry if it's off topic as I'm pretty new to angular. By the way, thanks for this helpfull module.

laurelnaiad commented 11 years ago

I don't use $resource, but my best guess is that you could set the flag in the query object. However, I assume that if you've tried everywhere then you've already tried it. Are you saying that the interceptor is intercepting the following?

    query : {
      method : 'GET',
      params : {
        login : null,
        password : null
      },
      isArray : true,
      ignoreAuthModule: true
    }
jscti commented 11 years ago

Yep Tried this, and it doesn't work. Request is intercepted (response.config is empty / without the flag)

laurelnaiad commented 11 years ago

The point is not to get the flag back from the response... the point is for the interceptor not to intercept the response. If you're not getting the interception event, then it's working.

jscti commented 11 years ago

Well I know, I was debugging the lib to understand what happens. It's definitely intercepted.

jscti commented 10 years ago

Hi,

No news about my case ? For now, "for the interceptor not to intercept the response" I send a crappy 402 HTTP status code instead of a 401, but isn't there any better solution with this ignoreAuthModule flag ?

Thanks

witoldsz commented 10 years ago

@bixibu I have lost the plot here, can you explain again, why can't you add ignoreAuthModule: true as a parameter to your login request?

jscti commented 10 years ago

Hi

while calling a login webservice thats returns a 401 when auth fails :

angular.module('my.services', [ 'ngResource' ]) .factory('Login', function($resource, $rootScope) { return $resource('http://domain.com/auth.json', {}, { query : { method : 'GET', params : { login : null, password : null }, isArray : true, ignoreAuthModule: true } }); });

I want it to be not intercepeted (it's pointless to add this HTTP to the queue as it's just a failed login attempt) but it is intercepted even with the flag (if I go in debug mode in your lib, I can see that the response.config is empty / without the flag.

I tried to put the flag in every manner I could without success.

Thanks for the help

witoldsz commented 10 years ago

Did you check the source code of ngResource to figure it out? Just see how does it "play" with $http, it should give you clear answer.