Skip to content

Commit 5297d8d

Browse files
author
IndominusByte
committed
complete basic guide
1 parent 7bffd65 commit 5297d8d

File tree

13 files changed

+126
-222
lines changed

13 files changed

+126
-222
lines changed

README.md

Lines changed: 15 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1,223 +1,35 @@
1-
# fastapi-jwt-auth
1+
<h1 align="left" style="margin-bottom: 20px; font-weight: 500; font-size: 50px; color: black;">
2+
FastAPI JWT Auth
3+
</h1>
24

35
[![Build Status](https://travis-ci.org/IndominusByte/fastapi-jwt-auth.svg?branch=master)](https://travis-ci.org/IndominusByte/fastapi-jwt-auth)
46
[![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)
57
[![PyPI version](https://badge.fury.io/py/fastapi-jwt-auth.svg)](https://badge.fury.io/py/fastapi-jwt-auth)
68
[![Downloads](https://pepy.tech/badge/fastapi-jwt-auth)](https://pepy.tech/project/fastapi-jwt-auth)
79

10+
---
11+
812
## Features
913
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.
14+
1015
- Access token and refresh token
11-
- Token freshness will only allow fresh tokens to access endpoint
12-
- Token revoking/blacklisting
13-
- Custom token revoking
16+
- Token freshness
17+
- Token revoking
18+
- Support for adding custom claims to JSON Web Tokens
19+
- Support RSA encryption
20+
- Storing tokens in cookies and CSRF protection
1421

1522
## Installation
16-
```bash
17-
pip install fastapi-jwt-auth
18-
```
23+
The easiest way to start working with this extension with pip
1924

20-
## Usage
21-
### Setting `AUTHJWT_SECRET_KEY` in environment variable
22-
- For Linux, macOS, Windows Bash
23-
```bash
24-
export AUTHJWT_SECRET_KEY=secretkey
25-
```
26-
- For Windows PowerShell
2725
```bash
28-
$Env:AUTHJWT_SECRET_KEY = "secretkey"
29-
```
30-
### Create it
31-
- Create a file `basic.py` with:
32-
```python
33-
from fastapi import FastAPI, Depends, HTTPException
34-
from fastapi_jwt_auth import AuthJWT
35-
from pydantic import BaseModel, Field
36-
37-
app = FastAPI()
38-
39-
class User(BaseModel):
40-
username: str = Field(...,min_length=1)
41-
password: str = Field(...,min_length=1)
42-
43-
# Provide a method to create access tokens. The create_access_token()
44-
# function is used to actually generate the token, and you can return
45-
# it to the caller however you choose.
46-
@app.post('/login',status_code=200)
47-
def login(user: User, Authorize: AuthJWT = Depends()):
48-
if user.username != 'test' or user.password != 'test':
49-
raise HTTPException(status_code=401,detail='Bad username or password')
50-
51-
# identity must be between string or integer
52-
access_token = Authorize.create_access_token(identity=user.username)
53-
return {"access_token": access_token}
54-
55-
@app.get('/protected',status_code=200)
56-
def protected(Authorize: AuthJWT = Depends()):
57-
# Protect an endpoint with jwt_required, which requires a valid access token
58-
# in the request to access.
59-
Authorize.jwt_required()
60-
61-
# Access the identity of the current user with get_jwt_identity
62-
current_user = Authorize.get_jwt_identity()
63-
return {"logged_in_as": current_user}
64-
26+
pip install fastapi-jwt-auth
6527
```
66-
### Run it
67-
Run the server with:
68-
```console
69-
$ uvicorn basic:app --host 0.0.0.0
7028

71-
INFO: Started server process [4235]
72-
INFO: Waiting for application startup.
73-
INFO: Application startup complete.
74-
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
75-
```
76-
### Access it
77-
To access a jwt_required protected url, all we have to do is send in the JWT with the request. By default, this is done with an authorization header that looks like:
29+
If you want to use asymmetric (public/private) key signing algorithms, include the <b>asymmetric</b> extra requirements.
7830
```bash
79-
Authorization: Bearer <access_token>
80-
```
81-
We can see this in action using CURL:
82-
```console
83-
$ curl http://localhost:8000/protected
84-
85-
{"detail":"Missing Authorization Header"}
86-
87-
$ curl -H "Content-Type: application/json" -X POST \
88-
-d '{"username":"test","password":"test"}' http://localhost:8000/login
89-
90-
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTczMzMxMzMsIm5iZiI6MTU5NzMzMzEzMywianRpIjoiNDczY2ExM2ItOWI1My00NDczLWJjZTctMWZiOWMzNTlmZmI0IiwiZXhwIjoxNTk3MzM0MDMzLCJpZGVudGl0eSI6InRlc3QiLCJ0eXBlIjoiYWNjZXNzIiwiZnJlc2giOmZhbHNlfQ.42CusQo6nsLxOk6bBUP1vnVX-REx4ZYBYYIjYChWf0c"
91-
92-
$ export TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTczMzMxMzMsIm5iZiI6MTU5NzMzMzEzMywianRpIjoiNDczY2ExM2ItOWI1My00NDczLWJjZTctMWZiOWMzNTlmZmI0IiwiZXhwIjoxNTk3MzM0MDMzLCJpZGVudGl0eSI6InRlc3QiLCJ0eXBlIjoiYWNjZXNzIiwiZnJlc2giOmZhbHNlfQ.42CusQo6nsLxOk6bBUP1vnVX-REx4ZYBYYIjYChWf0c
93-
94-
$ curl -H "Authorization: Bearer $TOKEN" http://localhost:8000/protected
95-
96-
{"logged_in_as":"test"}
97-
```
98-
## Extract Token
99-
Access all URL to see what the result
100-
```python
101-
from fastapi import FastAPI, Depends, HTTPException
102-
from fastapi_jwt_auth import AuthJWT
103-
from pydantic import BaseModel, Field
104-
105-
app = FastAPI()
106-
107-
class User(BaseModel):
108-
username: str = Field(...,min_length=1)
109-
password: str = Field(...,min_length=1)
110-
111-
@app.post('/login',status_code=200)
112-
def login(user: User, Authorize: AuthJWT = Depends()):
113-
if user.username != 'test' or user.password != 'test':
114-
raise HTTPException(status_code=401,detail='Bad username or password')
115-
116-
access_token = Authorize.create_access_token(identity=user.username)
117-
return access_token
118-
119-
# Returns the JTI (unique identifier) of an encoded JWT
120-
@app.get('/get-jti',status_code=200)
121-
def get_jti(Authorize: AuthJWT = Depends()):
122-
access_token = Authorize.create_access_token(identity='test')
123-
return Authorize.get_jti(encoded_token=access_token)
124-
125-
# this will return the identity of the JWT that is accessing this endpoint.
126-
# If no JWT is present, `None` is returned instead.
127-
@app.get('/get-jwt-identity',status_code=200)
128-
def get_jwt_identity(Authorize: AuthJWT = Depends()):
129-
Authorize.jwt_optional()
130-
131-
current_user = Authorize.get_jwt_identity()
132-
return {"logged_in_as": current_user}
133-
134-
# this will return the python dictionary which has all
135-
# of the claims of the JWT that is accessing the endpoint.
136-
# If no JWT is currently present, return None instead
137-
@app.get('/get-raw-jwt',status_code=200)
138-
def get_raw_jwt(Authorize: AuthJWT = Depends()):
139-
Authorize.jwt_optional()
140-
141-
token = Authorize.get_raw_jwt()
142-
return {"token": token}
143-
```
144-
145-
## Configuration Options (env)
146-
- `AUTHJWT_ACCESS_TOKEN_EXPIRES`<br/>
147-
How long an access token should live before it expires. If you not define in env variable
148-
default value is `15 minutes`. Or you can custom with value `int` (seconds), example
149-
`AUTHJWT_ACCESS_TOKEN_EXPIRES=300` its mean access token expired in 5 minute
150-
151-
- `AUTHJWT_REFRESH_TOKEN_EXPIRES`<br/>
152-
How long a refresh token should live before it expires. If you not define in env variable
153-
default value is `30 days`. Or you can custom with value `int` (seconds), example
154-
`AUTHJWT_REFRESH_TOKEN_EXPIRES=86400` its mean refresh token expired in 1 day
155-
156-
- `AUTHJWT_BLACKLIST_ENABLED`<br/>
157-
Enable/disable token revoking. Default value is None, for enable blacklist token: `AUTHJWT_BLACKLIST_ENABLED=true`
158-
159-
- `AUTHJWT_SECRET_KEY`<br/>
160-
The secret key needed for symmetric based signing algorithms, such as HS*. If this is not set `raise RuntimeError`.
161-
162-
- `AUTHJWT_ALGORITHM`<br/>
163-
Which algorithms are allowed to decode a JWT. Default value is `HS256`
164-
165-
## Configuration (pydantic or list[tuple])
166-
You can convert and validate type data from dotenv through pydantic (BaseSettings)
167-
```python
168-
from fastapi_jwt_auth import AuthJWT
169-
from pydantic import BaseSettings
170-
from datetime import timedelta
171-
from typing import Literal
172-
173-
# dotenv file parsing requires python-dotenv to be installed
174-
# This can be done with either pip install python-dotenv
175-
class Settings(BaseSettings):
176-
authjwt_access_token_expires: timedelta = timedelta(minutes=15)
177-
authjwt_refresh_token_expires: timedelta = timedelta(days=30)
178-
# literal type only available for python 3.8
179-
authjwt_blacklist_enabled: Literal['true','false']
180-
authjwt_secret_key: str
181-
authjwt_algorithm: str = 'HS256'
182-
183-
class Config:
184-
env_file = '.env'
185-
env_file_encoding = 'utf-8'
186-
187-
188-
@AuthJWT.load_env
189-
def get_settings():
190-
return Settings()
191-
# or you can just parse a list of tuple
192-
# return [
193-
# ("authjwt_access_token_expires",timedelta(minutes=2)),
194-
# ("authjwt_refresh_token_expires",timedelta(days=5)),
195-
# ("authjwt_blacklist_enabled","false"),
196-
# ("authjwt_secret_key","testing"),
197-
# ("authjwt_algorithm","HS256")
198-
# ]
199-
200-
201-
print(AuthJWT._access_token_expires)
202-
print(AuthJWT._refresh_token_expires)
203-
print(AuthJWT._blacklist_enabled)
204-
print(AuthJWT._secret_key)
205-
print(AuthJWT._algorithm)
31+
pip install 'fastapi-jwt-auth[asymmetric]'
20632
```
20733

208-
## Examples
209-
Examples are available on [examples](/examples) folder.
210-
There are:
211-
- [Basic](/examples/basic.py)
212-
- [Token Optional](/examples/optional_protected_endpoints.py)
213-
- [Refresh Token](/examples/refresh_tokens.py)
214-
- [Token Fresh](/examples/token_freshness.py)
215-
- [Blacklist Token](/examples/blacklist.py)
216-
- [Blacklist Token Use Redis](/examples/blacklist_redis.py)
217-
218-
Optional:
219-
- [Use AuthJWT Without Dependency Injection](/examples/without_dependency.py)
220-
- [On Mutiple Files](/examples/multiple_files)
221-
22234
## License
22335
This project is licensed under the terms of the MIT license.

docs/configuration/cookies.md

Whitespace-only changes.

docs/configuration/csrf.md

Whitespace-only changes.

docs/configuration/denylist.md

Whitespace-only changes.

docs/configuration/general.md

Whitespace-only changes.

docs/configuration/headers.md

Whitespace-only changes.

docs/installation.md

Lines changed: 0 additions & 10 deletions
This file was deleted.

docs/usage/freshness.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ This is useful for allowing the fresh token to do some critical things (such as
44

55
Here is an example of how you could utilize refresh tokens with the fresh token pattern:
66

7-
```python
7+
```python hl_lines="39"
88
{!../examples/freshness.py!}
99
```

docs/usage/optional.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +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

3-
```python
3+
```python hl_lines="37-40"
44
{!../examples/optional.py!}
55
```

docs/usage/refresh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ Utilizing refresh tokens we can help reduce the damage that can be done if an ac
44

55
Here is an example of using access and refresh tokens:
66

7-
```python
7+
```python hl_lines="35"
88
{!../examples/refresh.py!}
99
```

0 commit comments

Comments
 (0)