OpenID

Interface

For OpenID automations, it is possible to define a custom function for handling the user logged in event. This function will be called when the user logs in using OpenID.

User Logged In

You can implement your own handle function to handle the “User Logged In” event for OpenID. By default the following function is used:

fair_wizard.automation.openid.handle_openid_user_logged_in(openid_event: OpenIdUserLoggedInEvent) AuthorizedUserResponse | ForbiddenResponse | ErrorResponse[source]

Default handle function for “OpenID User Logged In” event.

Parameters:

openid_event – incoming OpenIdUserLoggedInEvent event

Returns:

resulting UserLoginResponse response

Your handle function must have the same signature, i.e. accept OpenIdUserLoggedInEvent as the argument and return UserLoginResponse.

For example, your function can look like this:

from fair_wizard.automation.openid.model import OpenIdUserLoggedInEvent, UserLoginResponse, ErrorResponse, AuthorizedUserResponse

def handle_openid_user_logged_in(openid_event: OpenIdUserLoggedInEvent) -> UserLoginResponse:
    try:
        email = retrieve_email_from_orcid(openid_event)
    except Exception:
        return ErrorResponse(
            message='Failed to retrieve email from ORCID (cannot log in)',
        )
    return AuthorizedUserResponse(
        first_name=openid_event.id_token.other_claims['given_name'],
        last_name=openid_event.id_token.other_claims['family_name'],
        image_url=None,
        affiliation=None,
        email=email,
        user_group_uuids=[],
    )

Notice that UserLoginResponse is actually just a type alias for union of AuthorizedUserResponse, ErrorResponse, and ForbiddenResponse.

Model

class fair_wizard.automation.openid.model.IdToken(*, iss: str, sub: str, aud: list[str], exp: int, iat: int, nonce: str | None = None, otherClaims: dict = {})[source]

Model for ID token of OpenID

model_computed_fields = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields = {'aud': FieldInfo(annotation=list[str], required=True, alias='aud', alias_priority=2), 'exp': FieldInfo(annotation=int, required=True, alias='exp', alias_priority=2), 'iat': FieldInfo(annotation=int, required=True, alias='iat', alias_priority=2), 'iss': FieldInfo(annotation=str, required=True, alias='iss', alias_priority=2), 'nonce': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, alias='nonce', alias_priority=2), 'other_claims': FieldInfo(annotation=dict, required=False, default={}, alias='otherClaims', alias_priority=2), 'sub': FieldInfo(annotation=str, required=True, alias='sub', alias_priority=2)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class fair_wizard.automation.openid.model.OpenIdUserLoggedInEvent(*, accessToken: str, tokenType: str, idToken: IdToken, idTokenJwt: str, expiresIn: int, refreshToken: str | None = None)[source]

Model for “OpenID User Logged In” event

model_computed_fields = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields = {'access_token': FieldInfo(annotation=str, required=True, alias='accessToken', alias_priority=2), 'expires_in': FieldInfo(annotation=int, required=True, alias='expiresIn', alias_priority=2), 'id_token': FieldInfo(annotation=IdToken, required=True, alias='idToken', alias_priority=2), 'id_token_jwt': FieldInfo(annotation=str, required=True, alias='idTokenJwt', alias_priority=2), 'refresh_token': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, alias='refreshToken', alias_priority=2), 'token_type': FieldInfo(annotation=str, required=True, alias='tokenType', alias_priority=2)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.