better-auth-api 1.0.0-alpha.5

Plugin implementations for better-auth
use super::OAuthProvider;
use super::authorization::{AuthorizationRequest, build_authorization_url};
use super::resolved::ResolvedProvider;

#[test]
fn social_authorization_omits_nonce_and_preserves_provider_login_hint_behavior()
-> Result<(), Box<dyn std::error::Error>> {
    for (id, config, forwards_hint) in [
        ("google", OAuthProvider::google("client", "secret"), true),
        ("github", OAuthProvider::github("client", "secret"), true),
        ("gitlab", OAuthProvider::gitlab("client", "secret"), true),
        ("spotify", OAuthProvider::spotify("client", "secret"), false),
        (
            "huggingface",
            OAuthProvider::huggingface("client", "secret"),
            false,
        ),
        ("polar", OAuthProvider::polar("client", "secret"), false),
        ("vercel", OAuthProvider::vercel("client", "secret"), false),
        ("figma", OAuthProvider::figma("client", "secret"), false),
        ("dropbox", OAuthProvider::dropbox("client", "secret"), false),
        ("kick", OAuthProvider::kick("client", "secret"), false),
        (
            "linkedin",
            OAuthProvider::linkedin("client", "secret"),
            true,
        ),
        ("linear", OAuthProvider::linear("client", "secret"), true),
    ] {
        let provider = ResolvedProvider {
            config: config.resolve(),
            generic: None,
        };
        let build = |login_hint, nonce| -> Result<url::Url, Box<dyn std::error::Error>> {
            Ok(url::Url::parse(&build_authorization_url(
                &provider,
                AuthorizationRequest {
                    callback_url: "https://app.example.test/callback/provider",
                    scopes: None,
                    state: "ordinary-state",
                    code_challenge: "ordinary-challenge",
                    login_hint,
                    nonce,
                    additional_params: None,
                },
            )?)?)
        };
        let baseline = build(None, None)?;
        let actual = build(Some("reader@example.test"), Some("ordinary-nonce"))?;
        let mut expected: Vec<_> = baseline.query_pairs().into_owned().collect();
        if forwards_hint {
            expected.push(("login_hint".into(), "reader@example.test".into()));
        }
        expected.sort_unstable();
        let mut actual_query: Vec<_> = actual.query_pairs().into_owned().collect();
        actual_query.sort_unstable();
        assert!(!actual_query.iter().any(|(key, _)| key == "nonce"), "{id}");
        assert_eq!(actual_query, expected, "{id}");
    }
    Ok(())
}