确定承载令牌是否已过期或是否已获得授权

时间:2014-11-12 18:47:26

标签: angularjs asp.net-web-api owin bearer-token

我的角色应用程序正在使用文章系列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错误。继承人我的拦截器中的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 个答案:

答案 0 :(得分:15)

正如我对Cory Silva评论的回应中所述,Web API授权属性将始终返回401未经授权的身份验证和授权。

请参阅下面的文章和主题:

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

Why does AuthorizeAttribute redirect to the login page for authentication and authorization failures?

看起来有两种选择:

  1. 当我将从我的授权服务器检索到的令牌存储在localStorage中时,我还存储了令牌的到期日期。在拦截器responseError函数中,我将存储的令牌到期与当前日期时间进行比较。如果确定已过期,请刷新令牌并重新发送请求。

    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);
            }
        }
    }
    
  3. 我想我会使用选项2,以便错误代码对客户端更清晰。