├── src ├── shared │ ├── mod.rs │ └── jwt_helpers.rs ├── consumer │ ├── attribute.rs │ ├── mod.rs │ ├── idp.rs │ ├── debug.rs │ ├── project.rs │ ├── device_history.rs │ ├── client.rs │ ├── impersonation.rs │ ├── fraud_fingerprint.rs │ ├── fraud_verdict_reasons.rs │ ├── rbac.rs │ ├── passwords_session.rs │ ├── passwords_existing_password.rs │ ├── m2m_clients_secrets.rs │ ├── connected_apps_clients_secrets.rs │ ├── otp.rs │ ├── idp_oauth.rs │ ├── connected_apps.rs │ ├── otp_sms.rs │ ├── otp_whatsapp.rs │ └── fraud_rules.rs ├── b2b │ ├── otp.rs │ ├── idp.rs │ ├── mod.rs │ ├── mfa.rs │ ├── discovery.rs │ ├── organizations_members_connected_apps.rs │ ├── client.rs │ ├── impersonation.rs │ ├── magic_links_email_discovery.rs │ ├── passwords_discovery.rs │ ├── magic_links_discovery.rs │ ├── oauth_discovery.rs │ ├── scim.rs │ ├── otp_email_discovery.rs │ ├── rbac.rs │ ├── idp_oauth.rs │ ├── sso_external.rs │ ├── passwords_session.rs │ └── passwords_discovery_email.rs ├── lib.rs └── client.rs ├── .gitignore ├── CODEOWNERS ├── .github └── workflows │ ├── auto-publish.yml │ └── rust.yaml ├── DEVELOPMENT.md ├── Cargo.toml ├── LICENSE ├── CODE_OF_CONDUCT.md └── README.md /src/shared/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod jwt_helpers; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | .idea 4 | 5 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Stytch code owners file 2 | 3 | # These owners will be the default owners for everything in 4 | # the repo. Unless a later match takes precedence, 5 | # @stytchauth/client-libraries will be requested for 6 | # review when someone opens a pull request. 7 | * @stytchauth/client-libraries 8 | 9 | -------------------------------------------------------------------------------- /src/consumer/attribute.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | 9 | /// Attributes: 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | pub struct Attributes { 12 | /// ip_address: The IP address of the user. 13 | pub ip_address: std::option::Option, 14 | /// user_agent: The user agent of the User. 15 | pub user_agent: std::option::Option, 16 | } 17 | -------------------------------------------------------------------------------- /src/b2b/otp.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::otp_email::Email; 8 | use crate::b2b::otp_sms::Sms; 9 | 10 | pub struct OTPs { 11 | pub sms: Sms, 12 | pub email: Email, 13 | } 14 | 15 | impl OTPs { 16 | pub fn new(http_client: crate::client::Client) -> Self { 17 | Self { 18 | sms: Sms::new(http_client.clone()), 19 | email: Email::new(http_client.clone()), 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Crates.io package 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | name: Publish to Crates.io 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - uses: dtolnay/rust-toolchain@1.82 15 | 16 | - name: Run release-plz 17 | uses: MarcoIeni/release-plz-action@v0.5 18 | with: 19 | command: release 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 23 | -------------------------------------------------------------------------------- /src/consumer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | 3 | pub mod attribute; 4 | pub mod connected_apps; 5 | pub mod connected_apps_clients; 6 | pub mod connected_apps_clients_secrets; 7 | pub mod crypto_wallets; 8 | pub mod debug; 9 | pub mod device_history; 10 | pub mod fraud; 11 | pub mod fraud_fingerprint; 12 | pub mod fraud_rules; 13 | pub mod fraud_verdict_reasons; 14 | pub mod idp; 15 | pub mod idp_oauth; 16 | pub mod impersonation; 17 | pub mod m2m; 18 | pub mod m2m_clients; 19 | pub mod m2m_clients_secrets; 20 | pub mod magic_links; 21 | pub mod magic_links_email; 22 | pub mod oauth; 23 | pub mod otp; 24 | pub mod otp_email; 25 | pub mod otp_sms; 26 | pub mod otp_whatsapp; 27 | pub mod passwords; 28 | pub mod passwords_email; 29 | pub mod passwords_existing_password; 30 | pub mod passwords_session; 31 | pub mod project; 32 | pub mod rbac; 33 | pub mod sessions; 34 | pub mod totps; 35 | pub mod users; 36 | pub mod webauthn; 37 | -------------------------------------------------------------------------------- /src/b2b/idp.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::idp_oauth::OAuth; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// ScopeResult: 11 | #[derive(Serialize, Deserialize, Debug, Clone)] 12 | pub struct ScopeResult { 13 | /// scope: The name of the scope. 14 | pub scope: String, 15 | /// description: A human-readable description of the scope, taken from the RBAC Policy. 16 | pub description: String, 17 | /// is_grantable: Indicates whether the scope can be granted. Users can only grant scopes if they have the 18 | /// required permissions. 19 | pub is_grantable: bool, 20 | } 21 | 22 | pub struct IDP { 23 | pub oauth: OAuth, 24 | } 25 | 26 | impl IDP { 27 | pub fn new(http_client: crate::client::Client) -> Self { 28 | Self { 29 | oauth: OAuth::new(http_client.clone()), 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/consumer/idp.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::idp_oauth::OAuth; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// ScopeResult: 11 | #[derive(Serialize, Deserialize, Debug, Clone)] 12 | pub struct ScopeResult { 13 | /// scope: The name of the scope. 14 | pub scope: String, 15 | /// description: A human-readable description of the scope, taken from the RBAC Policy. 16 | pub description: String, 17 | /// is_grantable: Indicates whether the scope can be granted. Users can only grant scopes if they have the 18 | /// required permissions. 19 | pub is_grantable: bool, 20 | } 21 | 22 | pub struct IDP { 23 | pub oauth: OAuth, 24 | } 25 | 26 | impl IDP { 27 | pub fn new(http_client: crate::client::Client) -> Self { 28 | Self { 29 | oauth: OAuth::new(http_client.clone()), 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | Thanks for contributing to Stytch's Rust library! If you run into trouble, find us in [Slack]. 4 | 5 | ## Issues and Pull Requests 6 | 7 | Please file issues in this repo. We don't have an issue template yet, but for now, say whatever you think is important! 8 | 9 | If you have non-trivial changes you'd like us to incorporate, please open an issue first so we can discuss the changes before starting on a pull request. (It's fine to start with the PR for a typo or simple bug.) If we think the changes align with the direction of the project, we'll either ask you to open the PR or assign someone on the Stytch team to make the changes. 10 | 11 | When you're ready for someone to look at your issue or PR, assign `@stytchauth/client-libraries` (GitHub should do this automatically). If we don't acknowledge it within one business day, please escalate it by tagging `@stytchauth/engineering` in a comment or letting us know in [Slack]. 12 | 13 | [Slack]: https://join.slack.com/t/stytch/shared_invite/zt-nil4wo92-jApJ9Cl32cJbEd9esKkvyg 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/rust.yaml: -------------------------------------------------------------------------------- 1 | name: PR 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [main] 7 | 8 | jobs: 9 | format: 10 | name: Format 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - uses: dtolnay/rust-toolchain@1.91 16 | with: 17 | components: rustfmt 18 | 19 | - run: cargo fmt --all --check 20 | 21 | lint: 22 | name: Lint 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - uses: dtolnay/rust-toolchain@1.91 28 | with: 29 | components: clippy 30 | 31 | - uses: Swatinem/rust-cache@v2 32 | 33 | - uses: actions-rs/clippy-check@v1 34 | with: 35 | token: ${{ secrets.GITHUB_TOKEN }} 36 | 37 | test: 38 | name: Test 39 | runs-on: ubuntu-latest 40 | 41 | steps: 42 | - uses: actions/checkout@v4 43 | 44 | - uses: dtolnay/rust-toolchain@1.91 45 | 46 | - uses: Swatinem/rust-cache@v2 47 | 48 | - run: cargo test --workspace --no-fail-fast 49 | -------------------------------------------------------------------------------- /src/b2b/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | 3 | pub mod discovery; 4 | pub mod discovery_intermediate_sessions; 5 | pub mod discovery_organizations; 6 | pub mod idp; 7 | pub mod idp_oauth; 8 | pub mod impersonation; 9 | pub mod magic_links; 10 | pub mod magic_links_discovery; 11 | pub mod magic_links_email; 12 | pub mod magic_links_email_discovery; 13 | pub mod mfa; 14 | pub mod oauth; 15 | pub mod oauth_discovery; 16 | pub mod organizations; 17 | pub mod organizations_members; 18 | pub mod organizations_members_connected_apps; 19 | pub mod organizations_members_oauth_providers; 20 | pub mod otp; 21 | pub mod otp_email; 22 | pub mod otp_email_discovery; 23 | pub mod otp_sms; 24 | pub mod passwords; 25 | pub mod passwords_discovery; 26 | pub mod passwords_discovery_email; 27 | pub mod passwords_email; 28 | pub mod passwords_existing_password; 29 | pub mod passwords_session; 30 | pub mod rbac; 31 | pub mod recovery_codes; 32 | pub mod scim; 33 | pub mod scim_connection; 34 | pub mod sessions; 35 | pub mod sso; 36 | pub mod sso_external; 37 | pub mod sso_oidc; 38 | pub mod sso_saml; 39 | pub mod totps; 40 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stytch" 3 | version = "9.4.0" 4 | edition = "2021" 5 | license = "MIT" 6 | description = "Stytch Rust client" 7 | documentation = "https://stytch.com/docs" 8 | repository = "https://github.com/stytchauth/stytch-rust" 9 | categories = ["api-bindings", "authentication", "web-programming"] 10 | 11 | [dependencies] 12 | base64 = "0.22.1" 13 | chrono = { version = "0.4.22", default-features = false, features = [ 14 | "serde", 15 | "std", 16 | ] } 17 | http = "1.1.0" 18 | http-serde = "2.1.1" 19 | jsonwebtoken = "9.3.0" 20 | percent-encoding = "2.3.2" 21 | reqwest = { version = "0.12.4", default-features = false, features = ["json"] } 22 | serde = { version = "1.0.139", features = ["derive"] } 23 | serde_json = "1.0.82" 24 | serde_urlencoded = "0.7.1" 25 | thiserror = "1.0.31" 26 | tokio = { version = "1", features = [ 27 | "macros", 28 | "sync", 29 | ], default-features = false } 30 | tracing = "0.1.35" 31 | url = "2.2.2" 32 | 33 | [features] 34 | default = ["reqwest-native-tls"] 35 | reqwest-native-tls = ["reqwest/native-tls"] 36 | reqwest-rustls-tls = ["reqwest/rustls-tls"] 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Stytch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/b2b/mfa.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | 9 | /// MemberOptions: 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | pub struct MemberOptions { 12 | /// mfa_phone_number: The Member's MFA phone number. 13 | pub mfa_phone_number: String, 14 | /// totp_registration_id: The Member's MFA TOTP registration ID. 15 | pub totp_registration_id: String, 16 | } 17 | /// MfaRequired: 18 | #[derive(Serialize, Deserialize, Debug, Clone)] 19 | pub struct MfaRequired { 20 | /// member_options: Information about the Member's options for completing MFA. 21 | pub member_options: std::option::Option, 22 | /// secondary_auth_initiated: If null, indicates that no secondary authentication has been initiated. If 23 | /// equal to "sms_otp", indicates that the Member has a phone number, and a one time passcode has been sent 24 | /// to the Member's phone number. No secondary authentication will be initiated during calls to the 25 | /// discovery authenticate or list organizations endpoints, even if the Member has a phone number. 26 | pub secondary_auth_initiated: std::option::Option, 27 | } 28 | -------------------------------------------------------------------------------- /src/consumer/debug.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | use serde_urlencoded; 9 | 10 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 11 | pub struct WhoamiRequest {} 12 | #[derive(Serialize, Deserialize, Debug, Clone)] 13 | pub struct WhoamiResponse { 14 | pub request_id: String, 15 | pub project_id: String, 16 | pub name: String, 17 | #[serde(with = "http_serde::status_code")] 18 | pub status_code: http::StatusCode, 19 | } 20 | 21 | pub struct Debug { 22 | http_client: crate::client::Client, 23 | } 24 | 25 | impl Debug { 26 | pub fn new(http_client: crate::client::Client) -> Self { 27 | Self { 28 | http_client: http_client.clone(), 29 | } 30 | } 31 | 32 | pub async fn whoami(&self, body: WhoamiRequest) -> crate::Result { 33 | let path = format!( 34 | "/v1/debug/whoami?{}", 35 | serde_urlencoded::to_string(body).unwrap() 36 | ); 37 | self.http_client 38 | .send(crate::Request { 39 | method: http::Method::GET, 40 | path, 41 | body: serde_json::json!({}), 42 | }) 43 | .await 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(thiserror::Error, Debug)] 4 | #[non_exhaustive] 5 | pub enum Error { 6 | #[error("{0:?}")] 7 | Response(ErrorResponse), 8 | 9 | #[error(transparent)] 10 | InvalidHeaderValue(#[from] http::header::InvalidHeaderValue), 11 | 12 | #[error(transparent)] 13 | InvalidUrl(#[from] url::ParseError), 14 | 15 | #[error("Failed to fetch JWKS")] 16 | FetchJwks, 17 | 18 | #[error("{0:?}")] 19 | JwkNotFound(String), 20 | 21 | #[error("Unauthorized")] 22 | Unauthorized, 23 | 24 | #[error(transparent)] 25 | JWTError(#[from] crate::shared::jwt_helpers::JWTError), 26 | 27 | #[error(transparent)] 28 | Other(#[from] Box), 29 | } 30 | 31 | pub type Result = std::result::Result; 32 | 33 | pub struct Request { 34 | pub method: http::Method, 35 | pub path: String, 36 | pub body: Body, 37 | } 38 | 39 | #[derive(Serialize, Deserialize, Debug)] 40 | pub struct ErrorResponse { 41 | #[serde(with = "http_serde::status_code")] 42 | pub status_code: http::StatusCode, 43 | pub request_id: String, 44 | 45 | #[serde(alias = "error_type", alias = "error")] 46 | pub error_type: String, 47 | #[serde(alias = "error_message", alias = "error_description")] 48 | pub error_message: String, 49 | #[serde(alias = "error_url", alias = "error_uri")] 50 | pub error_url: String, 51 | } 52 | 53 | pub mod b2b; 54 | pub mod client; 55 | pub mod consumer; 56 | mod shared; 57 | -------------------------------------------------------------------------------- /src/consumer/project.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | use serde_urlencoded; 9 | 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | pub struct ProjectMetric { 12 | pub metric_type: ProjectMetricMetricType, 13 | pub count: u32, 14 | } 15 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 16 | pub struct MetricsRequest {} 17 | #[derive(Serialize, Deserialize, Debug, Clone)] 18 | pub struct MetricsResponse { 19 | pub request_id: String, 20 | pub project_id: String, 21 | pub metrics: std::vec::Vec, 22 | #[serde(with = "http_serde::status_code")] 23 | pub status_code: http::StatusCode, 24 | } 25 | 26 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 27 | pub enum ProjectMetricMetricType { 28 | #[serde(rename = "UNKNOWN")] 29 | #[default] 30 | UNKNOWN, 31 | #[serde(rename = "USER_COUNT")] 32 | USERCOUNT, 33 | #[serde(rename = "ORGANIZATION_COUNT")] 34 | ORGANIZATIONCOUNT, 35 | #[serde(rename = "MEMBER_COUNT")] 36 | MEMBERCOUNT, 37 | #[serde(rename = "M2M_CLIENT_COUNT")] 38 | M2MCLIENTCOUNT, 39 | } 40 | 41 | pub struct Project { 42 | http_client: crate::client::Client, 43 | } 44 | 45 | impl Project { 46 | pub fn new(http_client: crate::client::Client) -> Self { 47 | Self { 48 | http_client: http_client.clone(), 49 | } 50 | } 51 | 52 | pub async fn metrics(&self, body: MetricsRequest) -> crate::Result { 53 | let path = format!( 54 | "/v1/projects/metrics?{}", 55 | serde_urlencoded::to_string(body).unwrap() 56 | ); 57 | self.http_client 58 | .send(crate::Request { 59 | method: http::Method::GET, 60 | path, 61 | body: serde_json::json!({}), 62 | }) 63 | .await 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/consumer/device_history.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | 9 | /// DeviceAttributeDetails: 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | pub struct DeviceAttributeDetails { 12 | /// is_new: Whether this `ip_geo_country` has been seen before for this user. 13 | pub is_new: bool, 14 | /// first_seen_at: When this `ip_geo_country` was first seen for this user. Values conform to the RFC 3339 15 | /// standard and are expressed in UTC, e.g. `2021-12-29T12:33:09Z`. 16 | pub first_seen_at: std::option::Option>, 17 | /// last_seen_at: When this `ip_geo_country` was last seen for this user. Values conform to the RFC 3339 18 | /// standard and are expressed in UTC, e.g. `2021-12-29T12:33:09Z`. 19 | pub last_seen_at: std::option::Option>, 20 | } 21 | /// DeviceInfo: 22 | #[derive(Serialize, Deserialize, Debug, Clone)] 23 | pub struct DeviceInfo { 24 | /// visitor_id: The `visitor_id` (a unique identifier) of the user's device. See the 25 | /// [Device Fingerprinting documentation](https://stytch.com/docs/fraud/guides/device-fingerprinting/fingerprints) for more details on the `visitor_id`. 26 | pub visitor_id: String, 27 | /// visitor_id_details: Information about the `visitor_id`. 28 | pub visitor_id_details: std::option::Option, 29 | /// ip_address: The IP address of the user's device. 30 | pub ip_address: std::option::Option, 31 | /// ip_address_details: Information about the `ip_address`. 32 | pub ip_address_details: std::option::Option, 33 | /// ip_geo_city: The city where the IP address is located. 34 | pub ip_geo_city: std::option::Option, 35 | /// ip_geo_region: The region where the IP address is located. 36 | pub ip_geo_region: std::option::Option, 37 | /// ip_geo_country: The country code where the IP address is located. 38 | pub ip_geo_country: std::option::Option, 39 | /// ip_geo_country_details: Information about the `ip_geo_country`. 40 | pub ip_geo_country_details: std::option::Option, 41 | } 42 | -------------------------------------------------------------------------------- /src/b2b/discovery.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery_intermediate_sessions::IntermediateSessions; 8 | use crate::b2b::discovery_organizations::Organizations; 9 | use crate::b2b::mfa::MfaRequired; 10 | use crate::b2b::organizations::Member; 11 | use crate::b2b::organizations::Organization; 12 | use crate::b2b::sessions::PrimaryRequired; 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// DiscoveredOrganization: 16 | #[derive(Serialize, Deserialize, Debug, Clone)] 17 | pub struct DiscoveredOrganization { 18 | /// member_authenticated: Indicates whether the Member has all of the factors needed to fully authenticate 19 | /// to this Organization. If false, the Member may need to complete an MFA step or complete a different 20 | /// primary authentication flow. See the `primary_required` and `mfa_required` fields for more details on 21 | /// each. 22 | pub member_authenticated: bool, 23 | /// organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object). 24 | pub organization: std::option::Option, 25 | /// membership: Information about the membership. 26 | pub membership: std::option::Option, 27 | /// primary_required: Information about the primary authentication requirements of the Organization. 28 | pub primary_required: std::option::Option, 29 | /// mfa_required: Information about the MFA requirements of the Organization and the Member's options for 30 | /// fulfilling MFA. 31 | pub mfa_required: std::option::Option, 32 | } 33 | /// Membership: 34 | #[derive(Serialize, Deserialize, Debug, Clone)] 35 | pub struct Membership { 36 | /// type_: Either `active_member`, `pending_member`, `invited_member`, `eligible_to_join_by_email_domain`, 37 | /// or `eligible_to_join_by_oauth_tenant` 38 | #[serde(rename = "type")] 39 | pub type_: String, 40 | /// details: An object containing additional metadata about the membership, if available. 41 | pub details: std::option::Option, 42 | /// member: The [Member object](https://stytch.com/docs/b2b/api/member-object) if one already exists, or 43 | /// null if one does not. 44 | pub member: std::option::Option, 45 | } 46 | 47 | pub struct Discovery { 48 | pub intermediate_sessions: IntermediateSessions, 49 | pub organizations: Organizations, 50 | } 51 | 52 | impl Discovery { 53 | pub fn new(http_client: crate::client::Client) -> Self { 54 | Self { 55 | intermediate_sessions: IntermediateSessions::new(http_client.clone()), 56 | organizations: Organizations::new(http_client.clone()), 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/consumer/client.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::connected_apps::ConnectedApp; 8 | use crate::consumer::crypto_wallets::CryptoWallets; 9 | use crate::consumer::debug::Debug; 10 | use crate::consumer::fraud::Fraud; 11 | use crate::consumer::idp::IDP; 12 | use crate::consumer::impersonation::Impersonation; 13 | use crate::consumer::m2m::M2M; 14 | use crate::consumer::magic_links::MagicLinks; 15 | use crate::consumer::oauth::OAuth; 16 | use crate::consumer::otp::OTPs; 17 | use crate::consumer::passwords::Passwords; 18 | use crate::consumer::project::Project; 19 | use crate::consumer::rbac::RBAC; 20 | use crate::consumer::sessions::Sessions; 21 | use crate::consumer::totps::TOTPs; 22 | use crate::consumer::users::Users; 23 | use crate::consumer::webauthn::WebAuthn; 24 | 25 | pub struct Client { 26 | pub connected_app: ConnectedApp, 27 | pub crypto_wallets: CryptoWallets, 28 | pub debug: Debug, 29 | pub fraud: Fraud, 30 | pub idp: IDP, 31 | pub impersonation: Impersonation, 32 | pub m2m: M2M, 33 | pub magic_links: MagicLinks, 34 | pub oauth: OAuth, 35 | pub otps: OTPs, 36 | pub passwords: Passwords, 37 | pub project: Project, 38 | pub rbac: RBAC, 39 | pub sessions: Sessions, 40 | pub totps: TOTPs, 41 | pub users: Users, 42 | pub webauthn: WebAuthn, 43 | } 44 | 45 | impl Client { 46 | pub fn new(project_id: &str, secret: &str) -> crate::Result { 47 | Ok(Client::new_with_http_client( 48 | crate::client::Client::new(project_id, secret)?, 49 | crate::client::Client::new_fraud(project_id, secret)?, 50 | )) 51 | } 52 | 53 | pub fn new_with_http_client( 54 | http_client: crate::client::Client, 55 | fraud_http_client: crate::client::Client, 56 | ) -> Self { 57 | Client { 58 | connected_app: ConnectedApp::new(http_client.clone()), 59 | crypto_wallets: CryptoWallets::new(http_client.clone()), 60 | debug: Debug::new(http_client.clone()), 61 | fraud: Fraud::new(fraud_http_client.clone()), 62 | idp: IDP::new(http_client.clone()), 63 | impersonation: Impersonation::new(http_client.clone()), 64 | m2m: M2M::new(http_client.clone()), 65 | magic_links: MagicLinks::new(http_client.clone()), 66 | oauth: OAuth::new(http_client.clone()), 67 | otps: OTPs::new(http_client.clone()), 68 | passwords: Passwords::new(http_client.clone()), 69 | project: Project::new(http_client.clone()), 70 | rbac: RBAC::new(http_client.clone()), 71 | sessions: Sessions::new(http_client.clone()), 72 | totps: TOTPs::new(http_client.clone()), 73 | users: Users::new(http_client.clone()), 74 | webauthn: WebAuthn::new(http_client.clone()), 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/consumer/impersonation.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::sessions::Session; 8 | use crate::consumer::users::User; 9 | use serde::{Deserialize, Serialize}; 10 | 11 | /// AuthenticateRequest: Request type for `Impersonation.authenticate`. 12 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 13 | pub struct AuthenticateRequest { 14 | /// impersonation_token: The User Impersonation token to authenticate. Expires in 5 minutes by default. 15 | pub impersonation_token: String, 16 | } 17 | /// AuthenticateResponse: Response type for `Impersonation.authenticate`. 18 | #[derive(Serialize, Deserialize, Debug, Clone)] 19 | pub struct AuthenticateResponse { 20 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 21 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 22 | /// debug an issue. 23 | pub request_id: String, 24 | /// user_id: The unique ID of the affected User. 25 | pub user_id: String, 26 | /// user: The `user` object affected by this API call. See the 27 | /// [Get user endpoint](https://stytch.com/docs/api/get-user) for complete response field details. 28 | pub user: User, 29 | /// session_token: A secret token for a given Stytch Session. 30 | pub session_token: String, 31 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 32 | pub session_jwt: String, 33 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 34 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 35 | /// are server errors. 36 | #[serde(with = "http_serde::status_code")] 37 | pub status_code: http::StatusCode, 38 | /// session: If you initiate a Session, by including `session_duration_minutes` in your authenticate call, 39 | /// you'll receive a full Session object in the response. 40 | /// 41 | /// See [Session object](https://stytch.com/docs/api/session-object) for complete response fields. 42 | /// 43 | pub session: std::option::Option, 44 | } 45 | 46 | pub struct Impersonation { 47 | http_client: crate::client::Client, 48 | } 49 | 50 | impl Impersonation { 51 | pub fn new(http_client: crate::client::Client) -> Self { 52 | Self { 53 | http_client: http_client.clone(), 54 | } 55 | } 56 | 57 | pub async fn authenticate( 58 | &self, 59 | body: AuthenticateRequest, 60 | ) -> crate::Result { 61 | let path = String::from("/v1/impersonation/authenticate"); 62 | self.http_client 63 | .send(crate::Request { 64 | method: http::Method::POST, 65 | path, 66 | body, 67 | }) 68 | .await 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/b2b/organizations_members_connected_apps.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use percent_encoding; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// RevokeRequest: Request type for `ConnectedApps.revoke`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct RevokeRequest { 13 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 14 | /// critical to perform operations on an Organization, so be sure to preserve this value. You may also use 15 | /// the organization_slug or organization_external_id here as a convenience. 16 | pub organization_id: String, 17 | /// member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to 18 | /// perform operations on a Member, so be sure to preserve this value. You may use an external_id here if 19 | /// one is set for the member. 20 | pub member_id: String, 21 | /// connected_app_id: The ID of the Connected App. 22 | pub connected_app_id: String, 23 | } 24 | /// RevokeResponse: Response type for `ConnectedApps.revoke`. 25 | #[derive(Serialize, Deserialize, Debug, Clone)] 26 | pub struct RevokeResponse { 27 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 28 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 29 | /// debug an issue. 30 | pub request_id: String, 31 | #[serde(with = "http_serde::status_code")] 32 | pub status_code: http::StatusCode, 33 | } 34 | 35 | pub struct ConnectedApps { 36 | http_client: crate::client::Client, 37 | } 38 | 39 | impl ConnectedApps { 40 | pub fn new(http_client: crate::client::Client) -> Self { 41 | Self { 42 | http_client: http_client.clone(), 43 | } 44 | } 45 | 46 | pub async fn revoke(&self, body: RevokeRequest) -> crate::Result { 47 | let organization_id = percent_encoding::utf8_percent_encode( 48 | &body.organization_id, 49 | percent_encoding::NON_ALPHANUMERIC, 50 | ) 51 | .to_string(); 52 | let member_id = percent_encoding::utf8_percent_encode( 53 | &body.member_id, 54 | percent_encoding::NON_ALPHANUMERIC, 55 | ) 56 | .to_string(); 57 | let connected_app_id = percent_encoding::utf8_percent_encode( 58 | &body.connected_app_id, 59 | percent_encoding::NON_ALPHANUMERIC, 60 | ) 61 | .to_string(); 62 | let path = format!("/v1/b2b/organizations/{organization_id}/members/{member_id}/connected_apps/{connected_app_id}/revoke"); 63 | self.http_client 64 | .send(crate::Request { 65 | method: http::Method::POST, 66 | path, 67 | body, 68 | }) 69 | .await 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/b2b/client.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery::Discovery; 8 | use crate::b2b::idp::IDP; 9 | use crate::b2b::impersonation::Impersonation; 10 | use crate::b2b::magic_links::MagicLinks; 11 | use crate::b2b::oauth::OAuth; 12 | use crate::b2b::organizations::Organizations; 13 | use crate::b2b::otp::OTPs; 14 | use crate::b2b::passwords::Passwords; 15 | use crate::b2b::rbac::RBAC; 16 | use crate::b2b::recovery_codes::RecoveryCodes; 17 | use crate::b2b::scim::SCIM; 18 | use crate::b2b::sessions::Sessions; 19 | use crate::b2b::sso::SSO; 20 | use crate::b2b::totps::TOTPs; 21 | use crate::consumer::connected_apps::ConnectedApp; 22 | use crate::consumer::debug::Debug; 23 | use crate::consumer::fraud::Fraud; 24 | use crate::consumer::m2m::M2M; 25 | use crate::consumer::project::Project; 26 | 27 | pub struct Client { 28 | pub connected_app: ConnectedApp, 29 | pub debug: Debug, 30 | pub discovery: Discovery, 31 | pub fraud: Fraud, 32 | pub idp: IDP, 33 | pub impersonation: Impersonation, 34 | pub m2m: M2M, 35 | pub magic_links: MagicLinks, 36 | pub oauth: OAuth, 37 | pub otps: OTPs, 38 | pub organizations: Organizations, 39 | pub passwords: Passwords, 40 | pub project: Project, 41 | pub rbac: RBAC, 42 | pub recovery_codes: RecoveryCodes, 43 | pub scim: SCIM, 44 | pub sso: SSO, 45 | pub sessions: Sessions, 46 | pub totps: TOTPs, 47 | } 48 | 49 | impl Client { 50 | pub fn new(project_id: &str, secret: &str) -> crate::Result { 51 | Ok(Client::new_with_http_client( 52 | crate::client::Client::new_b2b(project_id, secret)?, 53 | crate::client::Client::new_fraud(project_id, secret)?, 54 | )) 55 | } 56 | 57 | pub fn new_with_http_client( 58 | http_client: crate::client::Client, 59 | fraud_http_client: crate::client::Client, 60 | ) -> Self { 61 | Client { 62 | connected_app: ConnectedApp::new(http_client.clone()), 63 | debug: Debug::new(http_client.clone()), 64 | discovery: Discovery::new(http_client.clone()), 65 | fraud: Fraud::new(fraud_http_client.clone()), 66 | idp: IDP::new(http_client.clone()), 67 | impersonation: Impersonation::new(http_client.clone()), 68 | m2m: M2M::new(http_client.clone()), 69 | magic_links: MagicLinks::new(http_client.clone()), 70 | oauth: OAuth::new(http_client.clone()), 71 | otps: OTPs::new(http_client.clone()), 72 | organizations: Organizations::new(http_client.clone()), 73 | passwords: Passwords::new(http_client.clone()), 74 | project: Project::new(http_client.clone()), 75 | rbac: RBAC::new(http_client.clone()), 76 | recovery_codes: RecoveryCodes::new(http_client.clone()), 77 | scim: SCIM::new(http_client.clone()), 78 | sso: SSO::new(http_client.clone()), 79 | sessions: Sessions::new(http_client.clone()), 80 | totps: TOTPs::new(http_client.clone()), 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at support@stytch.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [https://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: https://contributor-covenant.org 74 | [version]: https://contributor-covenant.org/version/1/4/ 75 | 76 | -------------------------------------------------------------------------------- /src/shared/jwt_helpers.rs: -------------------------------------------------------------------------------- 1 | use jsonwebtoken::{decode, decode_header, Algorithm, DecodingKey, Validation}; 2 | use serde::{Deserialize, Serialize}; 3 | use serde_json::Value; 4 | use std::collections::HashMap; 5 | use std::time::{SystemTime, UNIX_EPOCH}; 6 | 7 | #[derive(thiserror::Error, Debug)] 8 | #[non_exhaustive] 9 | pub enum JWTError { 10 | #[error("JWT too old")] 11 | TooOld, 12 | 13 | #[error("JWT missing '{0}' field")] 14 | MissingField(String), 15 | 16 | #[error(transparent)] 17 | Decode(#[from] jsonwebtoken::errors::Error), 18 | 19 | #[error("Payload format invalid")] 20 | PayloadFormat, 21 | 22 | #[error(transparent)] 23 | Other(#[from] Box), 24 | } 25 | 26 | #[derive(Debug, Serialize, Deserialize)] 27 | pub struct GenericClaims { 28 | pub reserved_claims: HashMap, 29 | pub untyped_claims: HashMap, 30 | } 31 | 32 | pub async fn authenticate_jwt( 33 | http_client: &crate::client::Client, 34 | jwt: &str, 35 | max_token_age_seconds: Option, 36 | ) -> std::result::Result { 37 | let jwt_audience = http_client.project_id.to_string(); 38 | let jwt_issuer = format!("stytch.com/{}", http_client.project_id); 39 | 40 | let now = SystemTime::now() 41 | .duration_since(UNIX_EPOCH) 42 | .map_err(|e| JWTError::Other(Box::new(e)))? 43 | .as_secs(); 44 | 45 | let kid = decode_header(jwt) 46 | .map_err(|e| JWTError::Other(Box::new(e)))? 47 | .kid 48 | .ok_or(JWTError::MissingField("kid".to_string()))?; 49 | let jwk = http_client 50 | .fetch_jwk(&kid) 51 | .await 52 | .map_err(|e| JWTError::Other(Box::new(e)))?; 53 | let decoding_key = DecodingKey::from_rsa_components(&jwk.n, &jwk.e)?; 54 | 55 | // Validate the JWT 56 | let mut validation = Validation::new(Algorithm::RS256); 57 | validation.set_audience(&[&jwt_audience]); 58 | validation.set_issuer(&[&jwt_issuer]); 59 | 60 | // And decode it 61 | let token_data = decode::(jwt, &decoding_key, &validation)?; 62 | let payload = token_data.claims; 63 | 64 | if let Some(max_age) = max_token_age_seconds { 65 | if let Some(iat) = payload["iat"].as_u64() { 66 | if now - iat >= max_age { 67 | return Err(JWTError::TooOld); 68 | } 69 | } else { 70 | return Err(JWTError::MissingField("iat".to_string())); 71 | } 72 | } 73 | 74 | let reserved_claim_keys = &["aud", "exp", "iat", "iss", "jti", "nbf", "sub"]; 75 | if let Value::Object(map) = &payload { 76 | Ok(GenericClaims { 77 | reserved_claims: map 78 | .iter() 79 | .filter_map(|(k, v)| { 80 | if reserved_claim_keys.contains(&k.as_str()) { 81 | Some((k.clone(), v.clone())) 82 | } else { 83 | None 84 | } 85 | }) 86 | .collect(), 87 | untyped_claims: map 88 | .iter() 89 | .filter_map(|(k, v)| { 90 | if !reserved_claim_keys.contains(&k.as_str()) { 91 | Some((k.clone(), v.clone())) 92 | } else { 93 | None 94 | } 95 | }) 96 | .collect(), 97 | }) 98 | } else { 99 | Err(JWTError::PayloadFormat) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/b2b/impersonation.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::mfa::MfaRequired; 8 | use crate::b2b::organizations::Member; 9 | use crate::b2b::organizations::Organization; 10 | use crate::b2b::sessions::MemberSession; 11 | use serde::{Deserialize, Serialize}; 12 | 13 | /// AuthenticateRequest: Request type for `Impersonation.authenticate`. 14 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 15 | pub struct AuthenticateRequest { 16 | /// impersonation_token: The Member Impersonation token to authenticate. Expires in 5 minutes by default. 17 | pub impersonation_token: String, 18 | } 19 | /// AuthenticateResponse: Response type for `Impersonation.authenticate`. 20 | #[derive(Serialize, Deserialize, Debug, Clone)] 21 | pub struct AuthenticateResponse { 22 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 23 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 24 | /// debug an issue. 25 | pub request_id: String, 26 | /// member_id: Globally unique UUID that identifies a specific Member. 27 | pub member_id: String, 28 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 29 | /// critical to perform operations on an Organization, so be sure to preserve this value. 30 | pub organization_id: String, 31 | /// member: The [Member object](https://stytch.com/docs/b2b/api/member-object) 32 | pub member: Member, 33 | /// session_token: A secret token for a given Stytch Session. 34 | pub session_token: String, 35 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 36 | pub session_jwt: String, 37 | /// organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object). 38 | pub organization: Organization, 39 | /// intermediate_session_token: Successfully authenticating an impersonation token will never result in an 40 | /// intermediate session. If the token is valid, a full session will be created. 41 | pub intermediate_session_token: String, 42 | /// member_authenticated: The member will always be fully authenticated if an impersonation token is 43 | /// successfully authenticated. 44 | pub member_authenticated: bool, 45 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 46 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 47 | /// are server errors. 48 | #[serde(with = "http_serde::status_code")] 49 | pub status_code: http::StatusCode, 50 | /// member_session: The [Session object](https://stytch.com/docs/b2b/api/session-object) for the 51 | /// impersonated Member. 52 | pub member_session: std::option::Option, 53 | /// mfa_required: MFA will not be required when authenticating impersonation tokens. 54 | pub mfa_required: std::option::Option, 55 | } 56 | 57 | pub struct Impersonation { 58 | http_client: crate::client::Client, 59 | } 60 | 61 | impl Impersonation { 62 | pub fn new(http_client: crate::client::Client) -> Self { 63 | Self { 64 | http_client: http_client.clone(), 65 | } 66 | } 67 | 68 | pub async fn authenticate( 69 | &self, 70 | body: AuthenticateRequest, 71 | ) -> crate::Result { 72 | let path = String::from("/v1/b2b/impersonation/authenticate"); 73 | self.http_client 74 | .send(crate::Request { 75 | method: http::Method::POST, 76 | path, 77 | body, 78 | }) 79 | .await 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/b2b/magic_links_email_discovery.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | 9 | /// SendRequest: Request type for `Discovery.send`. 10 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 11 | pub struct SendRequest { 12 | /// email_address: The email address of the Member. 13 | pub email_address: String, 14 | /// discovery_redirect_url: The URL that the end user clicks from the discovery Magic Link. This URL should 15 | /// be an endpoint in the backend server that 16 | /// verifies the request by querying Stytch's discovery authenticate endpoint and continues the flow. If 17 | /// this value is not passed, the default 18 | /// discovery redirect URL that you set in your Dashboard is used. If you have not set a default discovery 19 | /// redirect URL, an error is returned. 20 | pub discovery_redirect_url: std::option::Option, 21 | /// pkce_code_challenge: A base64url encoded SHA256 hash of a one time secret used to validate that the 22 | /// request starts and ends on the same device. 23 | pub pkce_code_challenge: std::option::Option, 24 | /// login_template_id: Use a custom template for discovery emails. By default, it will use your default 25 | /// email template. The template must be from Stytch's 26 | /// built-in customizations or a custom HTML email for Magic Links - Login. 27 | pub login_template_id: std::option::Option, 28 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 29 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 30 | /// 31 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 32 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 33 | /// 34 | /// Request support for additional languages 35 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 36 | /// 37 | pub locale: std::option::Option, 38 | /// discovery_expiration_minutes: The expiration time, in minutes, for an discovery magic link email. If not 39 | /// accepted within this time frame, the email will need to be resent. Defaults to 60 (1 hour) with a 40 | /// minimum of 5 and a maximum of 10080 (1 week). 41 | pub discovery_expiration_minutes: std::option::Option, 42 | } 43 | /// SendResponse: Response type for `Discovery.send`. 44 | #[derive(Serialize, Deserialize, Debug, Clone)] 45 | pub struct SendResponse { 46 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 47 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 48 | /// debug an issue. 49 | pub request_id: String, 50 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 51 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 52 | /// are server errors. 53 | #[serde(with = "http_serde::status_code")] 54 | pub status_code: http::StatusCode, 55 | } 56 | 57 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 58 | pub enum SendRequestLocale { 59 | #[serde(rename = "en")] 60 | #[default] 61 | En, 62 | #[serde(rename = "es")] 63 | Es, 64 | #[serde(rename = "ptbr")] 65 | Ptbr, 66 | #[serde(rename = "fr")] 67 | Fr, 68 | } 69 | 70 | pub struct Discovery { 71 | http_client: crate::client::Client, 72 | } 73 | 74 | impl Discovery { 75 | pub fn new(http_client: crate::client::Client) -> Self { 76 | Self { 77 | http_client: http_client.clone(), 78 | } 79 | } 80 | 81 | pub async fn send(&self, body: SendRequest) -> crate::Result { 82 | let path = String::from("/v1/b2b/magic_links/email/discovery/send"); 83 | self.http_client 84 | .send(crate::Request { 85 | method: http::Method::POST, 86 | path, 87 | body, 88 | }) 89 | .await 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/consumer/fraud_fingerprint.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::fraud::Fingerprints; 8 | use crate::consumer::fraud::Metadata; 9 | use crate::consumer::fraud::Properties; 10 | use crate::consumer::fraud::Verdict; 11 | use serde::{Deserialize, Serialize}; 12 | 13 | /// LookupRequest: Request type for `Fingerprint.lookup`. 14 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 15 | pub struct LookupRequest { 16 | /// telemetry_id: The telemetry ID associated with the fingerprint getting looked up. 17 | pub telemetry_id: String, 18 | /// external_metadata: External identifiers that you wish to associate with the given telemetry ID. You will 19 | /// be able to search for fingerprint results by these identifiers in the DFP analytics dashboard. External 20 | /// metadata fields may not exceed 65 characters. They may only contain alphanumerics and the characters `_` 21 | /// `-` `+` `.` or `@`. 22 | pub external_metadata: std::option::Option, 23 | } 24 | /// LookupResponse: Response type for `Fingerprint.lookup`. 25 | #[derive(Serialize, Deserialize, Debug, Clone)] 26 | pub struct LookupResponse { 27 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 28 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 29 | /// debug an issue. 30 | pub request_id: String, 31 | /// telemetry_id: The telemetry ID associated with the fingerprint getting looked up. 32 | pub telemetry_id: String, 33 | /// fingerprints: A Stytch fingerprint consists of the following identifiers: 34 | pub fingerprints: Fingerprints, 35 | /// verdict: The metadata associated with each fingerprint 36 | pub verdict: Verdict, 37 | /// external_metadata: External identifiers that you wish to associate with the given telemetry ID. You will 38 | /// be able to search for fingerprint results by these identifiers in the DFP analytics dashboard. External 39 | /// metadata fields may not exceed 65 characters. They may only contain alphanumerics and the characters `_` 40 | /// `-` `+` `.` or `@`. 41 | pub external_metadata: Metadata, 42 | /// created_at: The time when the fingerprint was taken. Values conform to the RFC 3339 standard and are 43 | /// expressed in UTC, e.g. `2021-12-29T12:33:09Z`. 44 | pub created_at: chrono::DateTime, 45 | /// expires_at: The timestamp when the fingerprint expires. Values conform to the RFC 3339 standard and are 46 | /// expressed in UTC, e.g. `2021-12-29T12:33:09Z`. 47 | pub expires_at: chrono::DateTime, 48 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 49 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 50 | /// are server errors. 51 | #[serde(with = "http_serde::status_code")] 52 | pub status_code: http::StatusCode, 53 | /// properties: Additional information about the user's browser and network. 54 | pub properties: std::option::Option, 55 | /// raw_signals: The raw device attributes, such as screen size, that were collected by the Device 56 | /// Fingerprinting product to generate the fingerprints and verdict. You must be specifically enabled for 57 | /// the raw signals feature to see this field. You can find documentation for the specific fields in the 58 | /// [guides](https://stytch.com/docs/fraud/guides/device-fingerprinting/reference/raw-signals). 59 | pub raw_signals: std::option::Option, 60 | } 61 | 62 | pub struct Fingerprint { 63 | http_client: crate::client::Client, 64 | } 65 | 66 | impl Fingerprint { 67 | pub fn new(http_client: crate::client::Client) -> Self { 68 | Self { 69 | http_client: http_client.clone(), 70 | } 71 | } 72 | 73 | pub async fn lookup(&self, body: LookupRequest) -> crate::Result { 74 | let path = String::from("/v1/fingerprint/lookup"); 75 | self.http_client 76 | .send(crate::Request { 77 | method: http::Method::POST, 78 | path, 79 | body, 80 | }) 81 | .await 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/b2b/passwords_discovery.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery::DiscoveredOrganization; 8 | use crate::b2b::passwords_discovery_email::Email; 9 | use serde::{Deserialize, Serialize}; 10 | 11 | /// AuthenticateRequest: Request type for `Discovery.authenticate`. 12 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 13 | pub struct AuthenticateRequest { 14 | /// email_address: The email address of the Member. 15 | pub email_address: String, 16 | /// password: The password to authenticate, reset, or set for the first time. Any UTF8 character is allowed, 17 | /// e.g. spaces, emojis, non-English characters, etc. 18 | pub password: String, 19 | } 20 | /// AuthenticateResponse: Response type for `Discovery.authenticate`. 21 | #[derive(Serialize, Deserialize, Debug, Clone)] 22 | pub struct AuthenticateResponse { 23 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 24 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 25 | /// debug an issue. 26 | pub request_id: String, 27 | /// email_address: The email address. 28 | pub email_address: String, 29 | /// intermediate_session_token: The returned Intermediate Session Token contains a password factor 30 | /// associated with the Member. If this value is non-empty, the member must complete an MFA step to finish 31 | /// logging in to the Organization. The token can be used with the 32 | /// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms), 33 | /// [TOTP Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-totp), or 34 | /// [Recovery Codes Recover endpoint](https://stytch.com/docs/b2b/api/recovery-codes-recover) to complete an 35 | /// MFA flow and log in to the Organization. The token has a default expiry of 10 minutes. Password factors 36 | /// are not transferable between Organizations, so the intermediate session token is not valid for use with 37 | /// discovery endpoints. 38 | pub intermediate_session_token: String, 39 | /// discovered_organizations: An array of `discovered_organization` objects tied to the 40 | /// `intermediate_session_token`, `session_token`, or `session_jwt`. See the 41 | /// [Discovered Organization Object](https://stytch.com/docs/b2b/api/discovered-organization-object) for 42 | /// complete details. 43 | /// 44 | /// Note that Organizations will only appear here under any of the following conditions: 45 | /// 1. The end user is already a Member of the Organization. 46 | /// 2. The end user is invited to the Organization. 47 | /// 3. The end user can join the Organization because: 48 | /// 49 | /// a) The Organization allows JIT provisioning. 50 | /// 51 | /// b) The Organizations' allowed domains list contains the Member's email domain. 52 | /// 53 | /// c) The Organization has at least one other Member with a verified email address with the same domain 54 | /// as the end user (to prevent phishing attacks). 55 | pub discovered_organizations: std::vec::Vec, 56 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 57 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 58 | /// are server errors. 59 | #[serde(with = "http_serde::status_code")] 60 | pub status_code: http::StatusCode, 61 | } 62 | 63 | pub struct Discovery { 64 | http_client: crate::client::Client, 65 | pub email: Email, 66 | } 67 | 68 | impl Discovery { 69 | pub fn new(http_client: crate::client::Client) -> Self { 70 | Self { 71 | http_client: http_client.clone(), 72 | email: Email::new(http_client.clone()), 73 | } 74 | } 75 | 76 | pub async fn authenticate( 77 | &self, 78 | body: AuthenticateRequest, 79 | ) -> crate::Result { 80 | let path = String::from("/v1/b2b/passwords/discovery/authenticate"); 81 | self.http_client 82 | .send(crate::Request { 83 | method: http::Method::POST, 84 | path, 85 | body, 86 | }) 87 | .await 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/b2b/magic_links_discovery.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery::DiscoveredOrganization; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// AuthenticateRequest: Request type for `Discovery.authenticate`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct AuthenticateRequest { 13 | /// discovery_magic_links_token: The Discovery Email Magic Link token to authenticate. 14 | pub discovery_magic_links_token: String, 15 | /// pkce_code_verifier: A base64url encoded one time secret used to validate that the request starts and 16 | /// ends on the same device. 17 | pub pkce_code_verifier: std::option::Option, 18 | } 19 | /// AuthenticateResponse: Response type for `Discovery.authenticate`. 20 | #[derive(Serialize, Deserialize, Debug, Clone)] 21 | pub struct AuthenticateResponse { 22 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 23 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 24 | /// debug an issue. 25 | pub request_id: String, 26 | /// intermediate_session_token: The Intermediate Session Token. This token does not necessarily belong to a 27 | /// specific instance of a Member, but represents a bag of factors that may be converted to a member 28 | /// session. The token can be used with the 29 | /// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms), 30 | /// [TOTP Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-totp), or 31 | /// [Recovery Codes Recover endpoint](https://stytch.com/docs/b2b/api/recovery-codes-recover) to complete an 32 | /// MFA flow and log in to the Organization. The token has a default expiry of 10 minutes. It can also be 33 | /// used with the 34 | /// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session) 35 | /// to join a specific Organization that allows the factors represented by the intermediate session token; 36 | /// or the 37 | /// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member. Intermediate Session Tokens have a default expiry of 10 minutes. 38 | pub intermediate_session_token: String, 39 | /// email_address: The email address. 40 | pub email_address: String, 41 | /// discovered_organizations: An array of `discovered_organization` objects tied to the 42 | /// `intermediate_session_token`, `session_token`, or `session_jwt`. See the 43 | /// [Discovered Organization Object](https://stytch.com/docs/b2b/api/discovered-organization-object) for 44 | /// complete details. 45 | /// 46 | /// Note that Organizations will only appear here under any of the following conditions: 47 | /// 1. The end user is already a Member of the Organization. 48 | /// 2. The end user is invited to the Organization. 49 | /// 3. The end user can join the Organization because: 50 | /// 51 | /// a) The Organization allows JIT provisioning. 52 | /// 53 | /// b) The Organizations' allowed domains list contains the Member's email domain. 54 | /// 55 | /// c) The Organization has at least one other Member with a verified email address with the same domain 56 | /// as the end user (to prevent phishing attacks). 57 | pub discovered_organizations: std::vec::Vec, 58 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 59 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 60 | /// are server errors. 61 | #[serde(with = "http_serde::status_code")] 62 | pub status_code: http::StatusCode, 63 | } 64 | 65 | pub struct Discovery { 66 | http_client: crate::client::Client, 67 | } 68 | 69 | impl Discovery { 70 | pub fn new(http_client: crate::client::Client) -> Self { 71 | Self { 72 | http_client: http_client.clone(), 73 | } 74 | } 75 | 76 | pub async fn authenticate( 77 | &self, 78 | body: AuthenticateRequest, 79 | ) -> crate::Result { 80 | let path = String::from("/v1/b2b/magic_links/discovery/authenticate"); 81 | self.http_client 82 | .send(crate::Request { 83 | method: http::Method::POST, 84 | path, 85 | body, 86 | }) 87 | .await 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/consumer/fraud_verdict_reasons.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::fraud::VerdictReasonAction; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// ListRequest: Request type for `VerdictReasons.list`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct ListRequest { 13 | /// overrides_only: Whether to return only verdict reasons that have overrides set. Defaults to false. 14 | pub overrides_only: std::option::Option, 15 | } 16 | /// ListResponse: Response type for `VerdictReasons.list`. 17 | #[derive(Serialize, Deserialize, Debug, Clone)] 18 | pub struct ListResponse { 19 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 20 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 21 | /// debug an issue. 22 | pub request_id: String, 23 | /// verdict_reason_actions: Information about verdict reasons and any overrides that were set on them. 24 | pub verdict_reason_actions: std::vec::Vec, 25 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 26 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 27 | /// are server errors. 28 | #[serde(with = "http_serde::status_code")] 29 | pub status_code: http::StatusCode, 30 | } 31 | /// OverrideRequest: Request type for `VerdictReasons.override`. 32 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 33 | pub struct OverrideRequest { 34 | /// verdict_reason: The verdict reason that you wish to override. For a list of possible reasons to 35 | /// override, see 36 | /// [Warning Flags (Verdict Reasons)](https://stytch.com/docs/docs/fraud/guides/device-fingerprinting/reference/warning-flags-verdict-reasons). You may not override the `RULE_MATCH` reason. 37 | pub verdict_reason: String, 38 | /// override_action: The action that you want to be returned for the specified verdict reason. The override 39 | /// action must be one of `ALLOW`, `BLOCK`, or `CHALLENGE`. 40 | pub override_action: OverrideRequestAction, 41 | /// override_description: An optional description for the verdict reason override. 42 | pub override_description: std::option::Option, 43 | } 44 | /// OverrideResponse: Response type for `VerdictReasons.override`. 45 | #[derive(Serialize, Deserialize, Debug, Clone)] 46 | pub struct OverrideResponse { 47 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 48 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 49 | /// debug an issue. 50 | pub request_id: String, 51 | /// verdict_reason_action: Information about the verdict reason override that was just set. 52 | pub verdict_reason_action: VerdictReasonAction, 53 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 54 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 55 | /// are server errors. 56 | #[serde(with = "http_serde::status_code")] 57 | pub status_code: http::StatusCode, 58 | } 59 | 60 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 61 | pub enum OverrideRequestAction { 62 | #[serde(rename = "ALLOW")] 63 | #[default] 64 | ALLOW, 65 | #[serde(rename = "CHALLENGE")] 66 | CHALLENGE, 67 | #[serde(rename = "BLOCK")] 68 | BLOCK, 69 | #[serde(rename = "NONE")] 70 | NONE, 71 | } 72 | 73 | pub struct VerdictReasons { 74 | http_client: crate::client::Client, 75 | } 76 | 77 | impl VerdictReasons { 78 | pub fn new(http_client: crate::client::Client) -> Self { 79 | Self { 80 | http_client: http_client.clone(), 81 | } 82 | } 83 | 84 | pub async fn r#override(&self, body: OverrideRequest) -> crate::Result { 85 | let path = String::from("/v1/verdict_reasons/override"); 86 | self.http_client 87 | .send(crate::Request { 88 | method: http::Method::POST, 89 | path, 90 | body, 91 | }) 92 | .await 93 | } 94 | pub async fn list(&self, body: ListRequest) -> crate::Result { 95 | let path = String::from("/v1/verdict_reasons/list"); 96 | self.http_client 97 | .send(crate::Request { 98 | method: http::Method::POST, 99 | path, 100 | body, 101 | }) 102 | .await 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/consumer/rbac.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | use serde_urlencoded; 9 | 10 | /// Policy: 11 | #[derive(Serialize, Deserialize, Debug, Clone)] 12 | pub struct Policy { 13 | /// roles: An array of [Role objects](https://stytch.com/docs/api/rbac-role-object). 14 | pub roles: std::vec::Vec, 15 | /// resources: An array of [Resource objects](https://stytch.com/docs/api/rbac-resource-object). 16 | pub resources: std::vec::Vec, 17 | pub scopes: std::vec::Vec, 18 | } 19 | /// PolicyResource: 20 | #[derive(Serialize, Deserialize, Debug, Clone)] 21 | pub struct PolicyResource { 22 | /// resource_id: A unique identifier of the RBAC Resource, provided by the developer and intended to be 23 | /// human-readable. 24 | /// 25 | /// A `resource_id` is not allowed to start with `stytch`, which is a special prefix used for Stytch 26 | /// default Resources with reserved `resource_id`s. 27 | /// 28 | pub resource_id: String, 29 | /// description: The description of the RBAC Resource. 30 | pub description: String, 31 | /// actions: A list of all possible actions for a provided Resource. 32 | pub actions: std::vec::Vec, 33 | } 34 | /// PolicyRole: 35 | #[derive(Serialize, Deserialize, Debug, Clone)] 36 | pub struct PolicyRole { 37 | /// role_id: The unique identifier of the RBAC Role, provided by the developer and intended to be 38 | /// human-readable. 39 | /// 40 | /// The `stytch_user` `role_id` is predefined by Stytch. 41 | /// Check out the [RBAC guide](https://stytch.com/docs/guides/rbac/overview) for a more detailed 42 | /// explanation. 43 | /// 44 | pub role_id: String, 45 | /// description: The description of the RBAC Role. 46 | pub description: String, 47 | /// permissions: A list of permissions that link a 48 | /// [Resource](https://stytch.com/docs/api/rbac-resource-object) to a list of actions. 49 | pub permissions: std::vec::Vec, 50 | } 51 | /// PolicyRolePermission: 52 | #[derive(Serialize, Deserialize, Debug, Clone)] 53 | pub struct PolicyRolePermission { 54 | /// resource_id: A unique identifier of the RBAC Resource, provided by the developer and intended to be 55 | /// human-readable. 56 | /// 57 | /// A `resource_id` is not allowed to start with `stytch`, which is a special prefix used for Stytch 58 | /// default Resources with reserved `resource_id`s. 59 | /// 60 | pub resource_id: String, 61 | /// actions: A list of permitted actions the Role is authorized to take with the provided Resource. You can 62 | /// use `*` as a wildcard to grant a Role permission to use all possible actions related to the Resource. 63 | pub actions: std::vec::Vec, 64 | } 65 | #[derive(Serialize, Deserialize, Debug, Clone)] 66 | pub struct PolicyScope { 67 | pub scope: String, 68 | pub description: String, 69 | pub permissions: std::vec::Vec, 70 | } 71 | #[derive(Serialize, Deserialize, Debug, Clone)] 72 | pub struct PolicyScopePermission { 73 | pub resource_id: String, 74 | pub actions: std::vec::Vec, 75 | } 76 | /// PolicyRequest: Request type for `RBAC.policy`. 77 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 78 | pub struct PolicyRequest {} 79 | /// PolicyResponse: Response type for `RBAC.policy`. 80 | #[derive(Serialize, Deserialize, Debug, Clone)] 81 | pub struct PolicyResponse { 82 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 83 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 84 | /// debug an issue. 85 | pub request_id: String, 86 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 87 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 88 | /// are server errors. 89 | #[serde(with = "http_serde::status_code")] 90 | pub status_code: http::StatusCode, 91 | /// policy: The RBAC Policy document that contains all defined Roles and Resources – which are managed in 92 | /// the [Dashboard](https://stytch.com/dashboard/rbac). Read more about these entities and how they work in 93 | /// our [RBAC overview](https://stytch.com/docs/guides/rbac/overview). 94 | pub policy: std::option::Option, 95 | } 96 | 97 | pub struct RBAC { 98 | http_client: crate::client::Client, 99 | } 100 | 101 | impl RBAC { 102 | pub fn new(http_client: crate::client::Client) -> Self { 103 | Self { 104 | http_client: http_client.clone(), 105 | } 106 | } 107 | 108 | pub async fn policy(&self, body: PolicyRequest) -> crate::Result { 109 | let path = format!( 110 | "/v1/rbac/policy?{}", 111 | serde_urlencoded::to_string(body).unwrap() 112 | ); 113 | self.http_client 114 | .send(crate::Request { 115 | method: http::Method::GET, 116 | path, 117 | body: serde_json::json!({}), 118 | }) 119 | .await 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/consumer/passwords_session.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::device_history::DeviceInfo; 8 | use crate::consumer::sessions::Session; 9 | use crate::consumer::users::User; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | /// ResetRequest: Request type for `Sessions.reset`. 13 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 14 | pub struct ResetRequest { 15 | /// password: The password for the user. Any UTF8 character is allowed, e.g. spaces, emojis, non-English 16 | /// characters, etc. 17 | pub password: String, 18 | /// session_token: The `session_token` associated with a User's existing Session. 19 | pub session_token: std::option::Option, 20 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 21 | pub session_jwt: std::option::Option, 22 | /// session_duration_minutes: Set the session lifetime to be this many minutes from now. This will start a 23 | /// new session if one doesn't already exist, 24 | /// returning both an opaque `session_token` and `session_jwt` for this session. Remember that the 25 | /// `session_jwt` will have a fixed lifetime of 26 | /// five minutes regardless of the underlying session duration, and will need to be refreshed over time. 27 | /// 28 | /// This value must be a minimum of 5 and a maximum of 527040 minutes (366 days). 29 | /// 30 | /// If a `session_token` or `session_jwt` is provided then a successful authentication will continue to 31 | /// extend the session this many minutes. 32 | /// 33 | /// If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created. 34 | pub session_duration_minutes: std::option::Option, 35 | /// session_custom_claims: Add a custom claims map to the Session being authenticated. Claims are only 36 | /// created if a Session is initialized by providing a value in `session_duration_minutes`. Claims will be 37 | /// included on the Session object and in the JWT. To update a key in an existing Session, supply a new 38 | /// value. To delete a key, supply a null value. 39 | /// 40 | /// Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be 41 | /// ignored. Total custom claims size cannot exceed four kilobytes. 42 | pub session_custom_claims: std::option::Option, 43 | /// telemetry_id: If the `telemetry_id` is passed, as part of this request, Stytch will call the 44 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) and store the associated 45 | /// fingerprints and IPGEO information for the User. Your workspace must be enabled for Device 46 | /// Fingerprinting to use this feature. 47 | pub telemetry_id: std::option::Option, 48 | } 49 | /// ResetResponse: Response type for `Sessions.reset`. 50 | #[derive(Serialize, Deserialize, Debug, Clone)] 51 | pub struct ResetResponse { 52 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 53 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 54 | /// debug an issue. 55 | pub request_id: String, 56 | /// user_id: The unique ID of the affected User. 57 | pub user_id: String, 58 | /// user: The `user` object affected by this API call. See the 59 | /// [Get user endpoint](https://stytch.com/docs/api/get-user) for complete response field details. 60 | pub user: User, 61 | /// session_token: A secret token for a given Stytch Session. 62 | pub session_token: String, 63 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 64 | pub session_jwt: String, 65 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 66 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 67 | /// are server errors. 68 | #[serde(with = "http_serde::status_code")] 69 | pub status_code: http::StatusCode, 70 | /// session: If you initiate a Session, by including `session_duration_minutes` in your authenticate call, 71 | /// you'll receive a full Session object in the response. 72 | /// 73 | /// See [Session object](https://stytch.com/docs/api/session-object) for complete response fields. 74 | /// 75 | pub session: std::option::Option, 76 | /// user_device: If a valid `telemetry_id` was passed in the request and the 77 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) returned results, the 78 | /// `user_device` response field will contain information about the user's device attributes. 79 | pub user_device: std::option::Option, 80 | } 81 | 82 | pub struct Sessions { 83 | http_client: crate::client::Client, 84 | } 85 | 86 | impl Sessions { 87 | pub fn new(http_client: crate::client::Client) -> Self { 88 | Self { 89 | http_client: http_client.clone(), 90 | } 91 | } 92 | 93 | pub async fn reset(&self, body: ResetRequest) -> crate::Result { 94 | let path = String::from("/v1/passwords/session/reset"); 95 | self.http_client 96 | .send(crate::Request { 97 | method: http::Method::POST, 98 | path, 99 | body, 100 | }) 101 | .await 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/consumer/passwords_existing_password.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::device_history::DeviceInfo; 8 | use crate::consumer::sessions::Session; 9 | use crate::consumer::users::User; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | /// ResetRequest: Request type for `ExistingPassword.reset`. 13 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 14 | pub struct ResetRequest { 15 | /// email: The email address of the end user. 16 | pub email: String, 17 | /// existing_password: The user's existing password. 18 | pub existing_password: String, 19 | /// new_password: The new password for the user. 20 | pub new_password: String, 21 | /// session_token: The `session_token` associated with a User's existing Session. 22 | pub session_token: std::option::Option, 23 | /// session_duration_minutes: Set the session lifetime to be this many minutes from now. This will start a 24 | /// new session if one doesn't already exist, 25 | /// returning both an opaque `session_token` and `session_jwt` for this session. Remember that the 26 | /// `session_jwt` will have a fixed lifetime of 27 | /// five minutes regardless of the underlying session duration, and will need to be refreshed over time. 28 | /// 29 | /// This value must be a minimum of 5 and a maximum of 527040 minutes (366 days). 30 | /// 31 | /// If a `session_token` or `session_jwt` is provided then a successful authentication will continue to 32 | /// extend the session this many minutes. 33 | /// 34 | /// If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created. 35 | pub session_duration_minutes: std::option::Option, 36 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 37 | pub session_jwt: std::option::Option, 38 | /// session_custom_claims: Add a custom claims map to the Session being authenticated. Claims are only 39 | /// created if a Session is initialized by providing a value in `session_duration_minutes`. Claims will be 40 | /// included on the Session object and in the JWT. To update a key in an existing Session, supply a new 41 | /// value. To delete a key, supply a null value. 42 | /// 43 | /// Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be 44 | /// ignored. Total custom claims size cannot exceed four kilobytes. 45 | pub session_custom_claims: std::option::Option, 46 | /// telemetry_id: If the `telemetry_id` is passed, as part of this request, Stytch will call the 47 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) and store the associated 48 | /// fingerprints and IPGEO information for the User. Your workspace must be enabled for Device 49 | /// Fingerprinting to use this feature. 50 | pub telemetry_id: std::option::Option, 51 | } 52 | /// ResetResponse: Response type for `ExistingPassword.reset`. 53 | #[derive(Serialize, Deserialize, Debug, Clone)] 54 | pub struct ResetResponse { 55 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 56 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 57 | /// debug an issue. 58 | pub request_id: String, 59 | /// user_id: The unique ID of the affected User. 60 | pub user_id: String, 61 | /// session_token: A secret token for a given Stytch Session. 62 | pub session_token: String, 63 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 64 | pub session_jwt: String, 65 | /// user: The `user` object affected by this API call. See the 66 | /// [Get user endpoint](https://stytch.com/docs/api/get-user) for complete response field details. 67 | pub user: User, 68 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 69 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 70 | /// are server errors. 71 | #[serde(with = "http_serde::status_code")] 72 | pub status_code: http::StatusCode, 73 | /// session: If you initiate a Session, by including `session_duration_minutes` in your authenticate call, 74 | /// you'll receive a full Session object in the response. 75 | /// 76 | /// See [Session object](https://stytch.com/docs/api/session-object) for complete response fields. 77 | /// 78 | pub session: std::option::Option, 79 | /// user_device: If a valid `telemetry_id` was passed in the request and the 80 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) returned results, the 81 | /// `user_device` response field will contain information about the user's device attributes. 82 | pub user_device: std::option::Option, 83 | } 84 | 85 | pub struct ExistingPassword { 86 | http_client: crate::client::Client, 87 | } 88 | 89 | impl ExistingPassword { 90 | pub fn new(http_client: crate::client::Client) -> Self { 91 | Self { 92 | http_client: http_client.clone(), 93 | } 94 | } 95 | 96 | pub async fn reset(&self, body: ResetRequest) -> crate::Result { 97 | let path = String::from("/v1/passwords/existing_password/reset"); 98 | self.http_client 99 | .send(crate::Request { 100 | method: http::Method::POST, 101 | path, 102 | body, 103 | }) 104 | .await 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/consumer/m2m_clients_secrets.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::m2m::M2MClient; 8 | use crate::consumer::m2m::M2MClientWithNextClientSecret; 9 | use percent_encoding; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | /// RotateCancelRequest: Request type for `Secrets.rotate_cancel`. 13 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 14 | pub struct RotateCancelRequest { 15 | /// client_id: The ID of the client. 16 | pub client_id: String, 17 | } 18 | /// RotateCancelResponse: Response type for `Secrets.rotate_cancel`. 19 | #[derive(Serialize, Deserialize, Debug, Clone)] 20 | pub struct RotateCancelResponse { 21 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 22 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 23 | /// debug an issue. 24 | pub request_id: String, 25 | /// m2m_client: The M2M Client affected by this operation. 26 | pub m2m_client: M2MClient, 27 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 28 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 29 | /// are server errors. 30 | #[serde(with = "http_serde::status_code")] 31 | pub status_code: http::StatusCode, 32 | } 33 | /// RotateRequest: Request type for `Secrets.rotate`. 34 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 35 | pub struct RotateRequest { 36 | /// client_id: The ID of the client. 37 | pub client_id: String, 38 | } 39 | /// RotateResponse: Response type for `Secrets.rotate`. 40 | #[derive(Serialize, Deserialize, Debug, Clone)] 41 | pub struct RotateResponse { 42 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 43 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 44 | /// debug an issue. 45 | pub request_id: String, 46 | /// m2m_client: The M2M Client affected by this operation. 47 | pub m2m_client: M2MClient, 48 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 49 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 50 | /// are server errors. 51 | #[serde(with = "http_serde::status_code")] 52 | pub status_code: http::StatusCode, 53 | } 54 | /// RotateStartRequest: Request type for `Secrets.rotate_start`. 55 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 56 | pub struct RotateStartRequest { 57 | /// client_id: The ID of the client. 58 | pub client_id: String, 59 | } 60 | /// RotateStartResponse: Response type for `Secrets.rotate_start`. 61 | #[derive(Serialize, Deserialize, Debug, Clone)] 62 | pub struct RotateStartResponse { 63 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 64 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 65 | /// debug an issue. 66 | pub request_id: String, 67 | /// m2m_client: The M2M Client affected by this operation. 68 | pub m2m_client: M2MClientWithNextClientSecret, 69 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 70 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 71 | /// are server errors. 72 | #[serde(with = "http_serde::status_code")] 73 | pub status_code: http::StatusCode, 74 | } 75 | 76 | pub struct Secrets { 77 | http_client: crate::client::Client, 78 | } 79 | 80 | impl Secrets { 81 | pub fn new(http_client: crate::client::Client) -> Self { 82 | Self { 83 | http_client: http_client.clone(), 84 | } 85 | } 86 | 87 | pub async fn rotate_start( 88 | &self, 89 | body: RotateStartRequest, 90 | ) -> crate::Result { 91 | let client_id = percent_encoding::utf8_percent_encode( 92 | &body.client_id, 93 | percent_encoding::NON_ALPHANUMERIC, 94 | ) 95 | .to_string(); 96 | let path = format!("/v1/m2m/clients/{client_id}/secrets/rotate/start"); 97 | self.http_client 98 | .send(crate::Request { 99 | method: http::Method::POST, 100 | path, 101 | body, 102 | }) 103 | .await 104 | } 105 | pub async fn rotate_cancel( 106 | &self, 107 | body: RotateCancelRequest, 108 | ) -> crate::Result { 109 | let client_id = percent_encoding::utf8_percent_encode( 110 | &body.client_id, 111 | percent_encoding::NON_ALPHANUMERIC, 112 | ) 113 | .to_string(); 114 | let path = format!("/v1/m2m/clients/{client_id}/secrets/rotate/cancel"); 115 | self.http_client 116 | .send(crate::Request { 117 | method: http::Method::POST, 118 | path, 119 | body, 120 | }) 121 | .await 122 | } 123 | pub async fn rotate(&self, body: RotateRequest) -> crate::Result { 124 | let client_id = percent_encoding::utf8_percent_encode( 125 | &body.client_id, 126 | percent_encoding::NON_ALPHANUMERIC, 127 | ) 128 | .to_string(); 129 | let path = format!("/v1/m2m/clients/{client_id}/secrets/rotate"); 130 | self.http_client 131 | .send(crate::Request { 132 | method: http::Method::POST, 133 | path, 134 | body, 135 | }) 136 | .await 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/consumer/connected_apps_clients_secrets.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::connected_apps::ConnectedAppClient; 8 | use crate::consumer::connected_apps::ConnectedAppWithNextClientSecret; 9 | use percent_encoding; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | /// RotateCancelRequest: Request type for `Secrets.rotate_cancel`. 13 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 14 | pub struct RotateCancelRequest { 15 | /// client_id: The ID of the client. 16 | pub client_id: String, 17 | } 18 | /// RotateCancelResponse: Response type for `Secrets.rotate_cancel`. 19 | #[derive(Serialize, Deserialize, Debug, Clone)] 20 | pub struct RotateCancelResponse { 21 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 22 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 23 | /// debug an issue. 24 | pub request_id: String, 25 | /// connected_app: The Connected App affected by this operation. 26 | pub connected_app: ConnectedAppClient, 27 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 28 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 29 | /// are server errors. 30 | #[serde(with = "http_serde::status_code")] 31 | pub status_code: http::StatusCode, 32 | } 33 | /// RotateRequest: Request type for `Secrets.rotate`. 34 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 35 | pub struct RotateRequest { 36 | /// client_id: The ID of the client. 37 | pub client_id: String, 38 | } 39 | /// RotateResponse: Response type for `Secrets.rotate`. 40 | #[derive(Serialize, Deserialize, Debug, Clone)] 41 | pub struct RotateResponse { 42 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 43 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 44 | /// debug an issue. 45 | pub request_id: String, 46 | /// connected_app: The Connected App affected by this operation. 47 | pub connected_app: ConnectedAppClient, 48 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 49 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 50 | /// are server errors. 51 | #[serde(with = "http_serde::status_code")] 52 | pub status_code: http::StatusCode, 53 | } 54 | /// RotateStartRequest: Request type for `Secrets.rotate_start`. 55 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 56 | pub struct RotateStartRequest { 57 | /// client_id: The ID of the client. 58 | pub client_id: String, 59 | } 60 | /// RotateStartResponse: Response type for `Secrets.rotate_start`. 61 | #[derive(Serialize, Deserialize, Debug, Clone)] 62 | pub struct RotateStartResponse { 63 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 64 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 65 | /// debug an issue. 66 | pub request_id: String, 67 | /// connected_app: The Connected App affected by this operation. 68 | pub connected_app: ConnectedAppWithNextClientSecret, 69 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 70 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 71 | /// are server errors. 72 | #[serde(with = "http_serde::status_code")] 73 | pub status_code: http::StatusCode, 74 | } 75 | 76 | pub struct Secrets { 77 | http_client: crate::client::Client, 78 | } 79 | 80 | impl Secrets { 81 | pub fn new(http_client: crate::client::Client) -> Self { 82 | Self { 83 | http_client: http_client.clone(), 84 | } 85 | } 86 | 87 | pub async fn rotate_start( 88 | &self, 89 | body: RotateStartRequest, 90 | ) -> crate::Result { 91 | let client_id = percent_encoding::utf8_percent_encode( 92 | &body.client_id, 93 | percent_encoding::NON_ALPHANUMERIC, 94 | ) 95 | .to_string(); 96 | let path = format!("/v1/connected_apps/clients/{client_id}/secrets/rotate/start"); 97 | self.http_client 98 | .send(crate::Request { 99 | method: http::Method::POST, 100 | path, 101 | body, 102 | }) 103 | .await 104 | } 105 | pub async fn rotate_cancel( 106 | &self, 107 | body: RotateCancelRequest, 108 | ) -> crate::Result { 109 | let client_id = percent_encoding::utf8_percent_encode( 110 | &body.client_id, 111 | percent_encoding::NON_ALPHANUMERIC, 112 | ) 113 | .to_string(); 114 | let path = format!("/v1/connected_apps/clients/{client_id}/secrets/rotate/cancel"); 115 | self.http_client 116 | .send(crate::Request { 117 | method: http::Method::POST, 118 | path, 119 | body, 120 | }) 121 | .await 122 | } 123 | pub async fn rotate(&self, body: RotateRequest) -> crate::Result { 124 | let client_id = percent_encoding::utf8_percent_encode( 125 | &body.client_id, 126 | percent_encoding::NON_ALPHANUMERIC, 127 | ) 128 | .to_string(); 129 | let path = format!("/v1/connected_apps/clients/{client_id}/secrets/rotate"); 130 | self.http_client 131 | .send(crate::Request { 132 | method: http::Method::POST, 133 | path, 134 | body, 135 | }) 136 | .await 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/b2b/oauth_discovery.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery::DiscoveredOrganization; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// AuthenticateRequest: Request type for `Discovery.authenticate`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct AuthenticateRequest { 13 | /// discovery_oauth_token: The Discovery OAuth token to authenticate. 14 | pub discovery_oauth_token: String, 15 | pub session_token: std::option::Option, 16 | pub session_duration_minutes: std::option::Option, 17 | pub session_jwt: std::option::Option, 18 | pub session_custom_claims: std::option::Option, 19 | /// pkce_code_verifier: A base64url encoded one time secret used to validate that the request starts and 20 | /// ends on the same device. 21 | pub pkce_code_verifier: std::option::Option, 22 | } 23 | /// AuthenticateResponse: Response type for `Discovery.authenticate`. 24 | #[derive(Serialize, Deserialize, Debug, Clone)] 25 | pub struct AuthenticateResponse { 26 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 27 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 28 | /// debug an issue. 29 | pub request_id: String, 30 | /// intermediate_session_token: The Intermediate Session Token. This token does not necessarily belong to a 31 | /// specific instance of a Member, but represents a bag of factors that may be converted to a member 32 | /// session. The token can be used with the 33 | /// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms), 34 | /// [TOTP Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-totp), or 35 | /// [Recovery Codes Recover endpoint](https://stytch.com/docs/b2b/api/recovery-codes-recover) to complete an 36 | /// MFA flow and log in to the Organization. The token has a default expiry of 10 minutes. It can also be 37 | /// used with the 38 | /// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session) 39 | /// to join a specific Organization that allows the factors represented by the intermediate session token; 40 | /// or the 41 | /// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member. Intermediate Session Tokens have a default expiry of 10 minutes. 42 | pub intermediate_session_token: String, 43 | /// email_address: The email address. 44 | pub email_address: String, 45 | /// discovered_organizations: An array of `discovered_organization` objects tied to the 46 | /// `intermediate_session_token`, `session_token`, or `session_jwt`. See the 47 | /// [Discovered Organization Object](https://stytch.com/docs/b2b/api/discovered-organization-object) for 48 | /// complete details. 49 | /// 50 | /// Note that Organizations will only appear here under any of the following conditions: 51 | /// 1. The end user is already a Member of the Organization. 52 | /// 2. The end user is invited to the Organization. 53 | /// 3. The end user can join the Organization because: 54 | /// 55 | /// a) The Organization allows JIT provisioning. 56 | /// 57 | /// b) The Organizations' allowed domains list contains the Member's email domain. 58 | /// 59 | /// c) The Organization has at least one other Member with a verified email address with the same domain 60 | /// as the end user (to prevent phishing attacks). 61 | pub discovered_organizations: std::vec::Vec, 62 | /// provider_type: Denotes the OAuth identity provider that the user has authenticated with, e.g. Google, 63 | /// Microsoft, GitHub etc. 64 | pub provider_type: String, 65 | /// provider_tenant_id: The tenant ID returned by the OAuth provider. This is typically used to identify an 66 | /// organization or group within the provider's domain. For example, in HubSpot this is a Hub ID, in Slack 67 | /// this is the Workspace ID, and in GitHub this is an organization ID. This field will only be populated if 68 | /// exactly one tenant ID is returned from a successful OAuth authentication and developers should prefer 69 | /// `provider_tenant_ids` over this since it accounts for the possibility of an OAuth provider yielding 70 | /// multiple tenant IDs. 71 | pub provider_tenant_id: String, 72 | /// provider_tenant_ids: All tenant IDs returned by the OAuth provider. These is typically used to identify 73 | /// organizations or groups within the provider's domain. For example, in HubSpot this is a Hub ID, in Slack 74 | /// this is the Workspace ID, and in GitHub this is an organization ID. Some OAuth providers do not return 75 | /// tenant IDs, some providers are guaranteed to return one, and some may return multiple. This field will 76 | /// always be populated if at least one tenant ID was returned from the OAuth provider and developers should 77 | /// prefer this field over `provider_tenant_id`. 78 | pub provider_tenant_ids: std::vec::Vec, 79 | /// full_name: The full name of the authenticated end user, if available. 80 | pub full_name: String, 81 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 82 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 83 | /// are server errors. 84 | #[serde(with = "http_serde::status_code")] 85 | pub status_code: http::StatusCode, 86 | } 87 | 88 | pub struct Discovery { 89 | http_client: crate::client::Client, 90 | } 91 | 92 | impl Discovery { 93 | pub fn new(http_client: crate::client::Client) -> Self { 94 | Self { 95 | http_client: http_client.clone(), 96 | } 97 | } 98 | 99 | pub async fn authenticate( 100 | &self, 101 | body: AuthenticateRequest, 102 | ) -> crate::Result { 103 | let path = String::from("/v1/b2b/oauth/discovery/authenticate"); 104 | self.http_client 105 | .send(crate::Request { 106 | method: http::Method::POST, 107 | path, 108 | body, 109 | }) 110 | .await 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/consumer/otp.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::attribute::Attributes; 8 | use crate::consumer::device_history::DeviceInfo; 9 | use crate::consumer::magic_links::Options; 10 | use crate::consumer::otp_email::Email; 11 | use crate::consumer::otp_sms::Sms; 12 | use crate::consumer::otp_whatsapp::Whatsapp; 13 | use crate::consumer::sessions::Session; 14 | use crate::consumer::users::User; 15 | use serde::{Deserialize, Serialize}; 16 | 17 | /// AuthenticateRequest: Request type for `OTPs.authenticate`. 18 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 19 | pub struct AuthenticateRequest { 20 | /// method_id: The `email_id` or `phone_id` involved in the given authentication. 21 | pub method_id: String, 22 | /// code: The code to authenticate. 23 | pub code: String, 24 | /// attributes: Provided attributes to help with fraud detection. These values are pulled and passed into 25 | /// Stytch endpoints by your application. 26 | pub attributes: std::option::Option, 27 | /// options: Specify optional security settings. 28 | pub options: std::option::Option, 29 | /// session_token: The `session_token` associated with a User's existing Session. 30 | pub session_token: std::option::Option, 31 | /// session_duration_minutes: Set the session lifetime to be this many minutes from now. This will start a 32 | /// new session if one doesn't already exist, 33 | /// returning both an opaque `session_token` and `session_jwt` for this session. Remember that the 34 | /// `session_jwt` will have a fixed lifetime of 35 | /// five minutes regardless of the underlying session duration, and will need to be refreshed over time. 36 | /// 37 | /// This value must be a minimum of 5 and a maximum of 527040 minutes (366 days). 38 | /// 39 | /// If a `session_token` or `session_jwt` is provided then a successful authentication will continue to 40 | /// extend the session this many minutes. 41 | /// 42 | /// If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created. 43 | pub session_duration_minutes: std::option::Option, 44 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 45 | pub session_jwt: std::option::Option, 46 | /// session_custom_claims: Add a custom claims map to the Session being authenticated. Claims are only 47 | /// created if a Session is initialized by providing a value in `session_duration_minutes`. Claims will be 48 | /// included on the Session object and in the JWT. To update a key in an existing Session, supply a new 49 | /// value. To delete a key, supply a null value. 50 | /// 51 | /// Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be 52 | /// ignored. Total custom claims size cannot exceed four kilobytes. 53 | pub session_custom_claims: std::option::Option, 54 | /// telemetry_id: If the `telemetry_id` is passed, as part of this request, Stytch will call the 55 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) and store the associated 56 | /// fingerprints and IPGEO information for the User. Your workspace must be enabled for Device 57 | /// Fingerprinting to use this feature. 58 | pub telemetry_id: std::option::Option, 59 | } 60 | /// AuthenticateResponse: Response type for `OTPs.authenticate`. 61 | #[derive(Serialize, Deserialize, Debug, Clone)] 62 | pub struct AuthenticateResponse { 63 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 64 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 65 | /// debug an issue. 66 | pub request_id: String, 67 | /// user_id: The unique ID of the affected User. 68 | pub user_id: String, 69 | /// method_id: The `email_id` or `phone_id` involved in the given authentication. 70 | pub method_id: String, 71 | /// session_token: A secret token for a given Stytch Session. 72 | pub session_token: String, 73 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 74 | pub session_jwt: String, 75 | /// user: The `user` object affected by this API call. See the 76 | /// [Get user endpoint](https://stytch.com/docs/api/get-user) for complete response field details. 77 | pub user: User, 78 | /// reset_sessions: Indicates if all other of the User's Sessions need to be reset. You should check this 79 | /// field if you aren't using Stytch's Session product. If you are using Stytch's Session product, we revoke 80 | /// the User's other sessions for you. 81 | pub reset_sessions: bool, 82 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 83 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 84 | /// are server errors. 85 | #[serde(with = "http_serde::status_code")] 86 | pub status_code: http::StatusCode, 87 | /// session: If you initiate a Session, by including `session_duration_minutes` in your authenticate call, 88 | /// you'll receive a full Session object in the response. 89 | /// 90 | /// See [Session object](https://stytch.com/docs/api/session-object) for complete response fields. 91 | /// 92 | pub session: std::option::Option, 93 | /// user_device: If a valid `telemetry_id` was passed in the request and the 94 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) returned results, the 95 | /// `user_device` response field will contain information about the user's device attributes. 96 | pub user_device: std::option::Option, 97 | } 98 | 99 | pub struct OTPs { 100 | http_client: crate::client::Client, 101 | pub sms: Sms, 102 | pub whatsapp: Whatsapp, 103 | pub email: Email, 104 | } 105 | 106 | impl OTPs { 107 | pub fn new(http_client: crate::client::Client) -> Self { 108 | Self { 109 | http_client: http_client.clone(), 110 | sms: Sms::new(http_client.clone()), 111 | whatsapp: Whatsapp::new(http_client.clone()), 112 | email: Email::new(http_client.clone()), 113 | } 114 | } 115 | 116 | pub async fn authenticate( 117 | &self, 118 | body: AuthenticateRequest, 119 | ) -> crate::Result { 120 | let path = String::from("/v1/otps/authenticate"); 121 | self.http_client 122 | .send(crate::Request { 123 | method: http::Method::POST, 124 | path, 125 | body, 126 | }) 127 | .await 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/consumer/idp_oauth.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::connected_apps::ConnectedAppPublic; 8 | use crate::consumer::idp::ScopeResult; 9 | use crate::consumer::users::User; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | /// AuthorizeRequest: Request type for `OAuth.authorize`. 13 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 14 | pub struct AuthorizeRequest { 15 | /// consent_granted: Indicates whether the user granted the requested scopes. 16 | pub consent_granted: bool, 17 | /// scopes: An array of scopes requested by the client. 18 | pub scopes: std::vec::Vec, 19 | /// client_id: The ID of the Connected App client. 20 | pub client_id: String, 21 | /// redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI 22 | /// provided at the start of the OAuth flow. This field is required when using the `authorization_code` 23 | /// grant. 24 | pub redirect_uri: String, 25 | /// response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`. 26 | pub response_type: String, 27 | /// user_id: The unique ID of a specific User. You may use an `external_id` here if one is set for the user. 28 | pub user_id: std::option::Option, 29 | /// session_token: The `session_token` associated with a User's existing Session. 30 | pub session_token: std::option::Option, 31 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 32 | pub session_jwt: std::option::Option, 33 | /// prompt: Space separated list that specifies how the Authorization Server should prompt the user for 34 | /// reauthentication and consent. Only `consent` is supported today. 35 | pub prompt: std::option::Option, 36 | /// state: An opaque value used to maintain state between the request and callback. 37 | pub state: std::option::Option, 38 | /// nonce: A string used to associate a client session with an ID token to mitigate replay attacks. 39 | pub nonce: std::option::Option, 40 | /// code_challenge: A base64url encoded challenge derived from the code verifier for PKCE flows. 41 | pub code_challenge: std::option::Option, 42 | pub resources: std::option::Option>, 43 | } 44 | /// AuthorizeResponse: Response type for `OAuth.authorize`. 45 | #[derive(Serialize, Deserialize, Debug, Clone)] 46 | pub struct AuthorizeResponse { 47 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 48 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 49 | /// debug an issue. 50 | pub request_id: String, 51 | /// redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI 52 | /// provided at the start of the OAuth flow. This field is required when using the `authorization_code` 53 | /// grant. 54 | pub redirect_uri: String, 55 | #[serde(with = "http_serde::status_code")] 56 | pub status_code: http::StatusCode, 57 | /// authorization_code: A one-time use code that can be exchanged for tokens. 58 | pub authorization_code: std::option::Option, 59 | } 60 | /// AuthorizeStartRequest: Request type for `OAuth.authorize_start`. 61 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 62 | pub struct AuthorizeStartRequest { 63 | /// client_id: The ID of the Connected App client. 64 | pub client_id: String, 65 | /// redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI 66 | /// provided at the start of the OAuth flow. This field is required when using the `authorization_code` 67 | /// grant. 68 | pub redirect_uri: String, 69 | /// response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`. 70 | pub response_type: String, 71 | /// scopes: An array of scopes requested by the client. 72 | pub scopes: std::vec::Vec, 73 | /// user_id: The unique ID of a specific User. You may use an `external_id` here if one is set for the user. 74 | pub user_id: std::option::Option, 75 | /// session_token: The `session_token` associated with a User's existing Session. 76 | pub session_token: std::option::Option, 77 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 78 | pub session_jwt: std::option::Option, 79 | /// prompt: Space separated list that specifies how the Authorization Server should prompt the user for 80 | /// reauthentication and consent. Only `consent` is supported today. 81 | pub prompt: std::option::Option, 82 | } 83 | /// AuthorizeStartResponse: Response type for `OAuth.authorize_start`. 84 | #[derive(Serialize, Deserialize, Debug, Clone)] 85 | pub struct AuthorizeStartResponse { 86 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 87 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 88 | /// debug an issue. 89 | pub request_id: String, 90 | /// user_id: The unique ID of the affected User. 91 | pub user_id: String, 92 | /// user: The `user` object affected by this API call. See the 93 | /// [Get user endpoint](https://stytch.com/docs/api/get-user) for complete response field details. 94 | pub user: User, 95 | pub client: ConnectedAppPublic, 96 | /// consent_required: Whether the user must provide explicit consent for the authorization request. 97 | pub consent_required: bool, 98 | /// scope_results: Details about each requested scope. 99 | pub scope_results: std::vec::Vec, 100 | #[serde(with = "http_serde::status_code")] 101 | pub status_code: http::StatusCode, 102 | } 103 | 104 | pub struct OAuth { 105 | http_client: crate::client::Client, 106 | } 107 | 108 | impl OAuth { 109 | pub fn new(http_client: crate::client::Client) -> Self { 110 | Self { 111 | http_client: http_client.clone(), 112 | } 113 | } 114 | 115 | pub async fn authorize_start( 116 | &self, 117 | body: AuthorizeStartRequest, 118 | ) -> crate::Result { 119 | let path = String::from("/v1/idp/oauth/authorize/start"); 120 | self.http_client 121 | .send(crate::Request { 122 | method: http::Method::POST, 123 | path, 124 | body, 125 | }) 126 | .await 127 | } 128 | pub async fn authorize(&self, body: AuthorizeRequest) -> crate::Result { 129 | let path = String::from("/v1/idp/oauth/authorize"); 130 | self.http_client 131 | .send(crate::Request { 132 | method: http::Method::POST, 133 | path, 134 | body, 135 | }) 136 | .await 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stytch Rust Library 2 | 3 | The Stytch Rust library makes it easy to use the Stytch user infrastructure API in server-side Rust applications. 4 | 5 | It pairs well with the Stytch [Web SDK](https://www.npmjs.com/package/@stytch/vanilla-js) or your own custom authentication flow. 6 | 7 | The minimum supported Rust version (MSRV) of this library is Rust 1.70. 8 | 9 | ## Install 10 | 11 | Use `cargo add stytch` to add this to your `Cargo.toml`: 12 | 13 | ```toml 14 | stytch = "8.0.0" 15 | ``` 16 | 17 | ## Usage 18 | 19 | You can find your API credentials in the [Stytch Dashboard](https://stytch.com/dashboard/api-keys). 20 | 21 | This client library supports all of Stytch's live products: 22 | 23 | **B2C** 24 | 25 | - [x] [Email Magic Links](https://stytch.com/docs/api/send-by-email) 26 | - [x] [Embeddable Magic Links](https://stytch.com/docs/api/create-magic-link) 27 | - [x] [OAuth logins](https://stytch.com/docs/api/oauth-google-start) 28 | - [x] [SMS passcodes](https://stytch.com/docs/api/send-otp-by-sms) 29 | - [x] [WhatsApp passcodes](https://stytch.com/docs/api/whatsapp-send) 30 | - [x] [Email passcodes](https://stytch.com/docs/api/send-otp-by-email) 31 | - [x] [Session Management](https://stytch.com/docs/api/session-auth) 32 | - [x] [WebAuthn](https://stytch.com/docs/api/webauthn-register-start) 33 | - [x] [User Management](https://stytch.com/docs/api/create-user) 34 | - [x] [Time-based one-time passcodes (TOTPs)](https://stytch.com/docs/api/totp-create) 35 | - [x] [Crypto wallets](https://stytch.com/docs/api/crypto-wallet-authenticate-start) 36 | - [x] [Passwords](https://stytch.com/docs/api/password-create) 37 | 38 | **B2B** 39 | 40 | - [x] [Organizations](https://stytch.com/docs/b2b/api/organization-object) 41 | - [x] [Members](https://stytch.com/docs/b2b/api/member-object) 42 | - [x] [Email Magic Links](https://stytch.com/docs/b2b/api/send-login-signup-email) 43 | - [x] [OAuth logins](https://stytch.com/docs/b2b/api/oauth-google-start) 44 | - [x] [Session Management](https://stytch.com/docs/b2b/api/session-object) 45 | - [x] [Single-Sign On](https://stytch.com/docs/b2b/api/sso-authenticate-start) 46 | - [x] [Discovery](https://stytch.com/docs/b2b/api/discovered-organization-object) 47 | - [x] [Passwords](https://stytch.com/docs/b2b/api/passwords-authenticate) 48 | 49 | **Shared** 50 | 51 | - [x] [M2M](https://stytch.com/docs/api/m2m-client) 52 | 53 | ### Example B2C usage 54 | 55 | Create an API client: 56 | 57 | ```rust 58 | let client = stytch::consumer::client::Client::new( 59 | &String::from("project-live-c60c0abe-c25a-4472-a9ed-320c6667d317"), 60 | &String::from("secret-live-80JASucyk7z_G8Z-7dVwZVGXL5NT_qGAQ2I="), 61 | )?; 62 | ``` 63 | 64 | Send a magic link by email: 65 | 66 | ```rust 67 | use stytch::consumer::magic_links_email::LoginOrCreateRequest; 68 | 69 | let resp = client.magic_links.email.login_or_create(LoginOrCreateRequest{ 70 | email: String::from("sandbox@stytch.com"), 71 | login_magic_link_url: Some(String::from("https://example.com/authenticate")), 72 | signup_magic_link_url: Some(String::from("https://example.com/authenticate")), 73 | ..Default::default() 74 | }).await?; 75 | ``` 76 | 77 | Authenticate the token from the magic link: 78 | 79 | ```rust 80 | use stytch::consumer::magic_links::AuthenticateRequest; 81 | 82 | let resp = client.magic_links.authenticate(AuthenticateRequest { 83 | token: String::from("DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94="), 84 | ..Default::default() 85 | }) 86 | .await?; 87 | ``` 88 | 89 | ### Example B2B usage 90 | 91 | Create an API client: 92 | 93 | ```rust 94 | let client = stytch::b2b::client::Client::new( 95 | &String::from("project-live-c60c0abe-c25a-4472-a9ed-320c6667d317"), 96 | &String::from("secret-live-80JASucyk7z_G8Z-7dVwZVGXL5NT_qGAQ2I="), 97 | )?; 98 | ``` 99 | 100 | Create an organization 101 | 102 | ```rust 103 | use stytch::b2b::organizations::CreateRequest; 104 | 105 | let resp = client.organizations.create(CreateRequest{ 106 | organization_name: String::from("Acme Co"), 107 | organization_slug: Some(String::from("acme-co")), 108 | email_allowed_domains: Some(vec![String::from("acme.co")]), 109 | ..Default::default() 110 | }) 111 | .await?; 112 | ``` 113 | 114 | Log the first user into the organization 115 | 116 | ```rust 117 | use stytch::b2b::magic_links_email::LoginOrSignupRequest; 118 | 119 | let resp = client.magic_links.email.login_or_signup(LoginOrSignupRequest{ 120 | organization_id: String::from("organization-id-from-create-response-..."), 121 | email_address: String::from("admin@acme.co"), 122 | ..Default::default() 123 | }) 124 | .await?; 125 | ``` 126 | 127 | ## Handling Errors 128 | 129 | The error type for all `Result` values is `stytch::Error`. If the error is from the Stytch API, 130 | this will be the `stytch::Error::Response` variant, which always includes an `error_type` field 131 | you can use to identify it: 132 | 133 | ```rust 134 | use stytch::consumer::magic_links::AuthenticateRequest; 135 | 136 | let resp = client.magic_links.authenticate(AuthenticateRequest{ 137 | token: String::from("not-a-token!"), 138 | ..Default::default() 139 | }) 140 | .await; 141 | 142 | match resp { 143 | Err(stytch::Error::Response(err)) => { 144 | if &err.error_type == "invalid_token" { 145 | println!("Whoops! Try again?"); 146 | } else { 147 | println!("Unexpected error type: {}", err.error_type); 148 | } 149 | } 150 | Err(err) => println!("Other error: {:?}", err), 151 | Ok(resp) => println!("Unexpected success: {:?}", resp), 152 | } 153 | ``` 154 | 155 | Learn more about errors in the [docs](https://stytch.com/docs/api/errors). 156 | 157 | ## Cargo Features 158 | 159 | - `reqwest-rustls-tls`: Enable reqwest's `rustls-tls` feature for the rustls implementation. 160 | - `reqwest-native-tls`: Enable reqwest's `native-tls` feature for the native TLS implementation. 161 | (This is enabled by default.) 162 | 163 | ## Documentation 164 | 165 | See example requests and responses for all the endpoints in the [Stytch API Reference](https://stytch.com/docs/api). 166 | 167 | Follow one of the [integration guides](https://stytch.com/docs/guides) or start with one of our [example apps](https://stytch.com/docs/example-apps). 168 | 169 | ## Support 170 | 171 | If you've found a bug, [open an issue](https://github.com/stytchauth/stytch-rust/issues/new)! 172 | 173 | If you have questions or want help troubleshooting, join us in [Slack](https://stytch.com/docs/resources/support/overview) or email support@stytch.com. 174 | 175 | If you've found a security vulnerability, please follow our [responsible disclosure instructions](https://stytch.com/docs/resources/security-and-trust/security#:~:text=Responsible%20disclosure%20program). 176 | 177 | ## Development 178 | 179 | See [DEVELOPMENT.md](DEVELOPMENT.md) 180 | 181 | ## Code of Conduct 182 | 183 | Everyone interacting in the Stytch project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md). 184 | 185 | ## Acknowledgements 186 | 187 | Special thanks to @itsyaasir for donating the `stytch` package name to this project and starting us on our Rust journey! 188 | -------------------------------------------------------------------------------- /src/b2b/scim.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::scim_connection::Connection; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | pub struct Address { 12 | pub formatted: String, 13 | pub street_address: String, 14 | pub locality: String, 15 | pub region: String, 16 | pub postal_code: String, 17 | pub country: String, 18 | #[serde(rename = "type")] 19 | pub type_: String, 20 | pub primary: bool, 21 | } 22 | #[derive(Serialize, Deserialize, Debug, Clone)] 23 | pub struct Email { 24 | pub value: String, 25 | #[serde(rename = "type")] 26 | pub type_: String, 27 | pub primary: bool, 28 | } 29 | #[derive(Serialize, Deserialize, Debug, Clone)] 30 | pub struct EnterpriseExtension { 31 | pub employee_number: String, 32 | pub cost_center: String, 33 | pub division: String, 34 | pub department: String, 35 | pub organization: String, 36 | pub manager: std::option::Option, 37 | } 38 | #[derive(Serialize, Deserialize, Debug, Clone)] 39 | pub struct Entitlement { 40 | pub value: String, 41 | #[serde(rename = "type")] 42 | pub type_: String, 43 | pub primary: bool, 44 | } 45 | #[derive(Serialize, Deserialize, Debug, Clone)] 46 | pub struct Group { 47 | pub value: String, 48 | pub display: String, 49 | } 50 | #[derive(Serialize, Deserialize, Debug, Clone)] 51 | pub struct IMs { 52 | pub value: String, 53 | #[serde(rename = "type")] 54 | pub type_: String, 55 | pub primary: bool, 56 | } 57 | #[derive(Serialize, Deserialize, Debug, Clone)] 58 | pub struct Manager { 59 | pub value: String, 60 | #[serde(rename = "ref")] 61 | pub ref_: String, 62 | pub display_name: String, 63 | } 64 | #[derive(Serialize, Deserialize, Debug, Clone)] 65 | pub struct Name { 66 | pub formatted: String, 67 | pub family_name: String, 68 | pub given_name: String, 69 | pub middle_name: String, 70 | pub honorific_prefix: String, 71 | pub honorific_suffix: String, 72 | } 73 | #[derive(Serialize, Deserialize, Debug, Clone)] 74 | pub struct PhoneNumber { 75 | pub value: String, 76 | #[serde(rename = "type")] 77 | pub type_: String, 78 | pub primary: bool, 79 | } 80 | #[derive(Serialize, Deserialize, Debug, Clone)] 81 | pub struct Photo { 82 | pub value: String, 83 | #[serde(rename = "type")] 84 | pub type_: String, 85 | pub primary: bool, 86 | } 87 | #[derive(Serialize, Deserialize, Debug, Clone)] 88 | pub struct Role { 89 | pub value: String, 90 | #[serde(rename = "type")] 91 | pub type_: String, 92 | pub primary: bool, 93 | } 94 | #[derive(Serialize, Deserialize, Debug, Clone)] 95 | pub struct SCIMAttributes { 96 | pub user_name: String, 97 | pub id: String, 98 | pub external_id: String, 99 | pub active: bool, 100 | pub groups: std::vec::Vec, 101 | pub display_name: String, 102 | pub nick_name: String, 103 | pub profile_url: String, 104 | pub user_type: String, 105 | pub title: String, 106 | pub preferred_language: String, 107 | pub locale: String, 108 | pub timezone: String, 109 | pub emails: std::vec::Vec, 110 | pub phone_numbers: std::vec::Vec, 111 | pub addresses: std::vec::Vec
, 112 | pub ims: std::vec::Vec, 113 | pub photos: std::vec::Vec, 114 | pub entitlements: std::vec::Vec, 115 | pub roles: std::vec::Vec, 116 | pub x509certificates: std::vec::Vec, 117 | pub name: std::option::Option, 118 | pub enterprise_extension: std::option::Option, 119 | } 120 | #[derive(Serialize, Deserialize, Debug, Clone)] 121 | pub struct SCIMConnection { 122 | pub organization_id: String, 123 | pub connection_id: String, 124 | pub status: String, 125 | pub display_name: String, 126 | pub identity_provider: String, 127 | pub base_url: String, 128 | pub bearer_token_last_four: String, 129 | pub scim_group_implicit_role_assignments: std::vec::Vec, 130 | pub next_bearer_token_last_four: String, 131 | pub bearer_token_expires_at: std::option::Option>, 132 | pub next_bearer_token_expires_at: std::option::Option>, 133 | } 134 | #[derive(Serialize, Deserialize, Debug, Clone)] 135 | pub struct SCIMConnectionWithNextToken { 136 | pub organization_id: String, 137 | pub connection_id: String, 138 | pub status: String, 139 | pub display_name: String, 140 | pub base_url: String, 141 | pub identity_provider: String, 142 | pub bearer_token_last_four: String, 143 | pub next_bearer_token: String, 144 | pub scim_group_implicit_role_assignments: std::vec::Vec, 145 | pub bearer_token_expires_at: std::option::Option>, 146 | pub next_bearer_token_expires_at: std::option::Option>, 147 | } 148 | #[derive(Serialize, Deserialize, Debug, Clone)] 149 | pub struct SCIMConnectionWithToken { 150 | pub organization_id: String, 151 | pub connection_id: String, 152 | pub status: String, 153 | pub display_name: String, 154 | pub identity_provider: String, 155 | pub base_url: String, 156 | pub bearer_token: String, 157 | pub scim_group_implicit_role_assignments: std::vec::Vec, 158 | pub bearer_token_expires_at: std::option::Option>, 159 | } 160 | /// SCIMGroup: 161 | #[derive(Serialize, Deserialize, Debug, Clone)] 162 | pub struct SCIMGroup { 163 | /// group_id: Stytch-issued, globally unique UUID that identifies a specific SCIM Group. The entity `id` in 164 | /// the SCIM specification is issued by the Service Provider (SP) and returned to the Identity Provider 165 | /// (IdP) to store and use for uniquely identify and updating the Group moving forward. 166 | pub group_id: String, 167 | /// group_name: The displayName of the SCIM group, sent from the Identity Provider (IdP). 168 | pub group_name: String, 169 | /// organization_id: Globally unique UUID that identifies a specific Organization. The organization_id is 170 | /// critical to perform operations on an Organization, so be sure to preserve this value. 171 | pub organization_id: String, 172 | /// connection_id: The ID of the SCIM connection. 173 | pub connection_id: String, 174 | } 175 | #[derive(Serialize, Deserialize, Debug, Clone)] 176 | pub struct SCIMGroupImplicitRoleAssignments { 177 | pub role_id: String, 178 | pub group_id: String, 179 | pub group_name: String, 180 | } 181 | #[derive(Serialize, Deserialize, Debug, Clone)] 182 | pub struct X509Certificate { 183 | pub value: String, 184 | #[serde(rename = "type")] 185 | pub type_: String, 186 | pub primary: bool, 187 | } 188 | 189 | pub struct SCIM { 190 | pub connection: Connection, 191 | } 192 | 193 | impl SCIM { 194 | pub fn new(http_client: crate::client::Client) -> Self { 195 | Self { 196 | connection: Connection::new(http_client.clone()), 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | use base64::{engine::general_purpose, Engine as _}; 2 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; 3 | use std::sync::Arc; 4 | use std::time::{Duration, Instant}; 5 | use tokio::sync::Mutex; 6 | 7 | const LIVE_URL: &str = "https://api.stytch.com/"; 8 | const TEST_URL: &str = "https://test.stytch.com/"; 9 | 10 | #[derive(Clone)] 11 | pub struct Client { 12 | pub client: reqwest::Client, 13 | pub base_url: reqwest::Url, 14 | pub project_id: String, 15 | jwks_url: String, 16 | jwks: Arc>>, 17 | } 18 | 19 | impl std::fmt::Debug for Client { 20 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 21 | f.debug_struct("Client") 22 | .field("base_url", &self.base_url) 23 | .finish() 24 | } 25 | } 26 | 27 | pub enum Vertical { 28 | Consumer, 29 | B2B, 30 | } 31 | 32 | #[derive(Debug, Serialize, Deserialize, Clone)] 33 | pub struct Jwk { 34 | pub kty: String, 35 | pub kid: String, 36 | pub alg: String, 37 | pub n: String, 38 | pub e: String, 39 | } 40 | 41 | #[derive(Debug, Serialize, Deserialize, Clone)] 42 | struct Jwks { 43 | keys: Vec, 44 | } 45 | 46 | impl Client { 47 | pub fn new(project_id: &str, secret: &str) -> crate::Result { 48 | let base_url = Self::base_url(project_id); 49 | Client::new_with_base_url(project_id, secret, base_url, Vertical::Consumer) 50 | } 51 | 52 | pub fn new_b2b(project_id: &str, secret: &str) -> crate::Result { 53 | let base_url = Self::base_url(project_id); 54 | Client::new_with_base_url(project_id, secret, base_url, Vertical::B2B) 55 | } 56 | 57 | pub fn new_fraud(project_id: &str, secret: &str) -> crate::Result { 58 | let base_url = reqwest::Url::parse("https://telemetry.stytch.com").unwrap(); 59 | Client::new_with_base_url(project_id, secret, base_url, Vertical::Consumer) 60 | } 61 | 62 | pub fn new_with_base_url( 63 | project_id: &str, 64 | secret: &str, 65 | base_url: reqwest::Url, 66 | vertical: Vertical, 67 | ) -> crate::Result { 68 | let mut headers = http::header::HeaderMap::new(); 69 | 70 | let encoded = general_purpose::STANDARD.encode(format!("{}:{}", project_id, secret)); 71 | let basic_auth = format!("Basic {}", encoded).parse::()?; 72 | 73 | headers.insert(http::header::AUTHORIZATION, basic_auth); 74 | 75 | let client = reqwest::Client::builder() 76 | .user_agent(concat!("stytch-rust ", env!("CARGO_PKG_VERSION"))) 77 | .default_headers(headers) 78 | .build()?; 79 | 80 | let jwks_url = match vertical { 81 | Vertical::Consumer => format!("/v1/sessions/jwks/{project_id}"), 82 | Vertical::B2B => format!("/v1/b2b/sessions/jwks/{project_id}"), 83 | }; 84 | 85 | Ok(Self { 86 | client, 87 | project_id: project_id.to_string(), 88 | base_url, 89 | jwks_url, 90 | jwks: Arc::new(Mutex::new(None)), 91 | }) 92 | } 93 | 94 | async fn fetch_jwks(&self) -> crate::Result { 95 | let mut cache = self.jwks.lock().await; 96 | let now = Instant::now(); 97 | 98 | if let Some((timestamp, jwks)) = &*cache { 99 | if now.duration_since(*timestamp) < Duration::from_secs(300) { 100 | return Ok(jwks.clone()); 101 | } 102 | } 103 | 104 | // Fetch new JWKS 105 | let new_jwks = self 106 | .send::<_, Jwks>(crate::Request { 107 | method: http::Method::GET, 108 | path: self.jwks_url.clone(), 109 | body: (), 110 | }) 111 | .await 112 | .map_err(|_| crate::Error::FetchJwks)?; 113 | 114 | *cache = Some((now, new_jwks.clone())); 115 | 116 | Ok(new_jwks) 117 | } 118 | 119 | pub async fn fetch_jwk(&self, kid: &str) -> crate::Result { 120 | let jwks = self.fetch_jwks().await?; 121 | let jwk = jwks 122 | .keys 123 | .iter() 124 | .find(|key| key.kid == kid) 125 | .ok_or_else(|| crate::Error::JwkNotFound(kid.to_string()))?; 126 | Ok(jwk.clone()) 127 | } 128 | 129 | pub async fn send(&self, req: crate::Request) -> crate::Result 130 | where 131 | Req: Serialize + std::fmt::Debug + std::marker::Send, 132 | Res: DeserializeOwned + std::fmt::Debug, 133 | { 134 | let url = self.base_url.join(&req.path)?; 135 | let req = self.client.request(req.method, url).json(&req.body); 136 | 137 | tracing::debug!({ req = ?req }, "send Stytch request"); 138 | let res = req.send().await?; 139 | 140 | if res.status().is_success() { 141 | let body = res.json().await?; 142 | tracing::debug!({ ?body }, "Stytch response success"); 143 | Ok(body) 144 | } else { 145 | let err = res.json::().await?; 146 | tracing::debug!({ ?err }, "Stytch response error"); 147 | Err(crate::Error::Response(err)) 148 | } 149 | } 150 | 151 | fn base_url(project_id: &str) -> reqwest::Url { 152 | if project_id.starts_with("project-live-") { 153 | reqwest::Url::parse(LIVE_URL).unwrap() 154 | } else { 155 | reqwest::Url::parse(TEST_URL).unwrap() 156 | } 157 | } 158 | } 159 | 160 | impl From for crate::Error { 161 | fn from(err: reqwest::Error) -> crate::Error { 162 | crate::Error::Other(Box::new(err)) 163 | } 164 | } 165 | 166 | #[cfg(test)] 167 | mod tests { 168 | use super::*; 169 | use std::env; 170 | 171 | #[tokio::test] 172 | async fn test_jwks_refreshes_after_300_seconds() -> crate::Result<()> { 173 | let project_id = match env::var("STYTCH_PROJECT_ID") { 174 | Ok(val) => val, 175 | Err(_) => { 176 | eprintln!("Skipping test: STYTCH_PROJECT_ID not set"); 177 | return Ok(()); 178 | } 179 | }; 180 | 181 | let secret = match env::var("STYTCH_SECRET") { 182 | Ok(val) => val, 183 | Err(_) => { 184 | eprintln!("Skipping test: STYTCH_SECRET not set"); 185 | return Ok(()); 186 | } 187 | }; 188 | 189 | let client = Client::new(&project_id, &secret)?; 190 | let first_jwks = client.fetch_jwks().await?; 191 | 192 | // Simulate 300 seconds passing 193 | { 194 | let mut cache = client.jwks.lock().await; 195 | if let Some((timestamp, _)) = cache.as_mut() { 196 | *timestamp = Instant::now() - Duration::from_secs(301); 197 | } 198 | } 199 | 200 | // Fetch JWKS again after expiration 201 | let refreshed_jwks = client.fetch_jwks().await?; 202 | 203 | // It's hard to make any great assertion here because JWKS only expire every six months. 204 | // We're not going to write a unit test that sleeps for six months :) 205 | // Instead, let's just check that the kty and alg match expected values. 206 | assert_eq!(first_jwks.keys[0].kty, refreshed_jwks.keys[0].kty); 207 | assert_eq!(first_jwks.keys[0].alg, refreshed_jwks.keys[0].alg); 208 | 209 | Ok(()) 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/b2b/otp_email_discovery.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery::DiscoveredOrganization; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// AuthenticateRequest: Request type for `Discovery.authenticate`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct AuthenticateRequest { 13 | /// email_address: The email address of the Member. 14 | pub email_address: String, 15 | /// code: The code to authenticate. 16 | pub code: String, 17 | } 18 | /// AuthenticateResponse: Response type for `Discovery.authenticate`. 19 | #[derive(Serialize, Deserialize, Debug, Clone)] 20 | pub struct AuthenticateResponse { 21 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 22 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 23 | /// debug an issue. 24 | pub request_id: String, 25 | /// intermediate_session_token: The Intermediate Session Token. This token does not necessarily belong to a 26 | /// specific instance of a Member, but represents a bag of factors that may be converted to a member 27 | /// session. The token can be used with the 28 | /// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms), 29 | /// [TOTP Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-totp), or 30 | /// [Recovery Codes Recover endpoint](https://stytch.com/docs/b2b/api/recovery-codes-recover) to complete an 31 | /// MFA flow and log in to the Organization. The token has a default expiry of 10 minutes. It can also be 32 | /// used with the 33 | /// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session) 34 | /// to join a specific Organization that allows the factors represented by the intermediate session token; 35 | /// or the 36 | /// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member. Intermediate Session Tokens have a default expiry of 10 minutes. 37 | pub intermediate_session_token: String, 38 | /// email_address: The email address. 39 | pub email_address: String, 40 | /// discovered_organizations: An array of `discovered_organization` objects tied to the 41 | /// `intermediate_session_token`, `session_token`, or `session_jwt`. See the 42 | /// [Discovered Organization Object](https://stytch.com/docs/b2b/api/discovered-organization-object) for 43 | /// complete details. 44 | /// 45 | /// Note that Organizations will only appear here under any of the following conditions: 46 | /// 1. The end user is already a Member of the Organization. 47 | /// 2. The end user is invited to the Organization. 48 | /// 3. The end user can join the Organization because: 49 | /// 50 | /// a) The Organization allows JIT provisioning. 51 | /// 52 | /// b) The Organizations' allowed domains list contains the Member's email domain. 53 | /// 54 | /// c) The Organization has at least one other Member with a verified email address with the same domain 55 | /// as the end user (to prevent phishing attacks). 56 | pub discovered_organizations: std::vec::Vec, 57 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 58 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 59 | /// are server errors. 60 | #[serde(with = "http_serde::status_code")] 61 | pub status_code: http::StatusCode, 62 | } 63 | /// SendRequest: Request type for `Discovery.send`. 64 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 65 | pub struct SendRequest { 66 | /// email_address: The email address to start the discovery flow for. 67 | pub email_address: String, 68 | /// login_template_id: Use a custom template for login emails. By default, it will use your default email 69 | /// template. The template must be a template using our built-in customizations or a custom HTML email for 70 | /// OTP - Login. 71 | pub login_template_id: std::option::Option, 72 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 73 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 74 | /// 75 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 76 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 77 | /// 78 | /// Request support for additional languages 79 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 80 | /// 81 | pub locale: std::option::Option, 82 | /// discovery_expiration_minutes: The expiration time, in minutes, for a discovery OTP email. If not 83 | /// accepted within this time frame, the OTP will need to be resent. Defaults to 10 with a minimum of 2 and 84 | /// a maximum of 15. 85 | pub discovery_expiration_minutes: std::option::Option, 86 | } 87 | /// SendResponse: Response type for `Discovery.send`. 88 | #[derive(Serialize, Deserialize, Debug, Clone)] 89 | pub struct SendResponse { 90 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 91 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 92 | /// debug an issue. 93 | pub request_id: String, 94 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 95 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 96 | /// are server errors. 97 | #[serde(with = "http_serde::status_code")] 98 | pub status_code: http::StatusCode, 99 | } 100 | 101 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 102 | pub enum SendRequestLocale { 103 | #[serde(rename = "en")] 104 | #[default] 105 | En, 106 | #[serde(rename = "es")] 107 | Es, 108 | #[serde(rename = "ptbr")] 109 | Ptbr, 110 | #[serde(rename = "fr")] 111 | Fr, 112 | } 113 | 114 | pub struct Discovery { 115 | http_client: crate::client::Client, 116 | } 117 | 118 | impl Discovery { 119 | pub fn new(http_client: crate::client::Client) -> Self { 120 | Self { 121 | http_client: http_client.clone(), 122 | } 123 | } 124 | 125 | pub async fn send(&self, body: SendRequest) -> crate::Result { 126 | let path = String::from("/v1/b2b/otps/email/discovery/send"); 127 | self.http_client 128 | .send(crate::Request { 129 | method: http::Method::POST, 130 | path, 131 | body, 132 | }) 133 | .await 134 | } 135 | pub async fn authenticate( 136 | &self, 137 | body: AuthenticateRequest, 138 | ) -> crate::Result { 139 | let path = String::from("/v1/b2b/otps/email/discovery/authenticate"); 140 | self.http_client 141 | .send(crate::Request { 142 | method: http::Method::POST, 143 | path, 144 | body, 145 | }) 146 | .await 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/b2b/rbac.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use serde::{Deserialize, Serialize}; 8 | use serde_urlencoded; 9 | 10 | /// Policy: 11 | #[derive(Serialize, Deserialize, Debug, Clone)] 12 | pub struct Policy { 13 | /// roles: An array of [Role objects](https://stytch.com/docs/b2b/api/rbac-role-object). 14 | pub roles: std::vec::Vec, 15 | /// resources: An array of [Resource objects](https://stytch.com/docs/b2b/api/rbac-resource-object). 16 | pub resources: std::vec::Vec, 17 | pub scopes: std::vec::Vec, 18 | } 19 | /// PolicyResource: 20 | #[derive(Serialize, Deserialize, Debug, Clone)] 21 | pub struct PolicyResource { 22 | /// resource_id: A unique identifier of the RBAC Resource, provided by the developer and intended to be 23 | /// human-readable. 24 | /// 25 | /// A `resource_id` is not allowed to start with `stytch`, which is a special prefix used for Stytch 26 | /// default Resources with reserved `resource_id`s. These include: 27 | /// 28 | /// * `stytch.organization` 29 | /// * `stytch.member` 30 | /// * `stytch.sso` 31 | /// * `stytch.self` 32 | /// 33 | /// Check out the 34 | /// [guide on Stytch default Resources](https://stytch.com/docs/b2b/guides/rbac/stytch-default) for a more 35 | /// detailed explanation. 36 | /// 37 | /// 38 | pub resource_id: String, 39 | /// description: The description of the RBAC Resource. 40 | pub description: String, 41 | /// actions: A list of all possible actions for a provided Resource. 42 | /// 43 | /// Reserved `actions` that are predefined by Stytch include: 44 | /// 45 | /// * `*` 46 | /// * For the `stytch.organization` Resource: 47 | /// * `update.info.name` 48 | /// * `update.info.slug` 49 | /// * `update.info.untrusted_metadata` 50 | /// * `update.info.email_jit_provisioning` 51 | /// * `update.info.logo_url` 52 | /// * `update.info.email_invites` 53 | /// * `update.info.allowed_domains` 54 | /// * `update.info.default_sso_connection` 55 | /// * `update.info.sso_jit_provisioning` 56 | /// * `update.info.mfa_policy` 57 | /// * `update.info.implicit_roles` 58 | /// * `delete` 59 | /// * For the `stytch.member` Resource: 60 | /// * `create` 61 | /// * `update.info.name` 62 | /// * `update.info.untrusted_metadata` 63 | /// * `update.info.mfa-phone` 64 | /// * `update.info.delete.mfa-phone` 65 | /// * `update.settings.is-breakglass` 66 | /// * `update.settings.mfa_enrolled` 67 | /// * `update.settings.roles` 68 | /// * `search` 69 | /// * `delete` 70 | /// * For the `stytch.sso` Resource: 71 | /// * `create` 72 | /// * `update` 73 | /// * `delete` 74 | /// * For the `stytch.self` Resource: 75 | /// * `update.info.name` 76 | /// * `update.info.untrusted_metadata` 77 | /// * `update.info.mfa-phone` 78 | /// * `update.info.delete.mfa-phone` 79 | /// * `update.info.delete.password` 80 | /// * `update.settings.mfa_enrolled` 81 | /// * `delete` 82 | /// 83 | pub actions: std::vec::Vec, 84 | } 85 | /// PolicyRole: 86 | #[derive(Serialize, Deserialize, Debug, Clone)] 87 | pub struct PolicyRole { 88 | /// role_id: The unique identifier of the RBAC Role, provided by the developer and intended to be 89 | /// human-readable. 90 | /// 91 | /// Reserved `role_id`s that are predefined by Stytch include: 92 | /// 93 | /// * `stytch_member` 94 | /// * `stytch_admin` 95 | /// 96 | /// Check out the [guide on Stytch default Roles](https://stytch.com/docs/b2b/guides/rbac/stytch-default) 97 | /// for a more detailed explanation. 98 | /// 99 | /// 100 | pub role_id: String, 101 | /// description: The description of the RBAC Role. 102 | pub description: String, 103 | /// permissions: A list of permissions that link a 104 | /// [Resource](https://stytch.com/docs/b2b/api/rbac-resource-object) to a list of actions. 105 | pub permissions: std::vec::Vec, 106 | } 107 | /// PolicyRolePermission: 108 | #[derive(Serialize, Deserialize, Debug, Clone)] 109 | pub struct PolicyRolePermission { 110 | /// resource_id: A unique identifier of the RBAC Resource, provided by the developer and intended to be 111 | /// human-readable. 112 | /// 113 | /// A `resource_id` is not allowed to start with `stytch`, which is a special prefix used for Stytch 114 | /// default Resources with reserved `resource_id`s. These include: 115 | /// 116 | /// * `stytch.organization` 117 | /// * `stytch.member` 118 | /// * `stytch.sso` 119 | /// * `stytch.self` 120 | /// 121 | /// Check out the 122 | /// [guide on Stytch default Resources](https://stytch.com/docs/b2b/guides/rbac/stytch-default) for a more 123 | /// detailed explanation. 124 | /// 125 | /// 126 | pub resource_id: String, 127 | /// actions: A list of permitted actions the Scope is required to take with the provided Resource. You can 128 | /// use `*` as a wildcard to require a Scope permission to use all possible actions related to the Resource. 129 | pub actions: std::vec::Vec, 130 | } 131 | #[derive(Serialize, Deserialize, Debug, Clone)] 132 | pub struct PolicyScope { 133 | pub scope: String, 134 | pub description: String, 135 | pub permissions: std::vec::Vec, 136 | } 137 | #[derive(Serialize, Deserialize, Debug, Clone)] 138 | pub struct PolicyScopePermission { 139 | pub resource_id: String, 140 | pub actions: std::vec::Vec, 141 | } 142 | /// PolicyRequest: Request type for `RBAC.policy`. 143 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 144 | pub struct PolicyRequest {} 145 | /// PolicyResponse: Response type for `RBAC.policy`. 146 | #[derive(Serialize, Deserialize, Debug, Clone)] 147 | pub struct PolicyResponse { 148 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 149 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 150 | /// debug an issue. 151 | pub request_id: String, 152 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 153 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 154 | /// are server errors. 155 | #[serde(with = "http_serde::status_code")] 156 | pub status_code: http::StatusCode, 157 | /// policy: The RBAC Policy document that contains all defined Roles and Resources – which are managed in 158 | /// the [Dashboard](https://stytch.com/dashboard/rbac). Read more about these entities and how they work in 159 | /// our [RBAC overview](https://stytch.com/docs/b2b/guides/rbac/overview). 160 | pub policy: std::option::Option, 161 | } 162 | 163 | pub struct RBAC { 164 | http_client: crate::client::Client, 165 | } 166 | 167 | impl RBAC { 168 | pub fn new(http_client: crate::client::Client) -> Self { 169 | Self { 170 | http_client: http_client.clone(), 171 | } 172 | } 173 | 174 | pub async fn policy(&self, body: PolicyRequest) -> crate::Result { 175 | let path = format!( 176 | "/v1/b2b/rbac/policy?{}", 177 | serde_urlencoded::to_string(body).unwrap() 178 | ); 179 | self.http_client 180 | .send(crate::Request { 181 | method: http::Method::GET, 182 | path, 183 | body: serde_json::json!({}), 184 | }) 185 | .await 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/consumer/connected_apps.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::connected_apps_clients::Clients; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// ConnectedAppClient: 11 | #[derive(Serialize, Deserialize, Debug, Clone)] 12 | pub struct ConnectedAppClient { 13 | /// client_id: The ID of the Connected App client. 14 | pub client_id: String, 15 | /// client_name: A human-readable name for the client. 16 | pub client_name: String, 17 | /// client_description: A human-readable description for the client. 18 | pub client_description: String, 19 | pub status: String, 20 | /// full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to 21 | /// this Client can be exchanged for a full Stytch session. 22 | pub full_access_allowed: bool, 23 | /// client_type: The type of Connected App. Supported values are `first_party`, `first_party_public`, 24 | /// `third_party`, and `third_party_public`. 25 | pub client_type: String, 26 | /// redirect_urls: Array of redirect URI values for use in OAuth Authorization flows. 27 | pub redirect_urls: std::vec::Vec, 28 | pub access_token_expiry_minutes: i32, 29 | pub access_token_template_content: String, 30 | /// post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows. 31 | pub post_logout_redirect_urls: std::vec::Vec, 32 | /// bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need 33 | /// to request explicit user consent for the `offline_access` scope. 34 | pub bypass_consent_for_offline_access: bool, 35 | /// client_secret_last_four: The last four characters of the client secret. 36 | pub client_secret_last_four: std::option::Option, 37 | /// next_client_secret_last_four: The last four characters of the `next_client_secret`. Null if no 38 | /// `next_client_secret` exists. 39 | pub next_client_secret_last_four: std::option::Option, 40 | pub access_token_custom_audience: std::option::Option, 41 | /// logo_url: The logo URL of the Connected App, if any. 42 | pub logo_url: std::option::Option, 43 | pub client_id_metadata_url: std::option::Option, 44 | } 45 | #[derive(Serialize, Deserialize, Debug, Clone)] 46 | pub struct ConnectedAppPublic { 47 | pub client_id: String, 48 | pub client_name: String, 49 | pub client_description: String, 50 | pub client_type: String, 51 | pub logo_url: std::option::Option, 52 | } 53 | /// ConnectedAppWithClientSecret: 54 | #[derive(Serialize, Deserialize, Debug, Clone)] 55 | pub struct ConnectedAppWithClientSecret { 56 | /// client_id: The ID of the Connected App client. 57 | pub client_id: String, 58 | /// client_name: A human-readable name for the client. 59 | pub client_name: String, 60 | /// client_description: A human-readable description for the client. 61 | pub client_description: String, 62 | pub status: String, 63 | /// full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to 64 | /// this Client can be exchanged for a full Stytch session. 65 | pub full_access_allowed: bool, 66 | /// client_type: The type of Connected App. Supported values are `first_party`, `first_party_public`, 67 | /// `third_party`, and `third_party_public`. 68 | pub client_type: String, 69 | /// redirect_urls: Array of redirect URI values for use in OAuth Authorization flows. 70 | pub redirect_urls: std::vec::Vec, 71 | pub access_token_expiry_minutes: i32, 72 | pub access_token_template_content: String, 73 | /// post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows. 74 | pub post_logout_redirect_urls: std::vec::Vec, 75 | /// bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need 76 | /// to request explicit user consent for the `offline_access` scope. 77 | pub bypass_consent_for_offline_access: bool, 78 | /// client_secret_last_four: The last four characters of the client secret. 79 | pub client_secret_last_four: std::option::Option, 80 | /// next_client_secret_last_four: The last four characters of the `next_client_secret`. Null if no 81 | /// `next_client_secret` exists. 82 | pub next_client_secret_last_four: std::option::Option, 83 | /// client_secret: The secret of the Connected App client. **Required for confidential clients** 84 | pub client_secret: std::option::Option, 85 | pub access_token_custom_audience: std::option::Option, 86 | /// logo_url: The logo URL of the Connected App, if any. 87 | pub logo_url: std::option::Option, 88 | pub client_id_metadata_url: std::option::Option, 89 | } 90 | /// ConnectedAppWithNextClientSecret: 91 | #[derive(Serialize, Deserialize, Debug, Clone)] 92 | pub struct ConnectedAppWithNextClientSecret { 93 | /// client_id: The ID of the Connected App client. 94 | pub client_id: String, 95 | /// client_name: A human-readable name for the client. 96 | pub client_name: String, 97 | /// client_description: A human-readable description for the client. 98 | pub client_description: String, 99 | pub status: String, 100 | /// client_secret_last_four: The last four characters of the client secret. 101 | pub client_secret_last_four: String, 102 | /// full_access_allowed: Valid for first party clients only. If `true`, an authorization token granted to 103 | /// this Client can be exchanged for a full Stytch session. 104 | pub full_access_allowed: bool, 105 | /// client_type: The type of Connected App. Supported values are `first_party`, `first_party_public`, 106 | /// `third_party`, and `third_party_public`. 107 | pub client_type: String, 108 | /// redirect_urls: Array of redirect URI values for use in OAuth Authorization flows. 109 | pub redirect_urls: std::vec::Vec, 110 | pub next_client_secret: String, 111 | pub access_token_expiry_minutes: i32, 112 | pub access_token_template_content: String, 113 | /// post_logout_redirect_urls: Array of redirect URI values for use in OIDC Logout flows. 114 | pub post_logout_redirect_urls: std::vec::Vec, 115 | /// bypass_consent_for_offline_access: Valid for first party clients only. If true, the client does not need 116 | /// to request explicit user consent for the `offline_access` scope. 117 | pub bypass_consent_for_offline_access: bool, 118 | /// next_client_secret_last_four: The last four characters of the `next_client_secret`. Null if no 119 | /// `next_client_secret` exists. 120 | pub next_client_secret_last_four: std::option::Option, 121 | pub access_token_custom_audience: std::option::Option, 122 | /// logo_url: The logo URL of the Connected App, if any. 123 | pub logo_url: std::option::Option, 124 | pub client_id_metadata_url: std::option::Option, 125 | } 126 | /// ResultsMetadata: 127 | #[derive(Serialize, Deserialize, Debug, Clone)] 128 | pub struct ResultsMetadata { 129 | /// total: The total number of results returned by your search query. If totals have been disabled for your 130 | /// Stytch Workspace to improve search performance, the value will always be -1. 131 | pub total: i32, 132 | /// next_cursor: The `next_cursor` string is returned when your search result contains more than one page of 133 | /// results. This value is passed into your next search call in the `cursor` field. 134 | pub next_cursor: std::option::Option, 135 | } 136 | 137 | pub struct ConnectedApp { 138 | pub clients: Clients, 139 | } 140 | 141 | impl ConnectedApp { 142 | pub fn new(http_client: crate::client::Client) -> Self { 143 | Self { 144 | clients: Clients::new(http_client.clone()), 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/b2b/idp_oauth.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::idp::ScopeResult; 8 | use crate::b2b::organizations::Member; 9 | use crate::b2b::organizations::Organization; 10 | use crate::consumer::connected_apps::ConnectedAppPublic; 11 | use serde::{Deserialize, Serialize}; 12 | 13 | /// AuthorizeRequest: Request type for `OAuth.authorize`. 14 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 15 | pub struct AuthorizeRequest { 16 | /// consent_granted: Indicates whether the user granted the requested scopes. 17 | pub consent_granted: bool, 18 | /// scopes: An array of scopes requested by the client. 19 | pub scopes: std::vec::Vec, 20 | /// client_id: The ID of the Connected App client. 21 | pub client_id: String, 22 | /// redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI 23 | /// provided at the start of the OAuth flow. This field is required when using the `authorization_code` 24 | /// grant. 25 | pub redirect_uri: String, 26 | /// response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`. 27 | pub response_type: String, 28 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 29 | /// critical to perform operations on an Organization, so be sure to preserve this value. You may also use 30 | /// the organization_slug or organization_external_id here as a convenience. 31 | pub organization_id: std::option::Option, 32 | /// member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to 33 | /// perform operations on a Member, so be sure to preserve this value. You may use an external_id here if 34 | /// one is set for the member. 35 | pub member_id: std::option::Option, 36 | /// session_token: A secret token for a given Stytch Session. 37 | pub session_token: std::option::Option, 38 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 39 | pub session_jwt: std::option::Option, 40 | /// prompt: Space separated list that specifies how the Authorization Server should prompt the user for 41 | /// reauthentication and consent. Only `consent` is supported today. 42 | pub prompt: std::option::Option, 43 | /// state: An opaque value used to maintain state between the request and callback. 44 | pub state: std::option::Option, 45 | /// nonce: A string used to associate a client session with an ID token to mitigate replay attacks. 46 | pub nonce: std::option::Option, 47 | /// code_challenge: A base64url encoded challenge derived from the code verifier for PKCE flows. 48 | pub code_challenge: std::option::Option, 49 | pub resources: std::option::Option>, 50 | } 51 | /// AuthorizeResponse: Response type for `OAuth.authorize`. 52 | #[derive(Serialize, Deserialize, Debug, Clone)] 53 | pub struct AuthorizeResponse { 54 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 55 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 56 | /// debug an issue. 57 | pub request_id: String, 58 | /// redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI 59 | /// provided at the start of the OAuth flow. This field is required when using the `authorization_code` 60 | /// grant. 61 | pub redirect_uri: String, 62 | #[serde(with = "http_serde::status_code")] 63 | pub status_code: http::StatusCode, 64 | /// authorization_code: A one-time use code that can be exchanged for tokens. 65 | pub authorization_code: std::option::Option, 66 | } 67 | /// AuthorizeStartRequest: Request type for `OAuth.authorize_start`. 68 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 69 | pub struct AuthorizeStartRequest { 70 | /// client_id: The ID of the Connected App client. 71 | pub client_id: String, 72 | /// redirect_uri: The callback URI used to redirect the user after authentication. This is the same URI 73 | /// provided at the start of the OAuth flow. This field is required when using the `authorization_code` 74 | /// grant. 75 | pub redirect_uri: String, 76 | /// response_type: The OAuth 2.0 response type. For authorization code flows this value is `code`. 77 | pub response_type: String, 78 | /// scopes: An array of scopes requested by the client. 79 | pub scopes: std::vec::Vec, 80 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 81 | /// critical to perform operations on an Organization, so be sure to preserve this value. You may also use 82 | /// the organization_slug or organization_external_id here as a convenience. 83 | pub organization_id: std::option::Option, 84 | /// member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to 85 | /// perform operations on a Member, so be sure to preserve this value. You may use an external_id here if 86 | /// one is set for the member. 87 | pub member_id: std::option::Option, 88 | /// session_token: A secret token for a given Stytch Session. 89 | pub session_token: std::option::Option, 90 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 91 | pub session_jwt: std::option::Option, 92 | /// prompt: Space separated list that specifies how the Authorization Server should prompt the user for 93 | /// reauthentication and consent. Only `consent` is supported today. 94 | pub prompt: std::option::Option, 95 | } 96 | /// AuthorizeStartResponse: Response type for `OAuth.authorize_start`. 97 | #[derive(Serialize, Deserialize, Debug, Clone)] 98 | pub struct AuthorizeStartResponse { 99 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 100 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 101 | /// debug an issue. 102 | pub request_id: String, 103 | /// member_id: Globally unique UUID that identifies a specific Member. 104 | pub member_id: String, 105 | /// member: The [Member object](https://stytch.com/docs/b2b/api/member-object) 106 | pub member: Member, 107 | /// organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object). 108 | pub organization: Organization, 109 | pub client: ConnectedAppPublic, 110 | /// consent_required: Whether the user must provide explicit consent for the authorization request. 111 | pub consent_required: bool, 112 | /// scope_results: Details about each requested scope. 113 | pub scope_results: std::vec::Vec, 114 | #[serde(with = "http_serde::status_code")] 115 | pub status_code: http::StatusCode, 116 | } 117 | 118 | pub struct OAuth { 119 | http_client: crate::client::Client, 120 | } 121 | 122 | impl OAuth { 123 | pub fn new(http_client: crate::client::Client) -> Self { 124 | Self { 125 | http_client: http_client.clone(), 126 | } 127 | } 128 | 129 | pub async fn authorize_start( 130 | &self, 131 | body: AuthorizeStartRequest, 132 | ) -> crate::Result { 133 | let path = String::from("/v1/b2b/idp/oauth/authorize/start"); 134 | self.http_client 135 | .send(crate::Request { 136 | method: http::Method::POST, 137 | path, 138 | body, 139 | }) 140 | .await 141 | } 142 | pub async fn authorize(&self, body: AuthorizeRequest) -> crate::Result { 143 | let path = String::from("/v1/b2b/idp/oauth/authorize"); 144 | self.http_client 145 | .send(crate::Request { 146 | method: http::Method::POST, 147 | path, 148 | body, 149 | }) 150 | .await 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/b2b/sso_external.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::sso::Connection; 8 | use crate::b2b::sso::ConnectionImplicitRoleAssignment; 9 | use crate::b2b::sso::GroupImplicitRoleAssignment; 10 | use crate::b2b::sso::SAMLConnectionImplicitRoleAssignment; 11 | use crate::b2b::sso::SAMLGroupImplicitRoleAssignment; 12 | use percent_encoding; 13 | use serde::{Deserialize, Serialize}; 14 | 15 | /// CreateConnectionRequest: Request type for `External.create_connection`. 16 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 17 | pub struct CreateConnectionRequest { 18 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 19 | /// critical to perform operations on an Organization, so be sure to preserve this value. You may also use 20 | /// the organization_slug or organization_external_id here as a convenience. 21 | pub organization_id: String, 22 | /// external_organization_id: Globally unique UUID that identifies a different Organization within your 23 | /// Project. 24 | pub external_organization_id: String, 25 | /// external_connection_id: Globally unique UUID that identifies a specific SSO connection configured for a 26 | /// different Organization in your Project. 27 | pub external_connection_id: String, 28 | /// display_name: A human-readable display name for the connection. 29 | pub display_name: std::option::Option, 30 | pub connection_implicit_role_assignments: 31 | std::option::Option>, 32 | pub group_implicit_role_assignments: 33 | std::option::Option>, 34 | } 35 | /// CreateConnectionResponse: Response type for `External.create_connection`. 36 | #[derive(Serialize, Deserialize, Debug, Clone)] 37 | pub struct CreateConnectionResponse { 38 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 39 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 40 | /// debug an issue. 41 | pub request_id: String, 42 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 43 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 44 | /// are server errors. 45 | #[serde(with = "http_serde::status_code")] 46 | pub status_code: http::StatusCode, 47 | /// connection: The `External Connection` object affected by this API call. See the 48 | /// [External Connection Object](https://stytch.com/docs/b2b/api/external-connection-object) for complete 49 | /// response field details. 50 | pub connection: std::option::Option, 51 | } 52 | /// UpdateConnectionRequest: Request type for `External.update_connection`. 53 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 54 | pub struct UpdateConnectionRequest { 55 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 56 | /// critical to perform operations on an Organization, so be sure to preserve this value. You may also use 57 | /// the organization_slug or organization_external_id here as a convenience. 58 | pub organization_id: String, 59 | /// connection_id: Globally unique UUID that identifies a specific External SSO Connection. 60 | pub connection_id: String, 61 | /// display_name: A human-readable display name for the connection. 62 | pub display_name: std::option::Option, 63 | /// external_connection_implicit_role_assignments: All Members who log in with this External connection will 64 | /// implicitly receive the specified Roles. See the 65 | /// [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role 66 | /// assignment. Implicit role assignments are not supported for External connections if the underlying SSO 67 | /// connection is an OIDC connection. 68 | pub external_connection_implicit_role_assignments: 69 | std::option::Option>, 70 | /// external_group_implicit_role_assignments: Defines the names of the groups 71 | /// that grant specific role assignments. For each group-Role pair, if a Member logs in with this external 72 | /// connection and 73 | /// belongs to the specified group, they will be granted the associated Role. See the 74 | /// [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role 75 | /// assignment. Before adding any group implicit role assignments to an external connection, you must add a 76 | /// "groups" key to the underlying SAML connection's 77 | /// `attribute_mapping`. Make sure that the SAML connection IdP is configured to correctly send the group 78 | /// information. Implicit role assignments are not supported 79 | /// for External connections if the underlying SSO connection is an OIDC connection. 80 | pub external_group_implicit_role_assignments: 81 | std::option::Option>, 82 | } 83 | /// UpdateConnectionResponse: Response type for `External.update_connection`. 84 | #[derive(Serialize, Deserialize, Debug, Clone)] 85 | pub struct UpdateConnectionResponse { 86 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 87 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 88 | /// debug an issue. 89 | pub request_id: String, 90 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 91 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 92 | /// are server errors. 93 | #[serde(with = "http_serde::status_code")] 94 | pub status_code: http::StatusCode, 95 | /// connection: The `External Connection` object affected by this API call. See the 96 | /// [External Connection Object](https://stytch.com/docs/b2b/api/external-connection-object) for complete 97 | /// response field details. 98 | pub connection: std::option::Option, 99 | } 100 | 101 | pub struct External { 102 | http_client: crate::client::Client, 103 | } 104 | 105 | impl External { 106 | pub fn new(http_client: crate::client::Client) -> Self { 107 | Self { 108 | http_client: http_client.clone(), 109 | } 110 | } 111 | 112 | pub async fn create_connection( 113 | &self, 114 | body: CreateConnectionRequest, 115 | ) -> crate::Result { 116 | let organization_id = percent_encoding::utf8_percent_encode( 117 | &body.organization_id, 118 | percent_encoding::NON_ALPHANUMERIC, 119 | ) 120 | .to_string(); 121 | let path = format!("/v1/b2b/sso/external/{organization_id}"); 122 | self.http_client 123 | .send(crate::Request { 124 | method: http::Method::POST, 125 | path, 126 | body, 127 | }) 128 | .await 129 | } 130 | pub async fn update_connection( 131 | &self, 132 | body: UpdateConnectionRequest, 133 | ) -> crate::Result { 134 | let organization_id = percent_encoding::utf8_percent_encode( 135 | &body.organization_id, 136 | percent_encoding::NON_ALPHANUMERIC, 137 | ) 138 | .to_string(); 139 | let connection_id = percent_encoding::utf8_percent_encode( 140 | &body.connection_id, 141 | percent_encoding::NON_ALPHANUMERIC, 142 | ) 143 | .to_string(); 144 | let path = format!("/v1/b2b/sso/external/{organization_id}/connections/{connection_id}"); 145 | self.http_client 146 | .send(crate::Request { 147 | method: http::Method::PUT, 148 | path, 149 | body, 150 | }) 151 | .await 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/consumer/otp_sms.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::attribute::Attributes; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// LoginOrCreateRequest: Request type for `Sms.login_or_create`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct LoginOrCreateRequest { 13 | /// phone_number: The phone number to use for one-time passcodes. The phone number should be in E.164 format 14 | /// (i.e. +1XXXXXXXXXX). You may use +10000000000 to test this endpoint, see 15 | /// [Testing](https://stytch.com/docs/home#resources_testing) for more detail. 16 | pub phone_number: String, 17 | /// expiration_minutes: Set the expiration for the one-time passcode, in minutes. The minimum expiration is 18 | /// 1 minute and the maximum is 10 minutes. The default expiration is 2 minutes. 19 | pub expiration_minutes: std::option::Option, 20 | /// attributes: Provided attributes to help with fraud detection. These values are pulled and passed into 21 | /// Stytch endpoints by your application. 22 | pub attributes: std::option::Option, 23 | /// create_user_as_pending: Flag for whether or not to save a user as pending vs active in Stytch. Defaults 24 | /// to false. 25 | /// If true, users will be saved with status pending in Stytch's backend until authenticated. 26 | /// If false, users will be created as active. An example usage of 27 | /// a true flag would be to require users to verify their phone by entering the OTP code before creating 28 | /// an account for them. 29 | pub create_user_as_pending: std::option::Option, 30 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 31 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 32 | /// 33 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 34 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 35 | /// 36 | /// Request support for additional languages 37 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 38 | /// 39 | pub locale: std::option::Option, 40 | } 41 | /// LoginOrCreateResponse: Response type for `Sms.login_or_create`. 42 | #[derive(Serialize, Deserialize, Debug, Clone)] 43 | pub struct LoginOrCreateResponse { 44 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 45 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 46 | /// debug an issue. 47 | pub request_id: String, 48 | /// user_id: The unique ID of the affected User. 49 | pub user_id: String, 50 | /// phone_id: The unique ID for the phone number. 51 | pub phone_id: String, 52 | /// user_created: In `login_or_create` endpoints, this field indicates whether or not a User was just 53 | /// created. 54 | pub user_created: bool, 55 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 56 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 57 | /// are server errors. 58 | #[serde(with = "http_serde::status_code")] 59 | pub status_code: http::StatusCode, 60 | } 61 | /// SendRequest: Request type for `Sms.send`. 62 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 63 | pub struct SendRequest { 64 | /// phone_number: The phone number to use for one-time passcodes. The phone number should be in E.164 format 65 | /// (i.e. +1XXXXXXXXXX). You may use +10000000000 to test this endpoint, see 66 | /// [Testing](https://stytch.com/docs/home#resources_testing) for more detail. 67 | pub phone_number: String, 68 | /// expiration_minutes: Set the expiration for the one-time passcode, in minutes. The minimum expiration is 69 | /// 1 minute and the maximum is 10 minutes. The default expiration is 2 minutes. 70 | pub expiration_minutes: std::option::Option, 71 | /// attributes: Provided attributes to help with fraud detection. These values are pulled and passed into 72 | /// Stytch endpoints by your application. 73 | pub attributes: std::option::Option, 74 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 75 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 76 | /// 77 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 78 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 79 | /// 80 | /// Request support for additional languages 81 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 82 | /// 83 | pub locale: std::option::Option, 84 | /// user_id: The unique ID of a specific User. You may use an `external_id` here if one is set for the user. 85 | pub user_id: std::option::Option, 86 | /// session_token: The `session_token` associated with a User's existing Session. 87 | pub session_token: std::option::Option, 88 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 89 | pub session_jwt: std::option::Option, 90 | } 91 | /// SendResponse: Response type for `Sms.send`. 92 | #[derive(Serialize, Deserialize, Debug, Clone)] 93 | pub struct SendResponse { 94 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 95 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 96 | /// debug an issue. 97 | pub request_id: String, 98 | /// user_id: The unique ID of the affected User. 99 | pub user_id: String, 100 | /// phone_id: The unique ID for the phone number. 101 | pub phone_id: String, 102 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 103 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 104 | /// are server errors. 105 | #[serde(with = "http_serde::status_code")] 106 | pub status_code: http::StatusCode, 107 | } 108 | 109 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 110 | pub enum LoginOrCreateRequestLocale { 111 | #[serde(rename = "en")] 112 | #[default] 113 | En, 114 | #[serde(rename = "es")] 115 | Es, 116 | #[serde(rename = "ptbr")] 117 | Ptbr, 118 | #[serde(rename = "fr")] 119 | Fr, 120 | #[serde(rename = "it")] 121 | It, 122 | #[serde(rename = "deDE")] 123 | DeDE, 124 | #[serde(rename = "zhHans")] 125 | ZhHans, 126 | #[serde(rename = "caES")] 127 | CaES, 128 | } 129 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 130 | pub enum SendRequestLocale { 131 | #[serde(rename = "en")] 132 | #[default] 133 | En, 134 | #[serde(rename = "es")] 135 | Es, 136 | #[serde(rename = "ptbr")] 137 | Ptbr, 138 | #[serde(rename = "fr")] 139 | Fr, 140 | #[serde(rename = "it")] 141 | It, 142 | #[serde(rename = "deDE")] 143 | DeDE, 144 | #[serde(rename = "zhHans")] 145 | ZhHans, 146 | #[serde(rename = "caES")] 147 | CaES, 148 | } 149 | 150 | pub struct Sms { 151 | http_client: crate::client::Client, 152 | } 153 | 154 | impl Sms { 155 | pub fn new(http_client: crate::client::Client) -> Self { 156 | Self { 157 | http_client: http_client.clone(), 158 | } 159 | } 160 | 161 | pub async fn send(&self, body: SendRequest) -> crate::Result { 162 | let path = String::from("/v1/otps/sms/send"); 163 | self.http_client 164 | .send(crate::Request { 165 | method: http::Method::POST, 166 | path, 167 | body, 168 | }) 169 | .await 170 | } 171 | pub async fn login_or_create( 172 | &self, 173 | body: LoginOrCreateRequest, 174 | ) -> crate::Result { 175 | let path = String::from("/v1/otps/sms/login_or_create"); 176 | self.http_client 177 | .send(crate::Request { 178 | method: http::Method::POST, 179 | path, 180 | body, 181 | }) 182 | .await 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/b2b/passwords_session.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::mfa::MfaRequired; 8 | use crate::b2b::organizations::Member; 9 | use crate::b2b::organizations::Organization; 10 | use crate::b2b::sessions::MemberSession; 11 | use crate::consumer::device_history::DeviceInfo; 12 | use serde::{Deserialize, Serialize}; 13 | 14 | /// ResetRequest: Request type for `Sessions.reset`. 15 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 16 | pub struct ResetRequest { 17 | /// organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is 18 | /// critical to perform operations on an Organization, so be sure to preserve this value. You may also use 19 | /// the organization_slug or organization_external_id here as a convenience. 20 | pub organization_id: String, 21 | /// password: The password to authenticate, reset, or set for the first time. Any UTF8 character is allowed, 22 | /// e.g. spaces, emojis, non-English characters, etc. 23 | pub password: String, 24 | /// session_token: A secret token for a given Stytch Session. 25 | pub session_token: std::option::Option, 26 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 27 | pub session_jwt: std::option::Option, 28 | /// session_duration_minutes: Set the session lifetime to be this many minutes from now. This will start a 29 | /// new session if one doesn't already exist, 30 | /// returning both an opaque `session_token` and `session_jwt` for this session. Remember that the 31 | /// `session_jwt` will have a fixed lifetime of 32 | /// five minutes regardless of the underlying session duration, and will need to be refreshed over time. 33 | /// 34 | /// This value must be a minimum of 5 and a maximum of 527040 minutes (366 days). 35 | /// 36 | /// If a `session_token` or `session_jwt` is provided then a successful authentication will continue to 37 | /// extend the session this many minutes. 38 | /// 39 | /// If the `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 40 | /// 60 minute duration. If you don't want 41 | /// to use the Stytch session product, you can ignore the session fields in the response. 42 | pub session_duration_minutes: std::option::Option, 43 | /// session_custom_claims: Add a custom claims map to the Session being authenticated. Claims are only 44 | /// created if a Session is initialized by providing a value in 45 | /// `session_duration_minutes`. Claims will be included on the Session object and in the JWT. To update a 46 | /// key in an existing Session, supply a new value. To 47 | /// delete a key, supply a null value. Custom claims made with reserved claims (`iss`, `sub`, `aud`, 48 | /// `exp`, `nbf`, `iat`, `jti`) will be ignored. 49 | /// Total custom claims size cannot exceed four kilobytes. 50 | pub session_custom_claims: std::option::Option, 51 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 52 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 53 | /// 54 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 55 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 56 | /// 57 | /// Request support for additional languages 58 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 59 | /// 60 | pub locale: std::option::Option, 61 | /// telemetry_id: If the `telemetry_id` is passed, as part of this request, Stytch will call the 62 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) and store the associated 63 | /// fingerprints and IPGEO information for the Member. Your workspace must be enabled for Device 64 | /// Fingerprinting to use this feature. 65 | pub telemetry_id: std::option::Option, 66 | } 67 | /// ResetResponse: Response type for `Sessions.reset`. 68 | #[derive(Serialize, Deserialize, Debug, Clone)] 69 | pub struct ResetResponse { 70 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 71 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 72 | /// debug an issue. 73 | pub request_id: String, 74 | /// member_id: Globally unique UUID that identifies a specific Member. 75 | pub member_id: String, 76 | /// member: The [Member object](https://stytch.com/docs/b2b/api/member-object) 77 | pub member: Member, 78 | /// organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object). 79 | pub organization: Organization, 80 | /// session_token: A secret token for a given Stytch Session. 81 | pub session_token: String, 82 | /// session_jwt: The JSON Web Token (JWT) for a given Stytch Session. 83 | pub session_jwt: String, 84 | /// intermediate_session_token: The Intermediate Session Token. This token does not necessarily belong to a 85 | /// specific instance of a Member, but represents a bag of factors that may be converted to a member 86 | /// session. The token can be used with the 87 | /// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms), 88 | /// [TOTP Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-totp), or 89 | /// [Recovery Codes Recover endpoint](https://stytch.com/docs/b2b/api/recovery-codes-recover) to complete an 90 | /// MFA flow and log in to the Organization. The token has a default expiry of 10 minutes. It can also be 91 | /// used with the 92 | /// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session) 93 | /// to join a specific Organization that allows the factors represented by the intermediate session token; 94 | /// or the 95 | /// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member. Intermediate Session Tokens have a default expiry of 10 minutes. 96 | pub intermediate_session_token: String, 97 | /// member_authenticated: Indicates whether the Member is fully authenticated. If false, the Member needs to 98 | /// complete an MFA step to log in to the Organization. 99 | pub member_authenticated: bool, 100 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 101 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 102 | /// are server errors. 103 | #[serde(with = "http_serde::status_code")] 104 | pub status_code: http::StatusCode, 105 | /// member_session: The [Session object](https://stytch.com/docs/b2b/api/session-object). 106 | pub member_session: std::option::Option, 107 | /// mfa_required: Information about the MFA requirements of the Organization and the Member's options for 108 | /// fulfilling MFA. 109 | pub mfa_required: std::option::Option, 110 | /// member_device: If a valid `telemetry_id` was passed in the request and the 111 | /// [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) returned results, the 112 | /// `member_device` response field will contain information about the member's device attributes. 113 | pub member_device: std::option::Option, 114 | } 115 | 116 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 117 | pub enum ResetRequestLocale { 118 | #[serde(rename = "en")] 119 | #[default] 120 | En, 121 | #[serde(rename = "es")] 122 | Es, 123 | #[serde(rename = "ptbr")] 124 | Ptbr, 125 | #[serde(rename = "fr")] 126 | Fr, 127 | } 128 | 129 | pub struct Sessions { 130 | http_client: crate::client::Client, 131 | } 132 | 133 | impl Sessions { 134 | pub fn new(http_client: crate::client::Client) -> Self { 135 | Self { 136 | http_client: http_client.clone(), 137 | } 138 | } 139 | 140 | pub async fn reset(&self, body: ResetRequest) -> crate::Result { 141 | let path = String::from("/v1/b2b/passwords/session/reset"); 142 | self.http_client 143 | .send(crate::Request { 144 | method: http::Method::POST, 145 | path, 146 | body, 147 | }) 148 | .await 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/consumer/otp_whatsapp.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::attribute::Attributes; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// LoginOrCreateRequest: Request type for `Whatsapp.login_or_create`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct LoginOrCreateRequest { 13 | /// phone_number: The phone number to use for one-time passcodes. The phone number should be in E.164 format 14 | /// (i.e. +1XXXXXXXXXX). You may use +10000000000 to test this endpoint, see 15 | /// [Testing](https://stytch.com/docs/home#resources_testing) for more detail. 16 | pub phone_number: String, 17 | /// expiration_minutes: Set the expiration for the one-time passcode, in minutes. The minimum expiration is 18 | /// 1 minute and the maximum is 10 minutes. The default expiration is 2 minutes. 19 | pub expiration_minutes: std::option::Option, 20 | /// attributes: Provided attributes to help with fraud detection. These values are pulled and passed into 21 | /// Stytch endpoints by your application. 22 | pub attributes: std::option::Option, 23 | /// create_user_as_pending: Flag for whether or not to save a user as pending vs active in Stytch. Defaults 24 | /// to false. 25 | /// If true, users will be saved with status pending in Stytch's backend until authenticated. 26 | /// If false, users will be created as active. An example usage of 27 | /// a true flag would be to require users to verify their phone by entering the OTP code before creating 28 | /// an account for them. 29 | pub create_user_as_pending: std::option::Option, 30 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 31 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 32 | /// 33 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 34 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 35 | /// 36 | /// Request support for additional languages 37 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 38 | /// 39 | pub locale: std::option::Option, 40 | } 41 | /// LoginOrCreateResponse: Response type for `Whatsapp.login_or_create`. 42 | #[derive(Serialize, Deserialize, Debug, Clone)] 43 | pub struct LoginOrCreateResponse { 44 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 45 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 46 | /// debug an issue. 47 | pub request_id: String, 48 | /// user_id: The unique ID of the affected User. 49 | pub user_id: String, 50 | /// phone_id: The unique ID for the phone number. 51 | pub phone_id: String, 52 | /// user_created: In `login_or_create` endpoints, this field indicates whether or not a User was just 53 | /// created. 54 | pub user_created: bool, 55 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 56 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 57 | /// are server errors. 58 | #[serde(with = "http_serde::status_code")] 59 | pub status_code: http::StatusCode, 60 | } 61 | /// SendRequest: Request type for `Whatsapp.send`. 62 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 63 | pub struct SendRequest { 64 | /// phone_number: The phone number to use for one-time passcodes. The phone number should be in E.164 format 65 | /// (i.e. +1XXXXXXXXXX). You may use +10000000000 to test this endpoint, see 66 | /// [Testing](https://stytch.com/docs/home#resources_testing) for more detail. 67 | pub phone_number: String, 68 | /// expiration_minutes: Set the expiration for the one-time passcode, in minutes. The minimum expiration is 69 | /// 1 minute and the maximum is 10 minutes. The default expiration is 2 minutes. 70 | pub expiration_minutes: std::option::Option, 71 | /// attributes: Provided attributes to help with fraud detection. These values are pulled and passed into 72 | /// Stytch endpoints by your application. 73 | pub attributes: std::option::Option, 74 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 75 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 76 | /// 77 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 78 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 79 | /// 80 | /// Request support for additional languages 81 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 82 | /// 83 | pub locale: std::option::Option, 84 | /// user_id: The unique ID of a specific User. You may use an `external_id` here if one is set for the user. 85 | pub user_id: std::option::Option, 86 | /// session_token: The `session_token` associated with a User's existing Session. 87 | pub session_token: std::option::Option, 88 | /// session_jwt: The `session_jwt` associated with a User's existing Session. 89 | pub session_jwt: std::option::Option, 90 | } 91 | /// SendResponse: Response type for `Whatsapp.send`. 92 | #[derive(Serialize, Deserialize, Debug, Clone)] 93 | pub struct SendResponse { 94 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 95 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 96 | /// debug an issue. 97 | pub request_id: String, 98 | /// user_id: The unique ID of the affected User. 99 | pub user_id: String, 100 | /// phone_id: The unique ID for the phone number. 101 | pub phone_id: String, 102 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 103 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 104 | /// are server errors. 105 | #[serde(with = "http_serde::status_code")] 106 | pub status_code: http::StatusCode, 107 | } 108 | 109 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 110 | pub enum LoginOrCreateRequestLocale { 111 | #[serde(rename = "en")] 112 | #[default] 113 | En, 114 | #[serde(rename = "es")] 115 | Es, 116 | #[serde(rename = "ptbr")] 117 | Ptbr, 118 | #[serde(rename = "fr")] 119 | Fr, 120 | #[serde(rename = "it")] 121 | It, 122 | #[serde(rename = "deDE")] 123 | DeDE, 124 | #[serde(rename = "zhHans")] 125 | ZhHans, 126 | #[serde(rename = "caES")] 127 | CaES, 128 | } 129 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 130 | pub enum SendRequestLocale { 131 | #[serde(rename = "en")] 132 | #[default] 133 | En, 134 | #[serde(rename = "es")] 135 | Es, 136 | #[serde(rename = "ptbr")] 137 | Ptbr, 138 | #[serde(rename = "fr")] 139 | Fr, 140 | #[serde(rename = "it")] 141 | It, 142 | #[serde(rename = "deDE")] 143 | DeDE, 144 | #[serde(rename = "zhHans")] 145 | ZhHans, 146 | #[serde(rename = "caES")] 147 | CaES, 148 | } 149 | 150 | pub struct Whatsapp { 151 | http_client: crate::client::Client, 152 | } 153 | 154 | impl Whatsapp { 155 | pub fn new(http_client: crate::client::Client) -> Self { 156 | Self { 157 | http_client: http_client.clone(), 158 | } 159 | } 160 | 161 | pub async fn send(&self, body: SendRequest) -> crate::Result { 162 | let path = String::from("/v1/otps/whatsapp/send"); 163 | self.http_client 164 | .send(crate::Request { 165 | method: http::Method::POST, 166 | path, 167 | body, 168 | }) 169 | .await 170 | } 171 | pub async fn login_or_create( 172 | &self, 173 | body: LoginOrCreateRequest, 174 | ) -> crate::Result { 175 | let path = String::from("/v1/otps/whatsapp/login_or_create"); 176 | self.http_client 177 | .send(crate::Request { 178 | method: http::Method::POST, 179 | path, 180 | body, 181 | }) 182 | .await 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/consumer/fraud_rules.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::consumer::fraud::Rule; 8 | use crate::consumer::fraud::RuleAction; 9 | use serde::{Deserialize, Serialize}; 10 | 11 | /// ListRequest: Request type for `Rules.list`. 12 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 13 | pub struct ListRequest { 14 | /// cursor: The `cursor` field allows you to paginate through your results. Each result array is limited to 15 | /// 100 results. If your query returns more than 100 results, you will need to paginate the responses using 16 | /// the `cursor`. If you receive a response that includes a non-null `next_cursor`, repeat the request with 17 | /// the `next_cursor` value set to the `cursor` field to retrieve the next page of results. Continue to make 18 | /// requests until the `next_cursor` in the response is null. 19 | pub cursor: std::option::Option, 20 | /// limit: The number of results to return per page. The default limit is 10. A maximum of 100 results can 21 | /// be returned by a single get request. If the total size of your result set is greater than one page size, 22 | /// you must paginate the response. See the `cursor` field. 23 | pub limit: std::option::Option, 24 | } 25 | /// ListResponse: Response type for `Rules.list`. 26 | #[derive(Serialize, Deserialize, Debug, Clone)] 27 | pub struct ListResponse { 28 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 29 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 30 | /// debug an issue. 31 | pub request_id: String, 32 | /// next_cursor: The `next_cursor` string is returned when your result contains more than one page of 33 | /// results. This value is passed into your next request in the `cursor` field. 34 | pub next_cursor: String, 35 | /// rules: A list of rules for the project 36 | pub rules: std::vec::Vec, 37 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 38 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 39 | /// are server errors. 40 | #[serde(with = "http_serde::status_code")] 41 | pub status_code: http::StatusCode, 42 | } 43 | /// SetRequest: Request type for `Rules.set`. 44 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 45 | pub struct SetRequest { 46 | /// action: The action that should be returned by a fingerprint lookup for that identifier with a 47 | /// `RULE_MATCH` reason. The following values are valid: `ALLOW`, `BLOCK`, `CHALLENGE`, or `NONE`. For 48 | /// country codes, `ALLOW` actions are not allowed. If a `NONE` action is specified, it will clear the 49 | /// stored rule. 50 | pub action: RuleAction, 51 | /// visitor_id: The visitor ID we want to set a rule for. Only one identifier can be specified in the 52 | /// request. 53 | pub visitor_id: std::option::Option, 54 | /// browser_id: The browser ID we want to set a rule for. Only one identifier can be specified in the 55 | /// request. 56 | pub browser_id: std::option::Option, 57 | /// visitor_fingerprint: The visitor fingerprint we want to set a rule for. Only one identifier can be 58 | /// specified in the request. 59 | pub visitor_fingerprint: std::option::Option, 60 | /// browser_fingerprint: The browser fingerprint we want to set a rule for. Only one identifier can be 61 | /// specified in the request. 62 | pub browser_fingerprint: std::option::Option, 63 | /// hardware_fingerprint: The hardware fingerprint we want to set a rule for. Only one identifier can be 64 | /// specified in the request. 65 | pub hardware_fingerprint: std::option::Option, 66 | /// network_fingerprint: The network fingerprint we want to set a rule for. Only one identifier can be 67 | /// specified in the request. 68 | pub network_fingerprint: std::option::Option, 69 | /// expires_in_minutes: The number of minutes until this rule expires. If no `expires_in_minutes` is 70 | /// specified, then the rule is kept permanently. 71 | pub expires_in_minutes: std::option::Option, 72 | /// description: An optional description for the rule. 73 | pub description: std::option::Option, 74 | /// cidr_block: The CIDR block we want to set a rule for. You may pass either an IP address or a CIDR block. 75 | /// The CIDR block prefix must be between 16 and 32, inclusive. If an end user's IP address is within this 76 | /// CIDR block, this rule will be applied. Only one identifier can be specified in the request. 77 | pub cidr_block: std::option::Option, 78 | /// country_code: The country code we want to set a rule for. The country code must be a valid ISO 3166-1 79 | /// alpha-2 code. You may not set `ALLOW` rules for country codes. Only one identifier can be specified in 80 | /// the request. 81 | pub country_code: std::option::Option, 82 | /// asn: The ASN we want to set a rule for. The ASN must be the string representation of an integer between 83 | /// 0 and 4294967295, inclusive. Only one identifier can be specified in the request. 84 | pub asn: std::option::Option, 85 | } 86 | /// SetResponse: Response type for `Rules.set`. 87 | #[derive(Serialize, Deserialize, Debug, Clone)] 88 | pub struct SetResponse { 89 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 90 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 91 | /// debug an issue. 92 | pub request_id: String, 93 | /// action: The action that will be returned for the specified identifier. 94 | pub action: RuleAction, 95 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 96 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 97 | /// are server errors. 98 | #[serde(with = "http_serde::status_code")] 99 | pub status_code: http::StatusCode, 100 | /// visitor_id: The visitor ID that a rule was set for. 101 | pub visitor_id: std::option::Option, 102 | /// browser_id: The browser ID that a rule was set for. 103 | pub browser_id: std::option::Option, 104 | /// visitor_fingerprint: The visitor fingerprint that a rule was set for. 105 | pub visitor_fingerprint: std::option::Option, 106 | /// browser_fingerprint: The browser fingerprint that a rule was set for. 107 | pub browser_fingerprint: std::option::Option, 108 | /// hardware_fingerprint: The hardware fingerprint that a rule was set for. 109 | pub hardware_fingerprint: std::option::Option, 110 | /// network_fingerprint: The network fingerprint that a rule was set for. 111 | pub network_fingerprint: std::option::Option, 112 | /// expires_at: The timestamp when the rule expires. Values conform to the RFC 3339 standard and are 113 | /// expressed in UTC, e.g. `2021-12-29T12:33:09Z`. 114 | pub expires_at: std::option::Option>, 115 | /// cidr_block: The CIDR block that a rule was set for. If an end user's IP address is within this CIDR 116 | /// block, this rule will be applied. 117 | pub cidr_block: std::option::Option, 118 | /// country_code: The country code that a rule was set for. 119 | pub country_code: std::option::Option, 120 | /// asn: The ASN that a rule was set for. 121 | pub asn: std::option::Option, 122 | } 123 | 124 | pub struct Rules { 125 | http_client: crate::client::Client, 126 | } 127 | 128 | impl Rules { 129 | pub fn new(http_client: crate::client::Client) -> Self { 130 | Self { 131 | http_client: http_client.clone(), 132 | } 133 | } 134 | 135 | pub async fn set(&self, body: SetRequest) -> crate::Result { 136 | let path = String::from("/v1/rules/set"); 137 | self.http_client 138 | .send(crate::Request { 139 | method: http::Method::POST, 140 | path, 141 | body, 142 | }) 143 | .await 144 | } 145 | pub async fn list(&self, body: ListRequest) -> crate::Result { 146 | let path = String::from("/v1/rules/list"); 147 | self.http_client 148 | .send(crate::Request { 149 | method: http::Method::POST, 150 | path, 151 | body, 152 | }) 153 | .await 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/b2b/passwords_discovery_email.rs: -------------------------------------------------------------------------------- 1 | // !!! 2 | // WARNING: This file is autogenerated 3 | // Only modify code within MANUAL() sections 4 | // or your changes may be overwritten later! 5 | // !!! 6 | 7 | use crate::b2b::discovery::DiscoveredOrganization; 8 | use serde::{Deserialize, Serialize}; 9 | 10 | /// ResetRequest: Request type for `Email.reset`. 11 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 12 | pub struct ResetRequest { 13 | /// password_reset_token: The password reset token to authenticate. 14 | pub password_reset_token: String, 15 | /// password: The password to authenticate, reset, or set for the first time. Any UTF8 character is allowed, 16 | /// e.g. spaces, emojis, non-English characters, etc. 17 | pub password: String, 18 | pub pkce_code_verifier: std::option::Option, 19 | } 20 | /// ResetResponse: Response type for `Email.reset`. 21 | #[derive(Serialize, Deserialize, Debug, Clone)] 22 | pub struct ResetResponse { 23 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 24 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 25 | /// debug an issue. 26 | pub request_id: String, 27 | /// intermediate_session_token: The returned Intermediate Session Token contains a password factor 28 | /// associated with the Member. If this value is non-empty, the member must complete an MFA step to finish 29 | /// logging in to the Organization. The token can be used with the 30 | /// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms), 31 | /// [TOTP Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-totp), or 32 | /// [Recovery Codes Recover endpoint](https://stytch.com/docs/b2b/api/recovery-codes-recover) to complete an 33 | /// MFA flow and log in to the Organization. The token has a default expiry of 10 minutes. Password factors 34 | /// are not transferable between Organizations, so the intermediate session token is not valid for use with 35 | /// discovery endpoints. 36 | pub intermediate_session_token: String, 37 | /// email_address: The email address. 38 | pub email_address: String, 39 | /// discovered_organizations: An array of `discovered_organization` objects tied to the 40 | /// `intermediate_session_token`, `session_token`, or `session_jwt`. See the 41 | /// [Discovered Organization Object](https://stytch.com/docs/b2b/api/discovered-organization-object) for 42 | /// complete details. 43 | /// 44 | /// Note that Organizations will only appear here under any of the following conditions: 45 | /// 1. The end user is already a Member of the Organization. 46 | /// 2. The end user is invited to the Organization. 47 | /// 3. The end user can join the Organization because: 48 | /// 49 | /// a) The Organization allows JIT provisioning. 50 | /// 51 | /// b) The Organizations' allowed domains list contains the Member's email domain. 52 | /// 53 | /// c) The Organization has at least one other Member with a verified email address with the same domain 54 | /// as the end user (to prevent phishing attacks). 55 | pub discovered_organizations: std::vec::Vec, 56 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 57 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 58 | /// are server errors. 59 | #[serde(with = "http_serde::status_code")] 60 | pub status_code: http::StatusCode, 61 | } 62 | /// ResetStartRequest: Request type for `Email.reset_start`. 63 | #[derive(Serialize, Deserialize, Debug, Clone, Default)] 64 | pub struct ResetStartRequest { 65 | /// email_address: The email address of the Member to start the email reset process for. 66 | pub email_address: String, 67 | /// reset_password_redirect_url: The URL that the Member clicks from the reset password link. This URL 68 | /// should be an endpoint in the backend server that verifies the request by querying 69 | /// Stytch's authenticate endpoint and finishes the reset password flow. If this value is not passed, the 70 | /// default `reset_password_redirect_url` that you set in your Dashboard is used. 71 | /// If you have not set a default `reset_password_redirect_url`, an error is returned. 72 | pub reset_password_redirect_url: std::option::Option, 73 | /// discovery_redirect_url: The URL that the end user clicks from the discovery Magic Link. This URL should 74 | /// be an endpoint in the backend server that 75 | /// verifies the request by querying Stytch's discovery authenticate endpoint and continues the flow. If 76 | /// this value is not passed, the default 77 | /// discovery redirect URL that you set in your Dashboard is used. If you have not set a default discovery 78 | /// redirect URL, an error is returned. 79 | pub discovery_redirect_url: std::option::Option, 80 | /// reset_password_template_id: Use a custom template for reset password emails. By default, it will use 81 | /// your default email template. The template must be a template using our built-in customizations or a 82 | /// custom HTML email for Passwords - Reset Password. 83 | pub reset_password_template_id: std::option::Option, 84 | /// reset_password_expiration_minutes: Sets a time limit after which the email link to reset the member's 85 | /// password will no longer be valid. The minimum allowed expiration is 5 minutes and the maximum is 10080 86 | /// minutes (7 days). By default, the expiration is 30 minutes. 87 | pub reset_password_expiration_minutes: std::option::Option, 88 | pub pkce_code_challenge: std::option::Option, 89 | /// locale: Used to determine which language to use when sending the user this delivery method. Parameter is 90 | /// a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`. 91 | /// 92 | /// Currently supported languages are English (`"en"`), Spanish (`"es"`), French (`"fr"`) and Brazilian 93 | /// Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English. 94 | /// 95 | /// Request support for additional languages 96 | /// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")! 97 | /// 98 | pub locale: std::option::Option, 99 | /// verify_email_template_id: Use a custom template for verification emails sent during password reset 100 | /// flows. When cross-organization passwords are enabled for your Project, this template will be used the 101 | /// first time a user sets a password via a 102 | /// password reset flow. By default, it will use your default email template. The template must be a 103 | /// template using our built-in customizations or a custom HTML email for Passwords - Email Verification. 104 | pub verify_email_template_id: std::option::Option, 105 | } 106 | /// ResetStartResponse: Response type for `Email.reset_start`. 107 | #[derive(Serialize, Deserialize, Debug, Clone)] 108 | pub struct ResetStartResponse { 109 | /// request_id: Globally unique UUID that is returned with every API call. This value is important to log 110 | /// for debugging purposes; we may ask for this value to help identify a specific API call when helping you 111 | /// debug an issue. 112 | pub request_id: String, 113 | /// status_code: The HTTP status code of the response. Stytch follows standard HTTP response status code 114 | /// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX 115 | /// are server errors. 116 | #[serde(with = "http_serde::status_code")] 117 | pub status_code: http::StatusCode, 118 | } 119 | 120 | pub struct Email { 121 | http_client: crate::client::Client, 122 | } 123 | 124 | impl Email { 125 | pub fn new(http_client: crate::client::Client) -> Self { 126 | Self { 127 | http_client: http_client.clone(), 128 | } 129 | } 130 | 131 | pub async fn reset_start(&self, body: ResetStartRequest) -> crate::Result { 132 | let path = String::from("/v1/b2b/passwords/discovery/email/reset/start"); 133 | self.http_client 134 | .send(crate::Request { 135 | method: http::Method::POST, 136 | path, 137 | body, 138 | }) 139 | .await 140 | } 141 | pub async fn reset(&self, body: ResetRequest) -> crate::Result { 142 | let path = String::from("/v1/b2b/passwords/discovery/email/reset"); 143 | self.http_client 144 | .send(crate::Request { 145 | method: http::Method::POST, 146 | path, 147 | body, 148 | }) 149 | .await 150 | } 151 | } 152 | --------------------------------------------------------------------------------