# Expiring Tokens

```{note}
This functionality is introduced in version 0.3.0.
```

JWTs should not be long-lived. This prevents the misuse of
them by bad actors.

One method to do that is to use the
[`"exp"`](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4)
claim defined in the JSON Web Token standard.

The "problem" with using the `"exp"` claim is that it is in
the format of a `NumericDate` which is defined as the
following:

> A JSON numeric value representing the number of seconds
> from 1970-01-01T00:00:00Z UTC until the specified UTC
> date/time, ignoring leap seconds.  This is equivalent to
> the IEEE Std 1003.1, 2013 Edition
> [[POSIX.1](https://www.rfc-editor.org/rfc/rfc7519#ref-POSIX.1)]
> definition "Seconds Since the Epoch", in which each day is
> accounted for by exactly 86400 seconds, other than that
> non-integer values can be represented.  See [RFC
> 3339](https://www.rfc-editor.org/rfc/rfc3339) for details
> regarding date/times in general and UTC in particular.

That's no fun to calculate. Therefore, the `jwtdown-fastapi`
library does that for you.

## Setting the default expiration

Since version 0.3.0, the `Authenticator` will set the
expiration time for a JWT one hour after it is created. You
can change the default expiration duration by passing in a
`timedelta` when you create the `Authenticator`.

Let's say that you wanted the JWT to expire in two hours
rather than one. You would create a new `timedelta` for two
hours, then pass that into the initialization of the
`Authenticator` object.

```python
# authenticator.py
import os
from datetime import timedelta
from jwtdown_fastapi.authentication import Authenticator


class MyAuthenticator(Authenticator):
    # Your implementation of Authenticator


two_hours = timedelta(hours=2)


authenticator = MyAuthenticator(
  os.environ["SIGNING_KEY"],
  exp=two_hours,
)
```

## Expiration per JWT

In some use cases, you may want to set the expiration for
a JWT on a per-JWT basis. You can do that by overriding the
[`Authenticator.get_exp`](Authenticator.get_exp) method.

The following code checks to see if an account has the
_admin_ role and, if so, will set the expiration at 15
minutes to prevent misuse of the token.

```python
# authenticator.py
import os
from datetime import timedelta
from jwtdown_fastapi.authentication import Authenticator
from pydantic import BaseModel


class MyAuthenticator(Authenticator):
    # Your implementation of Authenticator

    def get_exp(
        self,
        proposed: timedelta,
        account: Optional[Union[BaseModel, dict]],
    ) -> timedelta:
        if "admin" in account.roles:
            return timedelta(minutes=15)
        return proposed


authenticator = MyAuthenticator(os.environ["SIGNING_KEY"])
```
