Skip to content

Commit 7bffd65

Browse files
author
IndominusByte
committed
update examples
1 parent 44c46c1 commit 7bffd65

19 files changed

+322
-618
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
[![Build Status](https://travis-ci.org/IndominusByte/fastapi-jwt-auth.svg?branch=master)](https://travis-ci.org/IndominusByte/fastapi-jwt-auth)
44
[![Coverage Status](https://coveralls.io/repos/github/IndominusByte/fastapi-jwt-auth/badge.svg?branch=master)](https://coveralls.io/github/IndominusByte/fastapi-jwt-auth?branch=master)
55
[![PyPI version](https://badge.fury.io/py/fastapi-jwt-auth.svg)](https://badge.fury.io/py/fastapi-jwt-auth)
6-
[![Downloads](https://pepy.tech/badge/fastapi-jwt-auth/month)](https://pepy.tech/project/fastapi-jwt-auth/month)
76
[![Downloads](https://pepy.tech/badge/fastapi-jwt-auth)](https://pepy.tech/project/fastapi-jwt-auth)
87

98
## Features

docs/index.md

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1 @@
1-
<h1 align="center" style="margin-bottom: 20px; font-weight: 500; font-size: 50px;">
2-
FastAPI JWT Auth
3-
</h1>
4-
<p align="center">
5-
<em>FastAPI extension that provides JWT Auth support (secure, easy to use, and lightweight)</em>
6-
</p>
7-
8-
[![Build Status](https://travis-ci.org/IndominusByte/fastapi-jwt-auth.svg?branch=master)](https://travis-ci.org/IndominusByte/fastapi-jwt-auth)
9-
[![Coverage Status](https://coveralls.io/repos/github/IndominusByte/fastapi-jwt-auth/badge.svg?branch=master)](https://coveralls.io/github/IndominusByte/fastapi-jwt-auth?branch=master)
10-
[![PyPI version](https://badge.fury.io/py/fastapi-jwt-auth.svg)](https://badge.fury.io/py/fastapi-jwt-auth)
11-
[![Downloads](https://pepy.tech/badge/fastapi-jwt-auth)](https://pepy.tech/project/fastapi-jwt-auth)
12-
13-
---
14-
15-
**Documentation**: <a href="https://IndominusByte.github.io/fastapi-jwt-auth/" target="_blank">https://IndominusByte.github.io/fastapi-jwt-auth/</a>
16-
17-
**Source Code**: <a href="https://github.com/IndominusByte/fastapi-jwt-auth/" target="_blank">https://github.com/IndominusByte/fastapi-jwt-auth/</a>
18-
19-
---
20-
21-
## Features
22-
FastAPI extension that provides JWT Auth support (secure, easy to use and lightweight), if you were familiar with flask-jwt-extended this extension suitable for you because this extension inspired by flask-jwt-extended.
23-
24-
- Access token and refresh token
25-
- Token freshness will only allow fresh tokens to access endpoint
26-
- Token revoking/blacklisting
27-
- Custom token revoking
1+
{!../README.md!}

docs/usage/basic.md

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,7 @@
11
Create a file `basic.py`:
22

33
```python
4-
from fastapi import FastAPI, HTTPException, Depends, Request
5-
from fastapi.responses import JSONResponse
6-
from fastapi_jwt_auth import AuthJWT
7-
from fastapi_jwt_auth.exceptions import AuthJWTException
8-
from pydantic import BaseModel
9-
10-
app = FastAPI()
11-
12-
class User(BaseModel):
13-
username: str
14-
password: str
15-
16-
# in production you can use Settings management
17-
# from pydantic to get secret key from .env
18-
class Settings(BaseModel):
19-
authjwt_secret_key: str = "secret"
20-
21-
# callback to get your configuration
22-
@AuthJWT.load_config
23-
def get_config():
24-
return Settings()
25-
26-
# exception handler for authjwt
27-
# in production, you can tweak performance using orjson response
28-
@app.exception_handler(AuthJWTException)
29-
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
30-
return JSONResponse(
31-
status_code=exc.status_code,
32-
content={"detail": exc.message}
33-
)
34-
35-
# provide a method to create access tokens. The create_access_token()
36-
# function is used to actually generate the token to use authorization
37-
# later in endpoint protected
38-
@app.post('/login')
39-
def login(user: User, Authorize: AuthJWT = Depends()):
40-
if user.username != "test" and user.password != "test":
41-
raise HTTPException(status_code=401,detail="Bad username or password")
42-
43-
# subject identifier for who this token is for example id or username from database
44-
access_token = Authorize.create_access_token(subject=user.username)
45-
return {"access_token": access_token}
46-
47-
# protect endpoint with function jwt_required(), which requires
48-
# a valid access token in the request headers to access.
49-
@app.get('/user')
50-
def user(Authorize: AuthJWT = Depends()):
51-
Authorize.jwt_required()
52-
53-
current_user = Authorize.get_jwt_subject()
54-
return {"user": current_user}
4+
{!../examples/basic.py!}
555
```
566

577
Run the server with:

docs/usage/freshness.md

Lines changed: 1 addition & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -5,89 +5,5 @@ This is useful for allowing the fresh token to do some critical things (such as
55
Here is an example of how you could utilize refresh tokens with the fresh token pattern:
66

77
```python
8-
from fastapi import FastAPI, HTTPException, Depends, Request
9-
from fastapi.responses import JSONResponse
10-
from fastapi_jwt_auth import AuthJWT
11-
from fastapi_jwt_auth.exceptions import AuthJWTException
12-
from pydantic import BaseModel
13-
14-
app = FastAPI()
15-
16-
class User(BaseModel):
17-
username: str
18-
password: str
19-
20-
class Settings(BaseModel):
21-
authjwt_secret_key: str = "secret"
22-
23-
@AuthJWT.load_config
24-
def get_config():
25-
return Settings()
26-
27-
@app.exception_handler(AuthJWTException)
28-
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
29-
return JSONResponse(
30-
status_code=exc.status_code,
31-
content={"detail": exc.message}
32-
)
33-
34-
# Standard login endpoint. Will return a fresh access token and a refresh token
35-
@app.post('/login')
36-
def login(user: User, Authorize: AuthJWT = Depends()):
37-
if user.username != "test" and user.password != "test":
38-
raise HTTPException(status_code=401,detail="Bad username or password")
39-
40-
"""
41-
create_access_token supports an optional 'fresh' argument,
42-
which marks the token as fresh or non-fresh accordingly.
43-
As we just verified their username and password, we are
44-
going to mark the token as fresh here.
45-
"""
46-
access_token = Authorize.create_access_token(subject=user.username,fresh=True)
47-
refresh_token = Authorize.create_refresh_token(subject=user.username)
48-
return {"access_token": access_token, "refresh_token": refresh_token}
49-
50-
@app.post('/refresh')
51-
def refresh(Authorize: AuthJWT = Depends()):
52-
"""
53-
Refresh token endpoint. This will generate a new access token from
54-
the refresh token, but will mark that access token as non-fresh,
55-
as we do not actually verify a password in this endpoint.
56-
"""
57-
Authorize.jwt_refresh_token_required()
58-
59-
current_user = Authorize.get_jwt_subject()
60-
new_access_token = Authorize.create_access_token(subject=current_user,fresh=False)
61-
return {"access_token": new_access_token}
62-
63-
@app.post('/fresh-login')
64-
def fresh_login(user: User, Authorize: AuthJWT = Depends()):
65-
"""
66-
Fresh login endpoint. This is designed to be used if we need to
67-
make a fresh token for a user (by verifying they have the
68-
correct username and password). Unlike the standard login endpoint,
69-
this will only return a new access token, so that we don't keep
70-
generating new refresh tokens, which entirely defeats their point.
71-
"""
72-
if user.username != "test" and user.password != "test":
73-
raise HTTPException(status_code=401,detail="Bad username or password")
74-
75-
new_access_token = Authorize.create_access_token(subject=user.username,fresh=True)
76-
return {"access_token": new_access_token}
77-
78-
# Any valid JWT access token can access this endpoint
79-
@app.get('/protected')
80-
def protected(Authorize: AuthJWT = Depends()):
81-
Authorize.jwt_required()
82-
83-
current_user = Authorize.get_jwt_subject()
84-
return {"user": current_user}
85-
86-
# Only fresh JWT access token can access this endpoint
87-
@app.get('/protected-fresh')
88-
def protected_fresh(Authorize: AuthJWT = Depends()):
89-
Authorize.fresh_jwt_required()
90-
91-
current_user = Authorize.get_jwt_subject()
92-
return {"user": current_user}
8+
{!../examples/freshness.py!}
939
```

docs/usage/optional.md

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,5 @@
11
In some cases you want to use one endpoint for both, protected and unprotected. in this situation you can use function <b>jwt_optional()</b>. this will allow the endpoint to be accessed regardless of if a JWT is sent in the request or not. if a JWT get tampering or expired an error will be returned instead of calling the endpoint.
22

33
```python
4-
from fastapi import FastAPI, HTTPException, Depends, Request
5-
from fastapi.responses import JSONResponse
6-
from fastapi_jwt_auth import AuthJWT
7-
from fastapi_jwt_auth.exceptions import AuthJWTException
8-
from pydantic import BaseModel
9-
10-
app = FastAPI()
11-
12-
class User(BaseModel):
13-
username: str
14-
password: str
15-
16-
class Settings(BaseModel):
17-
authjwt_secret_key: str = "secret"
18-
19-
@AuthJWT.load_config
20-
def get_config():
21-
return Settings()
22-
23-
@app.exception_handler(AuthJWTException)
24-
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
25-
return JSONResponse(
26-
status_code=exc.status_code,
27-
content={"detail": exc.message}
28-
)
29-
30-
@app.post('/login')
31-
def login(user: User, Authorize: AuthJWT = Depends()):
32-
if user.username != "test" and user.password != "test":
33-
raise HTTPException(status_code=401,detail="Bad username or password")
34-
35-
access_token = Authorize.create_access_token(subject=user.username)
36-
return {"access_token": access_token}
37-
38-
@app.get('/partially-protected')
39-
def partially_protected(Authorize: AuthJWT = Depends()):
40-
Authorize.jwt_optional()
41-
42-
# If no jwt is sent in the request, get_jwt_subject() will return None
43-
current_user = Authorize.get_jwt_subject() or "anonymous"
44-
return {"user": current_user}
4+
{!../examples/optional.py!}
455
```

docs/usage/refresh.md

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,5 @@ Utilizing refresh tokens we can help reduce the damage that can be done if an ac
55
Here is an example of using access and refresh tokens:
66

77
```python
8-
from fastapi import FastAPI, HTTPException, Depends, Request
9-
from fastapi.responses import JSONResponse
10-
from fastapi_jwt_auth import AuthJWT
11-
from fastapi_jwt_auth.exceptions import AuthJWTException
12-
from pydantic import BaseModel
13-
14-
app = FastAPI()
15-
16-
class User(BaseModel):
17-
username: str
18-
password: str
19-
20-
class Settings(BaseModel):
21-
authjwt_secret_key: str = "secret"
22-
23-
@AuthJWT.load_config
24-
def get_config():
25-
return Settings()
26-
27-
@app.exception_handler(AuthJWTException)
28-
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
29-
return JSONResponse(
30-
status_code=exc.status_code,
31-
content={"detail": exc.message}
32-
)
33-
34-
@app.post('/login')
35-
def login(user: User, Authorize: AuthJWT = Depends()):
36-
if user.username != "test" and user.password != "test":
37-
raise HTTPException(status_code=401,detail="Bad username or password")
38-
39-
# Use create_access_token() and create_refresh_token() to create our
40-
# access and refresh tokens
41-
access_token = Authorize.create_access_token(subject=user.username)
42-
refresh_token = Authorize.create_refresh_token(subject=user.username)
43-
return {"access_token": access_token, "refresh_token": refresh_token}
44-
45-
@app.post('/refresh')
46-
def refresh(Authorize: AuthJWT = Depends()):
47-
"""
48-
The jwt_refresh_token_required() function insures a valid refresh
49-
token is present in the request before running any code below that function.
50-
we can use the get_jwt_subject() function to get the subject of the refresh
51-
token, and use the create_access_token() function again to make a new access token
52-
"""
53-
Authorize.jwt_refresh_token_required()
54-
55-
current_user = Authorize.get_jwt_subject()
56-
new_access_token = Authorize.create_access_token(subject=current_user)
57-
return {"access_token": new_access_token}
58-
59-
@app.get('/protected')
60-
def protected(Authorize: AuthJWT = Depends()):
61-
Authorize.jwt_required()
62-
63-
current_user = Authorize.get_jwt_subject()
64-
return {"user": current_user}
8+
{!../examples/refresh.py!}
659
```

docs/usage/revoking.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ This will allow you to revoke a specific token so that it can no longer access y
33
Here is a basic example use token revoking:
44

55
```python
6+
{!../examples/denylist.py!}
67
```
78

89
In production, you will likely want to use either a database or in-memory store (such as Redis) to store your tokens. memory stores are great if you are wanting to revoke a token when the users log out and you can define timeout to your token in Redis, after the timeout has expired, the token will automatically be deleted.

examples/basic.py

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,51 @@
1-
from fastapi import FastAPI, Depends, HTTPException
1+
from fastapi import FastAPI, HTTPException, Depends, Request
2+
from fastapi.responses import JSONResponse
23
from fastapi_jwt_auth import AuthJWT
3-
from pydantic import BaseModel, Field
4-
5-
"""
6-
set secret key to environment variable with this command
7-
export AUTHJWT_SECRET_KEY=secretkey, in terminal linux, macOS, Windows Bash
8-
run app with this command uvicorn basic:app --host 0.0.0.0
9-
if you install python-dotenv run this command below
10-
uvicorn basic:app --host 0.0.0.0 --port 5000 --env-file .env
11-
"""
4+
from fastapi_jwt_auth.exceptions import AuthJWTException
5+
from pydantic import BaseModel
126

137
app = FastAPI()
148

159
class User(BaseModel):
16-
username: str = Field(...,min_length=1)
17-
password: str = Field(...,min_length=1)
10+
username: str
11+
password: str
12+
13+
# in production you can use Settings management
14+
# from pydantic to get secret key from .env
15+
class Settings(BaseModel):
16+
authjwt_secret_key: str = "secret"
17+
18+
# callback to get your configuration
19+
@AuthJWT.load_config
20+
def get_config():
21+
return Settings()
22+
23+
# exception handler for authjwt
24+
# in production, you can tweak performance using orjson response
25+
@app.exception_handler(AuthJWTException)
26+
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
27+
return JSONResponse(
28+
status_code=exc.status_code,
29+
content={"detail": exc.message}
30+
)
1831

19-
# Provide a method to create access tokens. The create_access_token()
20-
# function is used to actually generate the token, and you can return
21-
# it to the caller however you choose.
22-
@app.post('/login',status_code=200)
32+
# provide a method to create access tokens. The create_access_token()
33+
# function is used to actually generate the token to use authorization
34+
# later in endpoint protected
35+
@app.post('/login')
2336
def login(user: User, Authorize: AuthJWT = Depends()):
24-
if user.username != 'test' or user.password != 'test':
25-
raise HTTPException(status_code=401,detail='Bad username or password')
37+
if user.username != "test" and user.password != "test":
38+
raise HTTPException(status_code=401,detail="Bad username or password")
2639

27-
# identity must be between string or integer
28-
access_token = Authorize.create_access_token(identity=user.username)
40+
# subject identifier for who this token is for example id or username from database
41+
access_token = Authorize.create_access_token(subject=user.username)
2942
return {"access_token": access_token}
3043

31-
@app.get('/protected',status_code=200)
32-
def protected(Authorize: AuthJWT = Depends()):
33-
# Protect an endpoint with jwt_required, which requires a valid access token
34-
# in the request to access.
44+
# protect endpoint with function jwt_required(), which requires
45+
# a valid access token in the request headers to access.
46+
@app.get('/user')
47+
def user(Authorize: AuthJWT = Depends()):
3548
Authorize.jwt_required()
3649

37-
# Access the identity of the current user with get_jwt_identity
38-
current_user = Authorize.get_jwt_identity()
39-
return {"logged_in_as": current_user}
50+
current_user = Authorize.get_jwt_subject()
51+
return {"user": current_user}

0 commit comments

Comments
 (0)