def form(
    flow: FlowHandler,
    step_id: str,
    schema: dict,
    defaults: dict = None,
    template: dict = None,
    error: str = None,
):
    """Suppport:
     - overwrite schema defaults from dict (user_input or entry.options)
     - set base error code (translations > config > error > code)
     - set custom error via placeholders ("template": "{error}")
    """
    if defaults:
        for key in schema:
            if key.schema in defaults:
                key.default = vol.default_factory(defaults[key.schema])

    if template and "error" in template:
        error = {"base": "template"}
    elif error:
        error = {"base": error}

    return flow.async_show_form(
        step_id=step_id,
        data_schema=vol.Schema(schema),
        description_placeholders=template,
        errors=error,
    )
    async def async_finish_flow(
        self, flow: data_entry_flow.FlowHandler, result: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Return a user as result of login flow."""
        flow = cast(LoginFlow, flow)

        if result["type"] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
            return result

        # we got final result
        if isinstance(result["data"], models.Credentials):
            result["result"] = result["data"]
            return result

        auth_provider = self.auth_manager.get_auth_provider(*result["handler"])
        if not auth_provider:
            raise KeyError(f"Unknown auth provider {result['handler']}")

        credentials = await auth_provider.async_get_or_create_credentials(
            result["data"]
        )

        if flow.context.get("credential_only"):
            result["result"] = credentials
            return result

        # multi-factor module cannot enabled for new credential
        # which has not linked to a user yet
        if auth_provider.support_mfa and not credentials.is_new:
            user = await self.auth_manager.async_get_user_by_credentials(credentials)
            if user is not None:
                modules = await self.auth_manager.async_get_enabled_mfa(user)

                if modules:
                    flow.credential = credentials
                    flow.user = user
                    flow.available_mfa_modules = modules
                    return await flow.async_step_select_mfa_module()

        result["result"] = credentials
        return result