#firebase #client #rest #http-client

远航

非官方的 Firebase Auth REST API 的 Rust 客户端

2 个不稳定版本

0.2.0 2024年1月11日
0.1.0 2024年1月6日

#186认证

MIT/Apache

240KB
3K SLoC

远航

非官方的 Firebase Auth REST API 的 Rust 客户端。

安装

请通过 CLI 添加此库

$ cargo add fars

或将依赖项添加到您的 Cargo.toml

[dependencies]
fars = "0.2.0"

功能

本 crate 中的所有功能如下

支持的 API

以下为 Firebase Auth REST API 的支持 API

[!注意] 不支持的 API 已实现但未测试。

支持的 OAuth ID 提供商

以下为支持的 OAuth ID 提供商

  • (未实现) Apple (apple..com)
  • (未实现) Apple Game Center (gc..apple..com)
  • (未测试) Facebook (facebook..com)
  • (未实现) GitHub (github..com)
  • Google (google..com)
  • (未实现) Google Play Games (playgames..google..com)
  • (未实现) LinkedIn (linkedin..com)
  • (未实现) Microsoft (microsoft..com)
  • (未测试) Twitter (twitter.com)
  • (未实现) Yahoo (yahoo.com)

[!NOTE] 不支持的服务提供商可能尚未经过测试,或者 IdpPostBody 的格式在 官方API参考 中未文档化。

API 使用

根据以下步骤提供基于会话(fars::Session)的语义接口。

[!IMPORTANT]

  • ID令牌(fars::Session.id_token)有过期日期。
  • 当ID令牌过期时,通过会话调用API会自动通过刷新令牌API刷新ID令牌。
  • 所有通过会话调用的API都会消耗会话并返回一个新的会话,该会话具有相同的ID令牌或刷新后的ID令牌,除了删除账户API

因此,每次您通过返回的新会话使用会话调用API时,都必须更新会话。

登录用户的用法

  1. 使用您的Firebase项目API密钥创建一个配置(fars::Config)。
  2. 通过配置使用支持的选择(电子邮件和密码 / OAuth / 匿名 / 存储的刷新令牌)进行登录或注册,然后获取登录用户的会话(fars::Session)。
  3. 通过会话使用Auth API对登录用户进行操作,或使用ID令牌(fars::Session.id_token)对其他Firebase API进行操作。

以下是一个使用 电子邮件/密码 注册和用 tokioanyhow 获取用户数据的示例代码

use fars::Config;
use fars::ApiKey;
use fars::Email;
use fars::Password;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Create a config with your Firebase project API key.
    let config = Config::new(
        ApiKey::new("your-firebase-project-api-key"),
    );
    
    // 2. Sign up with email and password then get a session.
    let session = config.sign_up_with_email_password(
        Email::new("[email protected]"),
        Password::new("password"),
    ).await?;

    // 3. Get user data through the session and get a new session.
    let (new_session, user_data) = session.get_user_data().await?;

    // 4. Do something with new_session and user_data.

    Ok(())
}

未登录用户的用法

  1. 使用您的Firebase项目API密钥创建一个配置(fars::Config)。
  2. 通过配置使用Auth API对未登录用户进行操作。

以下是一个使用 发送密码重置电子邮件 的示例代码,使用 tokioanyhow

use fars::Config;
use fars::ApiKey;
use fars::Email;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Create a config with your Firebase project API key.
    let config = Config::new(
        ApiKey::new("your-firebase-project-api-key"),
    );
    
    // 2. Send reset password email to specified email through the config if it has been registered.
    config.send_reset_password_email(
        Email::new("user@example"),
        None, // Option: Locale
    ).await?;

    Ok(())
}

使用OAuth凭据登录

[!IMPORTANT] 此crate不提供获取每个ID提供者的OAuth凭据的方法。

当您使用OAuth凭据进行登录时,请实现一种获取目标OAuth凭据的方法。

请参阅支持的OAuth提供者

Google OAuth

要使用Google OAuth凭据进行登录,

  1. 使用您的Firebase项目API密钥创建一个配置(fars::Config)。
  2. 从Google OAuth API获取OpenID令牌。请参阅参考
  3. 指定 request_uriIdpPostBody::Google 进行登录。

以下是一个使用 Google OAuth凭据登录 的示例代码,使用 tokioanyhow

use fars::Config;
use fars::ApiKey;
use fars::OAuthRequestUri;
use fars::IdpPostBody;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Create a config with your Firebase project API key.
    let config = Config::new(
        ApiKey::new("your-firebase-project-api-key"),
    );

    // 2. Get an OpenID token from Google OAuth by any method.
    let google_id_token = "google-open-id-token".to_string();

    // 3. Get a session by signing in with Google OAuth credential.
    let session = config
        .sign_in_with_oauth_credential(
            OAuthRequestUri::new("https://your-app.com/redirect/path/auth/handler"),
            IdpPostBody::Google {
                id_token: google_id_token,
            },
        )
        .await?;

    // 4. Do something with the session.

    Ok(())
}

错误处理

如果您在此crate中处理错误,请处理 fars::Resultfars::Error

[!注意] fars::Error::ApiError 根据 API 参考文档 中的通用错误代码具有一个错误码(fars::error::CommonErrorCode)。您可以通过匹配错误码(fars::error::CommonErrorCode)来指定 Firebase Auth 的 API 错误类型。

以下是一个使用 reqwesttokioanyhow 处理通过电子邮件/密码 登录 的示例代码:

use fars::Config;
use fars::ApiKey;
use fars::Email;
use fars::Password;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create a config.
    let config = Config::new(
        ApiKey::new("your-firebase-project-api-key"),
    );

    // Create a session by signing in with email and password.
    match config
        .sign_in_with_email_password(
            Email::new("user@example"),
            Password::new("password"),
        )
        .await
    {
        // Success
        | Ok(session) => {
            println!(
                "Succeeded to sign in with email/password: {:?}",
                session
            );
            // Do something with the session.
            Ok(())
        },
        // Failure
        | Err(error) => {
            match error {
                // Handle HTTP request error.
                | fars::Error::HttpRequestError(error) => {
                    // Do something with HTTP request error, e.g. retry.
                    Err(error.into())
                },
                // Handle API error.
                | fars::Error::ApiError {
                    status_code,
                    error_code,
                    response,
                } => {
                    match error_code {
                        | CommonErrorCode::InvalidLoginCredentials => {
                            // Do something with invalid login credentials, e.g. display error message for user: "Invalid email or/and password.".
                            Err(fars::Error::ApiError {
                                status_code,
                                error_code,
                                response,
                            }
                            .into())
                        },
                        | CommonErrorCode::UserDisabled => {
                            // Do something with disabled user, e.g. display error message for user: "This user is disabled by administrator, please use another account.".
                            Err(fars::Error::ApiError {
                                status_code,
                                error_code,
                                response,
                            }
                            .into())
                        },
                        | CommonErrorCode::TooManyAttemptsTryLater => {
                            // Do something with too many attempts, e.g. display error message for user: "Too may requests, please try again later.".
                            Err(fars::Error::ApiError {
                                status_code,
                                error_code,
                                response,
                            }
                            .into())
                        },
                        | _ => {
                            // Do something with other API errors.
                            Err(fars::Error::ApiError {
                                status_code,
                                error_code,
                                response,
                            }
                            .into())
                        },
                    }
                },
                // Handle internal errors
                | _ => {
                    // Do something with internal errors.
                    Err(error.into())
                },
            }
        },
    }
}

原始 API 接口

提供 fars::api 模块支持的原始 API

以下是一个使用 reqwesttokioanyhow 通过电子邮件/密码 登录 的示例代码:

use fars::ApiKey;
use fars::Client;
use fars::api;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Specify your API key.
    let api_key = ApiKey::new("your-firebase-project-api-key");

    // 2. Create a HTTP client.
    let client = Client::new();

    // 3. Create a request payload for the sign in API.
    let request_payload = api::SignInWithEmailPasswordRequestBodyPayload::new(
        "[email protected]".to_string(),
        "password".to_string(),
    );

    // 4. Send a request and receive a response payload of the sign in API.
    let response_payload = api::sign_in_with_email_password(
        &client,
        &api_key,
        request_payload,
    ).await?;

    // 5. Do something with the response payload.

    Ok(())
}

(可选) ID 令牌验证

通过 fars::verification 模块提供 Firebase Auth 的 ID 令牌验证。

[!注意] ID 令牌验证是一个可选功能。

请通过 CLI 激活此功能

$ cargo add fars --features verify

或在您的 Cargo.toml 中添加功能

[dependencies]
fars = { version = "0.2.0", features = ["verify"] }

以下是一个使用 tokioanyhow 验证 ID 令牌 的示例代码:

use fars::VerificationConfig;
use fars::ProjectId;
use fars::IdToken;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create a cofig for verification with your Firebase project ID.
    let cofing = let config = VerificationConfig::new(
        ProjectId::new("firebase-project-id"),
    );

    // Get an ID token of the Firebase Auth by any method.
    let id_token = IdToken::new("id-token");

    // Verrify the ID token.
    match config.verify_id_token(&id_token).await {
        Ok(claims) => {
            // Verification succeeded.
        },
        Err(error) => {
            // Verification failed.
        },
    }

    Ok(())
}

HTTP 客户端自定义

提供 Firebase Auth API 的 HTTP 客户端定制接口。

[!注意] HTTP 客户端定制是一个可选功能。

请通过 CLI 激活此功能

$ cargo add fars --features custom_client

或在您的 Cargo.toml 中添加功能

[dependencies]
fars = { version = "0.2.0", features = ["custom_client"] }

以下是一个使用 tokioanyhow 定制 HTTP 客户端超时选项的示例:

use std::time::Duration;
use fars::Client;
use fars::ApiKey;
use fars::Config;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Create a custom client with re-exported `reqwest` client.
    let client = fars::reqwest::ClientBuilder::new()
        .timeout(Duration::from_secs(60))
        .connect_timeout(Duration::from_secs(10))
        .build()?;

    // 2. Customize HTTP client.
    let client = Client::custom(client);

    // 3. Create a cofig with customized client.
    let config = Config::custom(
        ApiKey::new("your-firebase-project-api-key"),
        client,
    );

    // 4. Do something with a customized config.

    Ok(())
}

其他示例

请参考 /examples 目录、shell 脚本 以及使用 dioxusWeb 前端认证研究

变更日志

CHANGELOG

许可证

根据您的选择,许可协议为 Apache License, Version 2.0MIT 许可证。

依赖项

~3–19MB
~274K SLoC