alibi-plugins 0.8.0

Built-in authentication plugins and API metadata for Alibi
Documentation
use alibi_core::AuthContext;
use alibi_core::AuthError;
use alibi_core::AuthResponse;
use alibi_core::AuthResult;
pub(in crate::oauth::handlers) fn redirect_response(location: &str) -> AuthResponse {
    AuthResponse::new(302)
        .with_header("content-type", "application/json")
        .with_header("Location", location)
}

pub(in crate::oauth::handlers) fn validate_redirect_target(
    target: &str,
    ctx: &AuthContext<impl alibi_core::AuthSchema>,
    error_message: &str,
) -> AuthResult<()> {
    if ctx.config.current_origin_check_disabled() {
        return Ok(());
    }
    if ctx.config.is_redirect_target_trusted(target) {
        Ok(())
    } else {
        Err(AuthError::forbidden(error_message.to_owned()))
    }
}

pub(in crate::oauth::handlers) fn build_redirect_url(
    base_url: &str,
    callback_url: Option<&str>,
    params: &[(&str, &str)],
) -> AuthResult<String> {
    let base = url::Url::parse(base_url)
        .map_err(|error| AuthError::internal(format!("Invalid base URL: {error}")))?;
    let mut url = if let Some(callback_url) = callback_url {
        base.join(callback_url)
            .map_err(|error| AuthError::bad_request(format!("Invalid callbackURL: {error}")))?
    } else {
        base.join("/error")
            .map_err(|error| AuthError::internal(format!("Invalid error URL: {error}")))?
    };
    if !params.is_empty() {
        let mut query_segments = Vec::new();
        if let Some(existing_query) = url.query()
            && !existing_query.is_empty()
        {
            query_segments.push(existing_query.to_owned());
        }
        for (key, value) in params {
            query_segments.push(format!(
                "{}={}",
                urlencoding::encode(key),
                urlencoding::encode(value),
            ));
        }
        let query = query_segments.join("&");
        url.set_query(Some(&query));
    }
    Ok(url.to_string())
}

pub(in crate::oauth::handlers) fn auth_base_url(
    ctx: &AuthContext<impl alibi_core::AuthSchema>,
) -> String {
    format!(
        "{}{}",
        ctx.config.base_url.trim_end_matches('/'),
        ctx.config.base_path
    )
}

pub(in crate::oauth::handlers) fn build_default_error_url(
    ctx: &AuthContext<impl alibi_core::AuthSchema>,
) -> String {
    ctx.config
        .api_error_url
        .as_ref()
        .filter(|value| !value.is_empty())
        .cloned()
        .unwrap_or_else(|| format!("{}/error", auth_base_url(ctx)))
}

pub(in crate::oauth::handlers) fn callback_failure_location(
    ctx: &AuthContext<impl alibi_core::AuthSchema>,
    error: &str,
) -> String {
    build_redirect_url(
        &auth_base_url(ctx),
        Some(&build_default_error_url(ctx)),
        &[("error", error)],
    )
    .unwrap_or_else(|_| {
        format!(
            "{}/error?error={}",
            auth_base_url(ctx),
            urlencoding::encode(error)
        )
    })
}

pub(in crate::oauth) fn callback_failure_redirect(
    ctx: &AuthContext<impl alibi_core::AuthSchema>,
    error: &str,
) -> AuthResponse {
    redirect_response(&callback_failure_location(ctx, error))
}

pub(crate) fn ambiguous_account_sign_in_response(
    ctx: &AuthContext<impl alibi_core::AuthSchema>,
) -> AuthResponse {
    callback_failure_redirect(ctx, "internal_server_error")
}