Client

Client Usage

#test_client.py
from fastapi import FastAPI

from easyauth import get_user
from easyauth.client import EasyAuthClient

server = FastAPI()

server.auth = EasyAuthClient.create(
    server,
    token_server='0.0.0.0',
    token_server_port=8090,
    auth_secret='abcd1234',
    default_permissions={'groups': ['users']}
)

# grants access to users matching default_permissions
@server.auth.get('/default')
async def default():
    return f"I am default"

# grants access to only specified users
@server.auth.get('/', users=['jane'])
async def root():
    return f"I am root"

# grants access to members of 'users' or 'admins' group.
@server.auth.get('/groups', groups=['users', 'admins'])
async def groups(user: get_user()):
    return f"{user} is in groups"

# grants access to all members of 'users' group
# or a groups with role of 'basic' or advanced
@server.auth.get('/roles', roles=['basic', 'advanced'], groups=['users'])
async def roles():
    return f"Roles and Groups"

# grants access to all members of groups with a roles granting 'BASIC_CREATE'
@server.auth.get('/actions', actions=['BASIC_CREATE'])
async def action():
    return f"I am actions"

default_permissions, if unspecified

{'groups': ['administrators']}

APIRouter

FastAPI provides a APIRouter object for defining path prefixes, pre-defined dependencies, see fastapi docs for more details. EasyAuthClient can extend the main FastAPI router using the .create_api_router() method or EasyAuthAPIRouter.create().

EasyAuthAPIRouter Considerations

EasyAuthAPIRouter should be created after an EasyAuthClient or EasyAuthServer is created to ensure that the router are correctly included and visible in OpenAPI schema.

from fastapi import FastAPI, Request, Depends
from fastapi.responses import HTMLResponse
from typing import Optional

from easyauth.client import EasyAuthClient

server = FastAPI(openapi_url="/groups/openapi.json")

server.auth = EasyAuthClient.create(
    server,
    token_server='0.0.0.0',
    token_server_port=8090,
    auth_secret='abcd1234',
    default_permissions={'groups': ['users']}
)

# import sub modules
from .finance import finance
from .hr import hr
from .marketing import marketing
from easyauth.router import EasyAuthAPIRouter

finance_router = EasyAuthAPIRouter.create(prefix='/finance', tags=['finance'])

@finance_router.get('/')
async def finance_root():
    return f"fiance_root"

@finance_router.get('/data')
async def finance_data():
    return f"finance_data"

Tip

EasyAuthAPIRouter.create() and server.auth.create_api_router() are wrappers around FastAPI's APIRouter, accepting and passing the same arguments, but also automatically including the router at startup.

.
├── app
│   ├── __init__.py
│   ├── server.py
│   └── marketing
│   │   ├── __init__.py
│   │   ├── marketing.py
│   └── finance
│   │   ├── __init__.py
│   │   ├── finance.py
│   └── hr
│       ├── __init__.py
│       └── hr.py

Permissions

EasyAuth allows endpoints to be as exclusive or as inclusive as needed. Authorization is granted if user meets at least 1 condition.

@server.auth.get(
    '/roles',
    roles=['basic'],  # OR
    groups=['users'], # OR
    actions=['CREATE_BASIC']
)

Cookies

EasyAuth client endpoints, decorated by the auth router, that serve HTML responses or static webcontent are provided default integrated login endpoints at /login /logout.

Note

Once logged in, the browser will contain a authenticatin cookie that matches the users token

Page Overloads

It is possible to overload the existing login, register, activation, not_found, and forbidden pages using the page specific "overloader". Just like routers, this should be done after an EasyAuthClient is created.

Danger

Consider reviewing what API's are used / required before overloading any existing page. Oauth Login scripts are not loaded into overloaded pages.

Not Found - 404

from easyauth.pages import NotFoundPage

@NotFoundPage.mark()
def custom_not_found_page():
    return "Custom 404 Page"

Tip

NotFoundPage contents is wrapped in an HTMLResponse with a status_code 404.

Forbidden Page - 403

from easyauth.pages import ForbiddenPage

@ForbiddenPage.mark()
def not_allowed_page():
    return "Custom 404 Page"

Login Page & 401

from easyauth.pages import LoginPage

@LoginPage.mark()
def custom_login_page():
    return "Custom Login Page"

Register Page

from easyauth.pages import RegisterPage

@RegisterPage.mark()
def custom_register_page():
    return "Custom Register Page"

Activation Page

from easyauth.pages import ActivationPage

@ActivationPage.mark()
def custom_activation_page():
    return "Custom Login Page"

Path Overloads

The default /login and 401 redirect path can be overloaded by setting the default_login_path on EasyAuthClient.create().

server.auth = EasyAuthClient.create(
    server,
    token_server='0.0.0.0',
    token_server_port=8090,
    auth_secret='abcd1234',
    default_permissions={'groups': ['users']},
    default_login_path='/v1/internal/login'
)