Using fastapi_aad_auth

Please see Basic Usage for information on how to configure and setup fastapi_aad_auth.

Customising authentication dependencies

The api_auth_required() method decorator provides controls over the scope, and is using the fastapi dependency injection system. If you want more customisation, you can use:

router = APIRouter()

@router.get('/hello')
async def hello_world(auth_state: AuthenticationState = Depends(auth_provider.auth_backend.requires_auth(allow_session=True))):
    print(auth_state)
    return {'hello': 'world'}

Accessing User Tokens/View

There are two routes that are automatically added to this, the /me and /me/getToken routes. The /me route provides a summary of the current user, and enables them to get a bearer token from Azure AD. The /me/token endpoint provides that same token (for the logged in user) in a JSON object

Warning

To get the token, this is primarily an interactive method, as it requires caching the token through the UI session based login approach, so it can fail intermittently depending on if the user has logged in recently.

This can be disabled by setting the config.routing.user_path to None or ''. #

Customising the User Model

The authentication state user can be processed within the application methods - the Depends part of the api route returns an AuthenticationState object - auth_state in the testapp (see Integration tests).

1@router.get('/hello')
2async def hello_world(auth_state: AuthenticationState = Depends(auth_provider.auth_backend.requires_auth(allow_session=True))):
3    print(auth_state)
4    return {'hello': 'world'}

The associated user is then available at auth_state.user

The Authenticator object takes a user_klass argument:

1class Authenticator(LoggingMixin):
2    """Authenticator class.
3
4    Creates the key components based on the provided configurations.
5    """
6
7    def __init__(self, config: Config = None, add_to_base_routes: bool = True, base_context: Optional[Dict[str, Any]] = None, user_klass: Optional[type] = None):

which defaults to the really basic User class, but any object with the same interface should work, so you can add e.g. database calls etc. to validate/persist/check the user and any other desired behaviours.

You can customise this when initialising the Authenticator object by setting the Config user_klass variable (this can also be done by the associated environment variable, or in the argument, which overrides all other settings):

from fastapi_aad_auth import Authenticator, Config

config = Config()

auth = Authenticator(config, user_klass=MyUserClass)

Customising the UI

The UI templates are rendered using Jinja2 Templates, with a customisation from Jinja2Templates that uses a loader that allows a package resource to be used in place of a file (using {% extends <package>:<resource> %}).

Additionally, the LoginUIConfig has an attribute ui_klass that can be used to customise how the context is built (note that this class should inherit from (or duck-type the public API of) UI)

These jinja templates also are structured (see fastapi_aad_auth.ui docs for the other templates) from a base template that is relatively generic:

<!DOCTYPE html>
<html lang="en">
    <head>
    {% block Head %}
        <title>{{app_name}}</title>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        {% block CSS %}
        <link href="{{static_path}}/css/bootstrap.min.css" rel="stylesheet">
        <link rel="stylesheet" href="{{static_path}}/css/cover.css">
        {% endblock CSS %}
        {% block Favicon %}
        <link rel="icon" type="img/ipng" href="/static/img/favicon.png" />
        {% endblock Favicon %}
        <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1" >
        {% block HeadScripts %}
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        {% endblock HeadScripts %}
    {% endblock Head %}
    </head>
    <body>
    {% block Body %}
        {% block Nav %}
        {% endblock Nav %}
        {% block Content %}
        {% endblock Content %}
        {% block Footer %}
        {% endblock Footer %}
        {% block BodyScripts %}
        {% endblock BodyScripts %}
    {% endblock Body %}
    </body>
</html>

And can easily be extended or customised.

Lastly, there is a context option on the LoginUIConfig which can set additional context variables including the containerClass to change the CSS div class to use.

Token Scopes

fastapi_aad_auth is used for providing authentication and authorisation on an API using Azure Active Directory as an authorisation provider.

This means that scopes are requested against the client_id of the application rather than e.g. MS Graph or similar, if your backend API needs to access Microsoft (or other APIs) you will need to use e.g. an additional msal instance (or provide specific additional scopes through the fastapi_aad_auth.providers.aad.AADSessionAuthenticator.get_access_token(), with app_scopes=False), if those permissions are added on the App Registration.

Alternatively, you can use an on-behalf-of flow (see Azure Docs).

Custom Token Scopes

You may want to request tokens with specific scopes to be parsed, these are currently provided using the token_scopes configuration option on the fastapi_aad_auth._base.provider.ProviderConfig. The scopes of a given token are added to the user class in the authentication state object.

Custom OpenAPI OAuth Flows

The default OAuth2 flow is authorizationCode, however we support all the options in fastapi, and these can be customized using the flow_type option on fastapi_aad_auth._base.provider.ProviderConfig.

Caching Microsoft JWKS

If you are making frequent authentication requests without sessions, then there will be frequent calls to get the Microsoft JWKs. There is an implemented cache using a Time-to-Live cache, which can be set through the ~fastapi_aad_auth.providers.aad.AADConfig jwks_cache_ttl variable (or AAD_JWKS_CACHE_TTL environment variable).