junobuild-auth 0.4.2

Authentication toolkit for Juno.
Documentation
use crate::delegation::types::DelegationTargets;
use crate::openid::types::provider::OpenIdDelegationProvider;
use crate::state::get_config;
use crate::strategies::AuthHeapStrategy;
use junobuild_shared::ic::api::id;

// By default, and for security reasons, we restrict delegation to the authentication module
// that created it. Developers can opt out (allow any targets) or define their own
// restrictions in their configuration.
//
// See https://internetcomputer.org/docs/current/references/ic-interface-spec#authentication
//
// ⚠️ Add-on to the documentation:
// > None means no restriction, Some(vec![]) means the delegation only applies to no canister.
//
// We do not support the "no canister" use case, as it would require introducing an enum
// to make the configuration fully comprehensive. Otherwise, on the JS side,
// `delegation.targets === undefined` would be ambiguous - is it the default (id()) or an empty list?
// Moreover, there is unlikely to be a valid use case where a delegation generated by the Satellite
// should target no canister at all.
pub fn build_targets(
    provider: &OpenIdDelegationProvider,
    auth_heap: &impl AuthHeapStrategy,
) -> Option<DelegationTargets> {
    get_config(auth_heap)
        .as_ref()
        .and_then(|config| config.openid.as_ref())
        .and_then(|openid| openid.providers.get(provider))
        .and_then(|provider| provider.delegation.as_ref())
        .map_or(Some(Vec::from([id()])), |delegation| {
            match &delegation.targets {
                None => None,
                Some(targets) => {
                    if targets.is_empty() {
                        Some(vec![id()])
                    } else {
                        Some(targets.clone())
                    }
                }
            }
        })
}

pub fn targets_to_bytes(targets: &Option<DelegationTargets>) -> Option<Vec<Vec<u8>>> {
    targets.as_ref().map(|target| {
        target
            .iter()
            .map(|principal| principal.as_slice().to_vec())
            .collect()
    })
}