This repository contains python plugins for using the Authup authentication and authorization framework in the python language. The plugins are used to integrate Authup with different python frameworks and libraries.
| Plugin | Extra | Sync | Async |
|---|---|---|---|
| httpx | ✅ | ✅ | |
| requests | [requests] | ✅ | ❌ |
| Plugin | Extra | Sync | Async | Middleware | User |
|---|---|---|---|---|---|
| FastApi | [fastapi] | ✅ | ✅ | ✅ | ✅ |
| ASGI | [asgi] | ❌ | ✅ | ✅ | ✅ |
| Flask | [flask] | ⏳ | ⏳ | ⏳ | ⏳ |
The plugins are available via PyPi.
pip install authup-pyThe plugin for the project's base library httpx needs no extra dependencies. To
use the additional plugins for other libraries, you need to install with the corresponding extra i.e. for requests:
pip install authup-py[requests]All the plugins share the underlying Authup class. The class is initialized with the url of the Authup server and
the credentials you would like to use (username/password or robot_id/secret).
The class provides both sync and async methods for the different authentication and authorization flows.
fromauthupimportAuthupauthup=Authup(
url="https://authup.org",
username="username",
password="password"
)
authup_robot=Authup(
url="https://authup.org",
robot_id="robot",
robot_secret="secret"
)The following plugins all expect the same arguments as the Authup class with the addition of the
app as a first argument for server side libraries (e.g. FastApi, Flask).
For synchronously using the plugin with httpx , you can use the AuthupHttpx class and pass an instance to your
httpx.Client or a basic httpx.Request as the auth parameter:
importhttpxfromauthup.plugins.httpximportAuthupHttpxauthup=AuthupHttpx(
url="https://authup.org",
username="username",
password="password",
)
# Use the authup instance as the auth parameter for the httpx clientclient=httpx.Client(auth=authup)
withclient:
response=client.get("https://authup.org")
print(response.status_code)
# Use the authup instance as the auth parameter for a top level request functionrequest=httpx.get("https://authup.org", auth=authup)It works the same way for the asynchronous httpx client:
importhttpxfromauthup.plugins.httpximportAuthupHttpxAsyncauthup=AuthupHttpxAsync(
url="https://authup.org",
username="username",
password="password",
)
asyncwithhttpx.AsyncClient(auth=authup) asclient:
response=awaitclient.get("https://authup.org")
print(response.status_code)Since requests is a synchronous library, the plugin is also synchronous. You can use the AuthupRequests class and
use it with the requests.Session or the requests.request functions:
Note Requires the
requestsextra to be installed.pip install authup-py[requests]
importrequestsfromauthup.plugins.requestsimportAuthupRequestsauthup=AuthupRequests(
url="https://authup.org",
username="username",
password="password",
)
# Use the authup instance as the auth parameter for the requests sessionwithrequests.Session() assession:
session.auth=authupresponse=session.get("https://authup.org")
print(response.status_code)
# Use the authup instance as the auth parameter for a top level request functionresponse=requests.get("https://authup.org", auth=authup)
print(response.status_code)The AuthupASGIMiddleware class can be used as an ASGI middleware for any ASGI framework (i.e. FastAPI, Starlette).
The middleware will check the incoming requests for a valid token and otherwise return a 401 response. If you pass the
optional user parameter, the middleware will inject the user object into the request scope (r.state.user).
The first argument is the ASGI application and the second argument is the URL of the authup instance.
Note Requires the
asgiextra to be installed.pip install authup-py[asgi]
The following shows a simple example for using the middleware with a FastAPI application but it should work with any ASGI framework.
Note Expects a running authup instance available at the given URL.
fromfastapiimportFastAPIfromauthup.plugins.asgiimportAuthupASGIMiddlewareapp=FastAPI()
authup_url="https://authup.org"# change to your authup instance@app.get("/test")asyncdeftest():
return {"message": "Hello World"}
# register the middleware pass the authup url as argumentapp.add_middleware(AuthupASGIMiddleware, authup_url=authup_url)Now you can access the /test endpoint without a token and will receive a 401 response. When using a valid token, you will receive the expected response.
importhttpxfromauthup.plugins.httpximportAuthupHttpx# no token or invalid token raises 401response=httpx.get("http://localhost:8000/test") # 401print(response.status_code)
# valid token receives the expected responseauthup=AuthupHttpx(
url="https://authup.org",
username="username",
password="password",
)
response=httpx.get("http://localhost:8000/test", auth=authup) # 200print(response.status_code)Set the user parameter to True when adding the middleware to your ASGI application:
fromfastapiimportFastAPI, Requestfromauthup.plugins.asgiimportAuthupASGIMiddlewareapp=FastAPI()
authup_url="https://authup.org"# change to your authup instance@app.get("/test-user")asyncdeftest(request: Request):
return {"user": request.state.user}
# register the middleware pass the authup url as argumentapp.add_middleware(AuthupASGIMiddleware, authup_url=authup_url, user=True)Calling the /test-user endpoint without a token will return a 401 response. When using a valid token, the user object
will be injected into the request scope, and you will receive the expected response containing your user.
The AuthupUser class can be used as a FastAPI dependency.
It will check the incoming requests for a valid token and otherwise return a 401 response. If the token is valid a user object
will be available in the dependency call.
The following shows a simple example for using the dependency with a FastAPI application that will return the user object obtained from the token.
fromfastapiimportFastAPI, Dependsfromauthup.plugins.fastapiimportAuthupUserfromauthupimportUserapp=FastAPI()
user_dependency=AuthupUser(url="http://localhost:3010")
@app.get("/test")asyncdefuser_test(user: User=Depends(user_dependency)):
return {"user": user.dict()}You can also require specific permissions for the user. The following example will only allow users with the
client_add permission and a power level of over 100. Otherwise, a 401 response will be returned.
fromfastapiimportFastAPI, Dependsfromauthup.plugins.fastapiimportAuthupUserfromauthupimportUserfromauthup.permissionsimportPermissionpermissions= [
Permission(name="client_add", inverse=False, power=100),
]
required_permissions=AuthupUser(
url="http://localhost:3010",
permissions=permissions,
)
app=FastAPI()
@app.get("/test")asyncdefuser_test(user: User=Depends(required_permissions)):
return {"user": user.dict()}Requires poetry and pre-commit and python 3.7+.
poetry install --with dev --all-extrasInstall pre-commit hooks
poetry run pre-commit installpoetry run pytest