Skip to content

Commit

Permalink
Merge pull request #14 from sijokun/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
sijokun authored Mar 12, 2024
2 parents 1e4ecbb + 878fad7 commit 7dd6376
Show file tree
Hide file tree
Showing 18 changed files with 211 additions and 155 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## Async fork 0.6.4
* Dependencies are now use >=, so everything should be fine.
* Examples for Swagger (OpenAPI) authorization

## Async fork 0.6.3
* Dependencies are updated to latest, but somebody (Me) done it wrong, would be fixed in 0.6.4

## Async fork 0.6.2
* OpenAPI now shows field for auth token. Thx to @SunnyCapt
```python
from async_fastapi_jwt_auth.auth_jwt import AuthJWT, AuthJWTBearer
from fastapi import Depends

auth_dep = AuthJWTBearer()

@app.get("/protected")
async def protected(Authorize: AuthJWT = Depends(auth_dep)):
await Authorize.jwt_required()
return {"success": True}
```

## Async fork 0.6.1
* Fix CHANGELOG.md, test action

Expand Down
12 changes: 7 additions & 5 deletions examples/additional_claims.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

from async_fastapi_jwt_auth import AuthJWT
from async_fastapi_jwt_auth.exceptions import AuthJWTException
from async_fastapi_jwt_auth.auth_jwt import AuthJWTBearer

app = FastAPI()
auth_dep = AuthJWTBearer()


class User(BaseModel):
Expand All @@ -28,14 +30,14 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException):


@app.post("/login")
async def login(user: User, Authorize: AuthJWT = Depends()):
async def login(user: User, authorize: AuthJWT = Depends(auth_dep)):
if user.username != "test" or user.password != "test":
raise HTTPException(status_code=401, detail="Bad username or password")

# You can be passing custom claim to argument user_claims
# in function create_access_token() or create refresh token()
another_claims = {"foo": ["fiz", "baz"]}
access_token = await Authorize.create_access_token(
access_token = await authorize.create_access_token(
subject=user.username, user_claims=another_claims
)
return {"access_token": access_token}
Expand All @@ -44,8 +46,8 @@ async def login(user: User, Authorize: AuthJWT = Depends()):
# In protected route, get the claims you added to the jwt with the
# get_raw_jwt() method
@app.get("/claims")
async def user(Authorize: AuthJWT = Depends()):
await Authorize.jwt_required()
async def user(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()

foo_claims = (await Authorize.get_raw_jwt())["foo"]
foo_claims = (await authorize.get_raw_jwt())["foo"]
return {"foo": foo_claims}
22 changes: 12 additions & 10 deletions examples/asymmetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from async_fastapi_jwt_auth import AuthJWT
from async_fastapi_jwt_auth.exceptions import AuthJWTException
from async_fastapi_jwt_auth.auth_jwt import AuthJWTBearer

# In the real case, you can put the
# public key and private key in *.pem, *.key then you can read that file
Expand Down Expand Up @@ -34,6 +35,7 @@
"""

app = FastAPI()
auth_dep = AuthJWTBearer()


class User(BaseModel):
Expand All @@ -58,27 +60,27 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException):


@app.post("/login")
async def login(user: User, Authorize: AuthJWT = Depends()):
async def login(user: User, authorize: AuthJWT = Depends(auth_dep)):
if user.username != "test" or user.password != "test":
raise HTTPException(status_code=401, detail="Bad username or password")

access_token = await Authorize.create_access_token(subject=user.username)
refresh_token = await Authorize.create_refresh_token(subject=user.username)
access_token = await authorize.create_access_token(subject=user.username)
refresh_token = await authorize.create_refresh_token(subject=user.username)
return {"access_token": access_token, "refresh_token": refresh_token}


@app.post("/refresh")
async def refresh(Authorize: AuthJWT = Depends()):
await Authorize.jwt_refresh_token_required()
async def refresh(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_refresh_token_required()

current_user = await Authorize.get_jwt_subject()
new_access_token = await Authorize.create_access_token(subject=current_user)
current_user = await authorize.get_jwt_subject()
new_access_token = await authorize.create_access_token(subject=current_user)
return {"access_token": new_access_token}


@app.get("/protected")
async def protected(Authorize: AuthJWT = Depends()):
await Authorize.jwt_required()
async def protected(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()

current_user = await Authorize.get_jwt_subject()
current_user = await authorize.get_jwt_subject()
return {"user": current_user}
12 changes: 7 additions & 5 deletions examples/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

from async_fastapi_jwt_auth import AuthJWT
from async_fastapi_jwt_auth.exceptions import AuthJWTException
from async_fastapi_jwt_auth.auth_jwt import AuthJWTBearer

app = FastAPI()
auth_dep = AuthJWTBearer()


class User(BaseModel):
Expand Down Expand Up @@ -36,22 +38,22 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException):
# function is used to actually generate the token to use authorization
# later in endpoint protected
@app.post("/login")
async def login(user: User, Authorize: AuthJWT = Depends()):
async def login(user: User, authorize: AuthJWT = Depends(auth_dep)):
if user.username != "test" or user.password != "test":
raise HTTPException(status_code=401, detail="Bad username or password")

# subject identifier for whom this token is for example id or username from database
access_token = await Authorize.create_access_token(subject=user.username)
access_token = await authorize.create_access_token(subject=user.username)
return {"access_token": access_token}


# protect endpoint with function jwt_required(), which requires
# a valid access token in the request headers to access.
@app.get("/user")
async def user(Authorize: AuthJWT = Depends()):
await Authorize.jwt_required()
async def user(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()

current_user = await Authorize.get_jwt_subject()
current_user = await authorize.get_jwt_subject()
return {"user": current_user}


Expand Down
34 changes: 18 additions & 16 deletions examples/csrf_protection_cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from async_fastapi_jwt_auth import AuthJWT
from async_fastapi_jwt_auth.exceptions import AuthJWTException
from async_fastapi_jwt_auth.auth_jwt import AuthJWTBearer

"""
By default, the CRSF cookies will be called csrf_access_token and
Expand All @@ -13,6 +14,7 @@
"""

app = FastAPI()
auth_dep = AuthJWTBearer()


class User(BaseModel):
Expand Down Expand Up @@ -43,7 +45,7 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException):


@app.post("/login")
async def login(user: User, Authorize: AuthJWT = Depends()):
async def login(user: User, authorize: AuthJWT = Depends(auth_dep)):
"""
With authjwt_cookie_csrf_protect set to True, set_access_cookies() and
set_refresh_cookies() will now also set the non-httponly CSRF cookies
Expand All @@ -52,42 +54,42 @@ async def login(user: User, Authorize: AuthJWT = Depends()):
raise HTTPException(status_code=401, detail="Bad username or password")

# Create the tokens and passing to set_access_cookies or set_refresh_cookies
access_token = await Authorize.create_access_token(subject=user.username)
refresh_token = await Authorize.create_refresh_token(subject=user.username)
access_token = await authorize.create_access_token(subject=user.username)
refresh_token = await authorize.create_refresh_token(subject=user.username)

# Set the JWT and CSRF double submit cookies in the response
await Authorize.set_access_cookies(access_token)
await Authorize.set_refresh_cookies(refresh_token)
await authorize.set_access_cookies(access_token)
await authorize.set_refresh_cookies(refresh_token)
return {"msg": "Successfully login"}


@app.post("/refresh")
async def refresh(Authorize: AuthJWT = Depends()):
await Authorize.jwt_refresh_token_required()
async def refresh(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_refresh_token_required()

current_user = await Authorize.get_jwt_subject()
new_access_token = await Authorize.create_access_token(subject=current_user)
current_user = await authorize.get_jwt_subject()
new_access_token = await authorize.create_access_token(subject=current_user)
# Set the JWT and CSRF double submit cookies in the response
await Authorize.set_access_cookies(new_access_token)
await authorize.set_access_cookies(new_access_token)
return {"msg": "The token has been refresh"}


@app.delete("/logout")
async def logout(Authorize: AuthJWT = Depends()):
async def logout(authorize: AuthJWT = Depends(auth_dep)):
"""
Because the JWT are stored in an httponly cookie now, we cannot
log the user out by simply deleting the cookie in the frontend.
We need the backend to send us a response to delete the cookies.
"""
await Authorize.jwt_required()
await authorize.jwt_required()

await Authorize.unset_jwt_cookies()
await authorize.unset_jwt_cookies()
return {"msg": "Successfully logout"}


@app.get("/protected")
async def protected(Authorize: AuthJWT = Depends()):
await Authorize.jwt_required()
async def protected(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()

current_user = await Authorize.get_jwt_subject()
current_user = await authorize.get_jwt_subject()
return {"user": current_user}
36 changes: 19 additions & 17 deletions examples/denylist.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

from async_fastapi_jwt_auth import AuthJWT
from async_fastapi_jwt_auth.exceptions import AuthJWTException
from async_fastapi_jwt_auth.auth_jwt import AuthJWTBearer

app = FastAPI()
auth_dep = AuthJWTBearer()


class User(BaseModel):
Expand Down Expand Up @@ -47,50 +49,50 @@ async def check_if_token_in_denylist(decrypted_token):


@app.post("/login")
async def login(user: User, Authorize: AuthJWT = Depends()):
async def login(user: User, authorize: AuthJWT = Depends(auth_dep)):
if user.username != "test" or user.password != "test":
raise HTTPException(status_code=401, detail="Bad username or password")

access_token = await Authorize.create_access_token(subject=user.username)
refresh_token = await Authorize.create_refresh_token(subject=user.username)
access_token = await authorize.create_access_token(subject=user.username)
refresh_token = await authorize.create_refresh_token(subject=user.username)
return {"access_token": access_token, "refresh_token": refresh_token}


# Standard refresh endpoint. Token in denylist will not
# be able to access this endpoint
@app.post("/refresh")
async def refresh(Authorize: AuthJWT = Depends()):
await Authorize.jwt_refresh_token_required()
async def refresh(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_refresh_token_required()

current_user = await Authorize.get_jwt_subject()
new_access_token = await Authorize.create_access_token(subject=current_user)
current_user = await authorize.get_jwt_subject()
new_access_token = await authorize.create_access_token(subject=current_user)
return {"access_token": new_access_token}


# Endpoint for revoking the current users access token
@app.delete("/access-revoke")
async def access_revoke(Authorize: AuthJWT = Depends()):
await Authorize.jwt_required()
async def access_revoke(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()

jti = (await Authorize.get_raw_jwt())["jti"]
jti = (await authorize.get_raw_jwt())["jti"]
denylist.add(jti)
return {"detail": "Access token has been revoke"}


# Endpoint for revoking the current users refresh token
@app.delete("/refresh-revoke")
async def refresh_revoke(Authorize: AuthJWT = Depends()):
await Authorize.jwt_refresh_token_required()
async def refresh_revoke(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_refresh_token_required()

jti = (await Authorize.get_raw_jwt())["jti"]
jti = (await authorize.get_raw_jwt())["jti"]
denylist.add(jti)
return {"detail": "Refresh token has been revoke"}


# A token in denylist will not be able to access this any more
# A token in denylist will not be able to access this anymore
@app.get("/protected")
async def protected(Authorize: AuthJWT = Depends()):
await Authorize.jwt_required()
async def protected(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()

current_user = await Authorize.get_jwt_subject()
current_user = await authorize.get_jwt_subject()
return {"user": current_user}
Loading

0 comments on commit 7dd6376

Please sign in to comment.