Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if bearer token has expired or is just authorized

My angular application is making use of bearer tokens as outlined in the article series http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/. I have followed the forked example to seamlessly refresh tokens when the access token has expired (via 401 http code).

My question is how can I determine if the bearer token is expired or just plain unauthorized based on the role determined?

For example, my web api method has the attribute [Authorize(Roles="Admin")]. When I make a call to that, I get back my 401 error, which is expected. However, when my access token expires and I make another web api method call, it also returns a 401 error. Heres my responseError handler in my interceptor:

        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;
        }

I was playing around with different things but basically, I'd like to refresh my token and resend my request when the access token has expired; however, I don't want to refresh my token if it truly is a denied request due to the role specified.

Any thoughts?

like image 213
mmoreno79 Avatar asked Nov 12 '14 18:11

mmoreno79


People also ask

How do you check bearer token is expired or not?

This can be done using the following steps: convert expires_in to an expire time (epoch, RFC-3339/ISO-8601 datetime, etc.) store the expire time. on each resource request, check the current time against the expire time and make a token refresh request before the resource request if the access_token has expired.

How can I check my token status?

Once you are logged in, from your user menu pick My access token option. In access token status section you can find out if your access token is active or not. If you see ACTIVE it means that everything is OK and your access token is working fine. If you see NOT ACTIVE status, you should refresh your access token.

How do you check access token is expired or not in Web API?

The easiest way is to just try to call the service with it. It will reject it if it is expired and then you can request a new one. You can also keep the time you received the token and use the expires_in to calculate when it will approximately expire.

Is bearer token used for authentication or authorization?

The most common way of accessing OAuth 2.0 APIs is using a “Bearer Token”. This is a single string which acts as the authentication of the API request, sent in an HTTP “Authorization” header.

How to request a new token after it has expired?

The easiest way is to just try to call the service with it. It will reject it if it is expired and then you can request a new one. You can also keep the time you received the token and use the expires_in to calculate when it will approximately expire. Then you request a new token before making a new request after the expiration date.

How do I get the Bearer Token from the Authorization header?

} The bearer token is made of an access_token property and a refresh_token property. As defined by HTTP/1.1 [RFC2617], the application should send the access_token directly in the Authorization request header. You can do so by including the bearer token's access_token value in the HTTP request body as 'Authorization: Bearer {access_token_value}'.

How to revoke an API Bearer Token?

You can revoke a token if a user is no longer permitted to make requests on the API or if the token has been compromised. The API bearer token's properties include an access_token / refresh_token pair and expiration dates.

What does the “expires” value on an access token mean?

The “expires” value is the number of seconds that the access token will be valid. It’s up to the service you’re using to decide how long access tokens will be valid, and may depend on the application or the organization’s own policies.


1 Answers

As noted in my response to Cory Silva's comment, the Web API Authorize attribute will always return 401 unauthorized for both authentication AND authorization.

See article and thread below:

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

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

It looks like there are two options:

  1. When I store the token retrieved from my authorization server in localStorage, I also store the token's expiration. In the interceptor responseError function, I compare the stored token expiration with the current datetime. If it's determined to be expired, refresh the token and resend the request.

    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. Use the accepted answer in the stackoverflow thread I referenced above and create my own AuthorizeAttribute to determine token expiration vs. unauthorized access.

    [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);
            }
        }
    }
    

I think I'm going to use option 2 so that the error codes a little clearer to the client.

like image 86
mmoreno79 Avatar answered Sep 23 '22 07:09

mmoreno79