=== "Python 3.10+"
- ```Python hl_lines="4 8 12 46 64 105 107-115 121-124 128-134 139 155"
+ ```Python hl_lines="5 9 13 47 65 106 108-116 122-125 129-135 140 156"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
+ ```Python hl_lines="2 5 9 13 47 65 106 108-116 122-125 129-135 140 156"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="2 4 8 12 47 65 106 108-116 122-125 129-135 140 156"
+ ```Python hl_lines="2 5 9 13 48 66 107 109-117 123-126 130-136 141 157"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="3 7 11 45 63 104 106-114 120-123 127-133 138 154"
+ ```Python hl_lines="4 8 12 46 64 105 107-115 121-124 128-134 139 155"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
+ ```Python hl_lines="2 5 9 13 47 65 106 108-116 122-125 129-135 140 156"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
+ ```Python hl_lines="2 5 9 13 47 65 106 108-116 122-125 129-135 140 156"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="62-65"
+ ```Python hl_lines="63-66"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="62-65"
+ ```Python hl_lines="63-66"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="63-66"
+ ```Python hl_lines="64-67"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="61-64"
+ ```Python hl_lines="62-65"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="62-65"
+ ```Python hl_lines="63-66"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="62-65"
+ ```Python hl_lines="63-66"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="155"
+ ```Python hl_lines="156"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="155"
+ ```Python hl_lines="156"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="156"
+ ```Python hl_lines="157"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="154"
+ ```Python hl_lines="155"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="155"
+ ```Python hl_lines="156"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="155"
+ ```Python hl_lines="156"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="4 139 170"
+ ```Python hl_lines="5 140 171"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="4 139 170"
+ ```Python hl_lines="5 140 171"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="4 140 171"
+ ```Python hl_lines="5 141 172"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="3 138 167"
+ ```Python hl_lines="4 139 168"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="4 139 168"
+ ```Python hl_lines="5 140 169"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="4 139 168"
+ ```Python hl_lines="5 140 169"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="8 105"
+ ```Python hl_lines="9 106"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="8 105"
+ ```Python hl_lines="9 106"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="8 106"
+ ```Python hl_lines="9 107"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="7 104"
+ ```Python hl_lines="8 105"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="8 105"
+ ```Python hl_lines="9 106"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="8 105"
+ ```Python hl_lines="9 106"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="105 107-115"
+ ```Python hl_lines="106 108-116"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="105 107-115"
+ ```Python hl_lines="106 108-116"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="106 108-116"
+ ```Python hl_lines="107 109-117"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="104 106-114"
+ ```Python hl_lines="105 107-115"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="105 107-115"
+ ```Python hl_lines="106 108-116"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="105 107-115"
+ ```Python hl_lines="106 108-116"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="46 116-127"
+ ```Python hl_lines="47 117-128"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="46 116-127"
+ ```Python hl_lines="47 117-128"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="47 117-128"
+ ```Python hl_lines="48 118-129"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="45 115-126"
+ ```Python hl_lines="46 116-127"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="46 116-127"
+ ```Python hl_lines="47 117-128"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="46 116-127"
+ ```Python hl_lines="47 117-128"
{!> ../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="128-134"
+ ```Python hl_lines="129-135"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="128-134"
+ ```Python hl_lines="129-135"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="129-135"
+ ```Python hl_lines="130-136"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="127-133"
+ ```Python hl_lines="128-134"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="128-134"
+ ```Python hl_lines="129-135"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="128-134"
+ ```Python hl_lines="129-135"
{!> ../../../docs_src/security/tutorial005.py!}
```
If you want to play with JWT tokens and see how they work, check <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>.
-## Install `python-jose`
+## Install `PyJWT`
-We need to install `python-jose` to generate and verify the JWT tokens in Python:
+We need to install `PyJWT` to generate and verify the JWT tokens in Python:
<div class="termy">
```console
-$ pip install "python-jose[cryptography]"
+$ pip install pyjwt
---> 100%
```
</div>
-<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">Python-jose</a> requires a cryptographic backend as an extra.
+!!! info
+ If you are planning to use digital signature algorithms like RSA or ECDSA, you should install the cryptography library dependency `pyjwt[crypto]`.
-Here we are using the recommended one: <a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>.
-
-!!! tip
- This tutorial previously used <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>.
-
- But it was updated to use Python-jose instead as it provides all the features from PyJWT plus some extras that you might need later when building integrations with other tools.
+ You can read more about it in the <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT Installation docs</a>.
## Password hashing
=== "Python 3.10+"
- ```Python hl_lines="7 48 55-56 59-60 69-75"
+ ```Python hl_lines="8 49 56-57 60-61 70-76"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="7 48 55-56 59-60 69-75"
+ ```Python hl_lines="8 49 56-57 60-61 70-76"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="7 49 56-57 60-61 70-76"
+ ```Python hl_lines="8 50 57-58 61-62 71-77"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="6 47 54-55 58-59 68-74"
+ ```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="7 48 55-56 59-60 69-75"
+ ```Python hl_lines="8 49 56-57 60-61 70-76"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="6 12-14 28-30 78-86"
+ ```Python hl_lines="4 7 13-15 29-31 79-87"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="6 12-14 28-30 78-86"
+ ```Python hl_lines="4 7 13-15 29-31 79-87"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="6 13-15 29-31 79-87"
+ ```Python hl_lines="4 7 14-16 30-32 80-88"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="5 11-13 27-29 77-85"
+ ```Python hl_lines="3 6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="6 12-14 28-30 78-86"
+ ```Python hl_lines="4 7 13-15 29-31 79-87"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="89-106"
+ ```Python hl_lines="90-107"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="89-106"
+ ```Python hl_lines="90-107"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="90-107"
+ ```Python hl_lines="91-108"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="88-105"
+ ```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="89-106"
+ ```Python hl_lines="90-107"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10+"
- ```Python hl_lines="117-132"
+ ```Python hl_lines="118-133"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
- ```Python hl_lines="117-132"
+ ```Python hl_lines="118-133"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.8+"
- ```Python hl_lines="118-133"
+ ```Python hl_lines="119-134"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="114-129"
+ ```Python hl_lines="115-130"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
!!! tip
Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="115-130"
+ ```Python hl_lines="116-131"
{!> ../../../docs_src/security/tutorial004.py!}
```
It gives you all the flexibility to choose the ones that fit your project the best.
-And you can use directly many well maintained and widely used packages like `passlib` and `python-jose`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
+And you can use directly many well maintained and widely used packages like `passlib` and `PyJWT`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.
from datetime import datetime, timedelta, timezone
from typing import Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
- except JWTError:
+ except InvalidTokenError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel
from typing_extensions import Annotated
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
- except JWTError:
+ except InvalidTokenError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import Annotated
+import jwt
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
- except JWTError:
+ except InvalidTokenError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import Annotated, Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
- except JWTError:
+ except InvalidTokenError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
+import jwt
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
- except JWTError:
+ except InvalidTokenError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import List, Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
SecurityScopes,
)
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel, ValidationError
raise credentials_exception
token_scopes = payload.get("scopes", [])
token_data = TokenData(scopes=token_scopes, username=username)
- except (JWTError, ValidationError):
+ except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import List, Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
SecurityScopes,
)
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel, ValidationError
from typing_extensions import Annotated
raise credentials_exception
token_scopes = payload.get("scopes", [])
token_data = TokenData(scopes=token_scopes, username=username)
- except (JWTError, ValidationError):
+ except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import Annotated
+import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
SecurityScopes,
)
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel, ValidationError
raise credentials_exception
token_scopes = payload.get("scopes", [])
token_data = TokenData(scopes=token_scopes, username=username)
- except (JWTError, ValidationError):
+ except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import Annotated, List, Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
SecurityScopes,
)
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel, ValidationError
raise credentials_exception
token_scopes = payload.get("scopes", [])
token_data = TokenData(scopes=token_scopes, username=username)
- except (JWTError, ValidationError):
+ except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
+import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
SecurityScopes,
)
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel, ValidationError
raise credentials_exception
token_scopes = payload.get("scopes", [])
token_data = TokenData(scopes=token_scopes, username=username)
- except (JWTError, ValidationError):
+ except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
from datetime import datetime, timedelta, timezone
from typing import Union
+import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import (
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
SecurityScopes,
)
-from jose import JWTError, jwt
+from jwt.exceptions import InvalidTokenError
from passlib.context import CryptContext
from pydantic import BaseModel, ValidationError
raise credentials_exception
token_scopes = payload.get("scopes", [])
token_data = TokenData(scopes=token_scopes, username=username)
- except (JWTError, ValidationError):
+ except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
databases[sqlite] >=0.3.2,<0.7.0
flask >=1.1.2,<3.0.0
anyio[trio] >=3.2.1,<4.0.0
-python-jose[cryptography] >=3.3.0,<4.0.0
+PyJWT==2.8.0
pyyaml >=5.3.1,<7.0.0
passlib[bcrypt] >=1.7.2,<2.0.0