Is there any way to check if oauth token is expired or not?

27,490

Solution 1

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.

Solution 2

Resurrecting this post once again and taking @Lavandysh's solution and pulling in the System.IdentityModel.Tokens.Jwt class; call this method to have an idea if the token is even valid anymore before the request:

    public bool _isEmptyOrInvalid (string token)
    {
        if (string.IsNullOrEmpty(token))
        {
            return true;
        }

        var jwtToken = new JwtSecurityToken(token);
        return (jwtToken == null) || (jwtToken.ValidFrom > DateTime.UtcNow) || (jwtToken.ValidTo < DateTime.UtcNow);
    }

Solution 3

I know this is an old post, but there is a more direct way. If you decode the token from Base64 format you can see what the expiration date is, then you can compare it with the date right now.

If you want to check if this method works you can use this website to decode the token.

Now, in C# you run against some difficulties since the token contains '.' that cannot be decoded and if you only take out the middle part between the two points the length becomes invalid (it should always be a multitude of 4). To make the middle part have a correct length you can add '=' signs until it is a multitude of 4.

In the end I compare the date with the current dat plus a minute. Because I don't want a token that will expire in a second to be considered valid. You might want to adjust that time to suit your purposes.

So here's my code:

    /***
     * Check if the string token is expired by decoding it from the Base64 string
     * Some adjustements to the string are necessairy since C# can only decode certain strings.
     * It cannot handle '.' and requires a string has a length that is a multitude of 4.
     * The information we are interrested in is found between the dots.
     * 
     * The token that is given as a parameter should have approximately the following structure:
     * ddddddddddddddddddddd.ddddddddddddddddddddddddddddddddddddd.dddddddddddddddddddddddddddd
     * And should be a valid Oauth token that may or may not be expired
     */
    public static bool isExpired(String token)
    {
        if (token == null || ("").Equals(token))
        {
            return true;
        }

        /***
         * Make string valid for FromBase64String
         * FromBase64String cannot accept '.' characters and only accepts stringth whose length is a multitude of 4
         * If the string doesn't have the correct length trailing padding '=' characters should be added.
         */
        int indexOfFirstPoint = token.IndexOf('.') + 1;
        String toDecode = token.Substring(indexOfFirstPoint, token.LastIndexOf('.') - indexOfFirstPoint);
        while (toDecode.Length % 4 != 0)
        {
            toDecode += '=';
        }

        //Decode the string
        string decodedString = Encoding.ASCII.GetString(Convert.FromBase64String(toDecode));

        //Get the "exp" part of the string
        String beginning = "\"exp\":\"";
        int startPosition = decodedString.LastIndexOf(beginning) + beginning.Length;
        decodedString = decodedString.Substring(startPosition);
        int endPosition = decodedString.IndexOf("\"");
        decodedString = decodedString.Substring(0, endPosition);
        long timestamp = Convert.ToInt64(decodedString);

        DateTime date = new DateTime(1970, 1, 1).AddMilliseconds(timestamp);
        DateTime compareTo = DateTime.Now.AddMinutes(1);

        int result = DateTime.Compare(date, compareTo);

        return result < 0;
    }

Solution 4

I got that problem when I was developing a Xamarin Forms application. The main problem here is that I couldn't install any Nuget in the project. So I decide to improve @Lavandysg answer, since It isn't extracting the expiration timestamp correctly and It isn't calculating the expiration time correctly. Here is my final code using regex to extract expiration time from token:

public bool IsTokenExpired(string token)
        {
            if (token == null || ("").Equals(token))
            {
                return true;
            }

            /***
             * Make string valid for FromBase64String
             * FromBase64String cannot accept '.' characters and only accepts stringth whose length is a multitude of 4
             * If the string doesn't have the correct length trailing padding '=' characters should be added.
             */
            int indexOfFirstPoint = token.IndexOf('.') + 1;
            String toDecode = token.Substring(indexOfFirstPoint, token.LastIndexOf('.') - indexOfFirstPoint);
            while (toDecode.Length % 4 != 0)
            {
                toDecode += '=';
            }

            //Decode the string
            string decodedString = Encoding.ASCII.GetString(Convert.FromBase64String(toDecode));

            //Get the "exp" part of the string
            Regex regex = new Regex("(\"exp\":)([0-9]{1,})");
            Match match = regex.Match(decodedString);
            long timestamp = Convert.ToInt64(match.Groups[2].Value);

            DateTime date = new DateTime(1970, 1, 1).AddSeconds(timestamp);
            DateTime compareTo = DateTime.UtcNow;

            int result = DateTime.Compare(date, compareTo);

            return result < 0;
        }
Share:
27,490
Gaurav123
Author by

Gaurav123

Updated on July 17, 2022

Comments

  • Gaurav123
    Gaurav123 almost 2 years

    I am accessing web api using oauth token.

    Token expires after 1 hour. But I want to add functionality to generate new token when it expires.

    I found that in case of expired token it sends StatusCode as unauthorized.

    Please let me know if its the only statuscode which tells about expiration of token.

  • Gaurav123
    Gaurav123 about 8 years
    When I will call the service, it will reject in with which status code ?
  • Patrick Hofman
    Patrick Hofman about 8 years
    It will give a HTTP 401, Unauthorized.
  • Gaurav123
    Gaurav123 about 8 years
    this will be the only StatusCode it will send when the token is expired ?
  • Patrick Hofman
    Patrick Hofman about 8 years
    Usually it is, yes. 403 is used to tell you don't have access to it when you have a valid token.
  • Lavandysh
    Lavandysh about 3 years
    For my information, why could you not install a Nuget package? Was that simply a requirement that you had or is there a reason why one shouldn't? I also used my code in a Xamarin project, works well.
  • Ângelo Polotto
    Ângelo Polotto about 3 years
    Company security policy. Install or update packages are restricted.
  • Lavandysh
    Lavandysh about 3 years
    Thank you, had me worried there was something I had overlooked
  • Ângelo Polotto
    Ângelo Polotto about 3 years
    The problems with your solution was the Exp string extraction, for me, your solution isn't working. Other problem is in the line DateTime(1970, 1, 1).AddMilliseconds(, the time of Expiration time is in seconds and not in milliseconds, so, just change to AddSeconds. If you want, I can edit your question and delete mine to unify both answers. Do you want that?
  • Lavandysh
    Lavandysh about 3 years
    No thank you, I'm just happy for the constructive feedback. Thanks a lot. For me, my code probably works because the server part was also written in-house following the protocol. So I guess our expiration time is simply also set in milliseconds serverside, I'll double-check later.
  • Ângelo Polotto
    Ângelo Polotto about 3 years
    I recommend you replace your string extraction to Regex. In that way, you don't worry about the string length. No problem. Any question just ask here.
  • Lavandysh
    Lavandysh about 3 years
    Yes, I did like that idea, improves readability too.
  • hylander0
    hylander0 about 3 years
    It really depends on the implementation. 403 should tell that you are authenticated but the resource you are requesting is not allowed by YOU. 401 is tell you nothing more than your token is wrong, expired/wrong/invalid/bad. There is no ALMOST status with authentication.