Skip to content

mochi-neko/fars

Repository files navigation

fars

An unofficial Rust client for the Firebase Auth REST API.

Installation

Please install this library by CLI:

$ cargo add fars

or adding dependency to your Cargo.toml:

[dependencies]
fars = "0.2.0"

Features

All features in this crate are as follows:

Supported APIs

Suppoted APIs of the Firebase Auth REST API are as follows:

Note

Unsupported APIs have already been implemented but not tested.

Supported OAuth ID providers

Supported OAuth ID provides are as follows:

  • (Not tested) Apple (apple.com)
  • (Not tested) Apple Game Center (gc.apple.com)
  • Facebook (facebook.com)
  • GitHub (github.com)
  • Google (google.com)
  • (Not tested) Google Play Games (playgames.google.com)
  • (Not tested) Microsoft (microsoft.com)
  • (Not tested) Twitter (twitter.com)
  • (Not tested) Yahoo (yahoo.com)
  • (Not tested) Custom ({custom-provder-id})

API Usages

Provides semantic interfaces based on a session (fars::Session) as following steps.

Important

  • ID token (fars::Session.id_token) has expiration date.
  • API calling through a session automatically refresh an ID token by the refresh token API when the ID token has been expired.
  • All APIs through session cosume session and return new session that has same ID token or refreshed one except for the delete account API.

Therefore you have to update session every time you use APIs through a session by returned new session.

A usage for a siging in user

  1. Create a config (fars::Config) with your Firebase project API key.
  2. Sign in or sign up by supported options (Email & password / OAuth / Anonymous / Stored refresh token) through the config then get the session (fars::Session) for the siging in user.
  3. Use Auth APIs for the siging in user through the session, or use ID token (fars::Session.id_token) for other Firebase APIs.

A sample code to sign up with email / password and to get user data with tokio and anyhow is as follows:

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("user@example.com"),
        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(())
}

A usage for not siging in user

  1. Create a config (fars::Config) with your Firebase project API key.
  2. Use Auth APIs for a not siging in user through the config.

A sample code to send password reset email with tokio and anyhow is as follows:

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(())
}

Sign in with OAuth credentials

Important

This crate does not provide methods to get OAuth credential for each ID provider.

When you use signing in with OAuth credential, please implement a method to get target OAuth credential.

See also supported OAuth providers.

Google OAuth

To sign in with Google OAuth credential,

  1. Create a config (fars::Config) with your Firebase project API key.
  2. Get an access token of a user from Google OAuth API. See reference.
  3. Sign in with specifying request_uri and IdpPostBody.

A sample code to sign in with Google OAuth credential with tokio and anyhow is as follows:

use std::collections::HashMap;
use fars::Config;
use fars::ApiKey;
use fars::OAuthRequestUri;
use fars::IdpPostBody;
use fars::ProviderId

#[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 access token from Google OAuth by any method.
    let google_access_token = "google-access-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::new(
                ProviderId::Google, // Specify IDP
                HashMap::from([(
                    "access_token",
                    google_access_token,
                )]), // Set post body as key-value pairs.
            )?,
        )
        .await?;

    // 4. Do something with the session.

    Ok(())
}

Error handling

If you handle error in this crate, please handle fars::Result and fars::Error.

Note

fars::Error::ApiError has an error code (fars::error::CommonErrorCode) according to common error codes in the API reference. You can specify error type of an API error of Firebase Auth by matching an error code (fars::error::CommonErrorCode).

A sample code to handle error for signing in with email / password with reqwest, tokio and anyhow is as follows:

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())
                },
            }
        },
    }
}

Raw API interfaces

Provides raw supported APIs by fars::api module.

A sample code to sign in with email / password with reqwest, tokio and anyhow is as follows:

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(
        "user@example.com".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(())
}

(Optional) ID token verification

Provides ID token verification of the Firebase Auth via fars::verification module.

Note

ID token verification is an optional feature.

Please activate this feature by CLI:

$ cargo add fars --features verify

or adding features to your Cargo.toml:

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

A sample code to verify ID token with tokio and anyhow is as follows:

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(())
}

(Optional) HTTP client customization

Provides HTTP client customization interface for Firebase Auth APIs.

Note

HTTP client customization is an optional feature.

Please activate this feature by CLI:

$ cargo add fars --features custom_client

or adding features to your Cargo.toml:

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

An example to customize timeout options of HTTP client with tokio and anyhow is as follows:

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(())
}

(Optional) OAuth 2.0 Client

TODO:

Other examples

Please refer /examples directory, a shell script and a study of authentication on Web frontend with dioxus.

Changelog

See CHANGELOG.

License

Licensed under either of the Apache License, Version 2.0 or the MIT license at your option.

About

An unofficial Rust client for the Firebase Auth REST API.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published