Определите, истек ли токен-носитель или просто разрешен

В моем приложении angular используются токены-носители, как описано в серии статей http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/. Я пошел по раздвоенному примеру, чтобы плавно обновлять токены, когда токен доступа истек (через 401 http-код).

Мой вопрос в том, как я могу определить, истек ли токен-носитель или просто несанкционирован на основании определенной роли?

Например, мой метод web api имеет атрибут [Authorize (Roles = "Admin" )]. Когда я звоню на это, я возвращаю свою ошибку 401, которая ожидается. Однако, когда мой токен доступа истекает, и я вызываю другой вызов метода web api, он также возвращает ошибку 401. Heres my responseError обработчик в моем перехватчике:

        responseError: function (rejection) {
            var deferred = q.defer();
            if (rejection.status === 401) {
                var authService = $injector.get('authService');
                authService.refreshToken().then(function (response) {
                    _retryHttpRequest(rejection.config, deferred);
                }, function () {
                    authService.logOut();
                    $location.path('/dashboard');
                    deferred.reject(rejection);
                });
            } else {
                deferred.reject(rejection);
            }
            return deferred.promise;
        }

Я играл с разными вещами, но в основном, я хотел бы обновить свой токен и повторно отправить мой запрос, когда токен доступа истек; однако я не хочу обновлять свой токен, если это действительно отрицаемый запрос из-за указанной роли.

Любые мысли?

Ответы

Ответ 1

Как отмечалось в моем ответе на комментарий Кори Сильвы, атрибут авторизации Web API всегда возвращает 401, неавторизованный как для аутентификации, так и для авторизации.

См. статью и нить ниже:

http://leastprivilege.com/2014/10/02/401-vs-403/

Почему AuthorizeAttribute перенаправляет на страницу входа для проверки подлинности и авторизации?

Похоже, есть два варианта:

  • Когда я храню токен, полученный с моего сервера авторизации в localStorage, я также сохраняю срок действия маркера. В функции ответа на перехват перехватчика я сравниваю время хранения хранимого токена с текущим временем datetime. Если срок его действия истек, обновите токен и отправьте запрос повторно.

    responseError: function (rejection) {
        var deferred = q.defer();
    
        if (rejection.status === 401) {
            var tokenExpired = false;
            var authData = localStorage.get('authorizationData');
            if (authData) {
                tokenExpired = moment().isAfter(authData.expiration);
            }
    
            if (tokenExpired) {
                var authService = auth;//$injector.get('authService');
                authService.refreshToken().then(function (response) {
                    _retryHttpRequest(rejection.config, deferred);
                }, function () {
                    authService.logOut();
                    $state.go('error');
                    deferred.reject(rejection);
                });
            }
            else {
                $state.go('error');
                deferred.reject(rejection);
            }
        } else {
            $state.go('error');
            deferred.reject(rejection);
        }
        return deferred.promise;
    }
    
  • Используйте принятый ответ в потоке stackoverflow, на который я ссылался выше, и создаю свой собственный атрибут AuthorizeAttribute для определения срока действия токена против несанкционированного доступа.

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : System.Web.Http.AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
            }
            else
            {
                base.HandleUnauthorizedRequest(actionContext);
            }
        }
    }
    

Я думаю, что я буду использовать вариант 2, чтобы код ошибки стал немного более понятным для клиента.