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).