Определите, истек ли срок действия токена на предъявителя или он просто авторизован

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

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

для например, мой метод web api имеет атрибут [Authorize (Roles="Admin")]. Когда я делаю вызов этому, я возвращаю свою ошибку 401, которая ожидается. Однако, когда мой токен доступа истекает, и я делаю другой вызов метода Web api, он также возвращает ошибку 401. Вот мой обработчик 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 unauthorized как для аутентификации, так и для авторизации.

см. статью и поток ниже:

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

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

похоже, что их два опции:

  1. когда я храню токен, полученный с моего сервера авторизации в localStorage, я также сохраняю срок действия токена. В функции interceptor responseError я сравниваю срок действия сохраненного маркера с текущим временем 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;
    }
    
  2. используйте принятый ответ в потоке 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, чтобы коды ошибок немного яснее для клиента.