ory / sdk

The place where ORY's SDKs are being auto-generated
Apache License 2.0
141 stars 85 forks source link

ory-client 1.6.1 deserialization error on get_registration_flow #325

Closed fraschm1998 closed 2 months ago

fraschm1998 commented 7 months ago

Preflight checklist

Ory Network Project

No response

Describe the bug

Err(
Serde(
Error("missing field nodetype", line: 1, column: 640),
),
)

Reproducing the bug

main.rs:

use ory_client::apis::{
    configuration::{ApiKey, Configuration},
    frontend_api::get_registration_flow,
};

#[tokio::main]
async fn main() {
    let mut config = Configuration::new();
    config.base_path = "http://127.0.0.1:4433".to_string();
    config.client = reqwest::Client::builder()
        .redirect(reqwest::redirect::Policy::limited(10)) // Allow up to 10 redirects
        .build()
        .unwrap();

    let flow = get_registration_flow(
        &config,
        "3728d7c7-31af-4864-be7c-ba862a5b1aa2", //flow id
        Some("csrf_token_3ac963bb878be49782bfacfa64748966624ad776419d415e9bdc1d85db359862=qZuup8N3jJYEyYDEMI2KJ0INSQhwYLQ+H8D+ZsnHI1c="), //cookie
    )
    .await;

    println!("{:#?}", &flow);
}

Cargo.toml:

[package]
name = "auth_new"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ory-client = "^1.6"
tokio = { version = "1.35.1", features = ["full"] }
reqwest = { version = "0.11", features = ["cookies", "json"] }

Relevant log output

Err(                                                                                                                                                                          
    Serde(                                                                                                                                                                    
        Error("missing field `nodetype`", line: 1, column: 640),                       
    ),                                                                                
)

Relevant configuration

No response

Version

latest self hosted kratos

On which operating system are you observing this issue?

None

In which environment are you deploying?

None

Additional Context

I tried manually quesrying the endpoint without ory_client sdk using reqwest and the following code:

use reqwest::header::{HeaderMap, HeaderValue, COOKIE, USER_AGENT};
use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let base_path = "http://127.0.0.1:4433";
    let id = "ccd904b9-b301-4ab9-93c2-81887df2a341";
    let cookie = Some("csrf_token_3ac963bb878be49782bfacfa64748966624ad776419d415e9bdc1d85db359862=qZuup8N3jJYEyYDEMI2KJ0INSQhwYLQ+H8D+ZsnHI1c=");

    let client = reqwest::Client::new();
    let url = format!("{}/self-service/registration/flows", base_path);

    let mut headers = HeaderMap::new();
    if let Some(cookie_value) = cookie {
        headers.insert(COOKIE, HeaderValue::from_str(cookie_value)?);
    }

    let response = client
        .get(&url)
        .query(&[("id", id)])
        .headers(headers)
        .send()
        .await?;

    let status = response.status();
    let content = response.text().await?;

    if !status.is_client_error() && !status.is_server_error() {
        // Directly print the JSON text
        println!("Registration Flow JSON: {}", content);
        Ok(())
    } else {
        // Handle errors by printing the status and content
        println!("Error: Status {}, Content {}", status, content);
        Err("Failed to fetch the registration flow".into())
    }
}

and got the following output:

Registration Flow JSON: {"id":"ccd904b9-b301-4ab9-93c2-81887df2a341","oauth2_login_challenge":null,"type":"browser","expires_at":"2024-02-12T19:13:03.688668Z","issued_at":"2024-02-12T19:03:03.688668Z","request_url":"http://127.0.0.1:4433/self-service/registration/browser","ui":{"action":"http://192.168.30.33:4455/.ory/kratos/public/self-service/registration?flow=ccd904b9-b301-4ab9-93c2-81887df2a341","method":"POST","nodes":[{"type":"input","group":"default","attributes":{"name":"csrf_token","type":"hidden","value":"yZu3SIzcAOh+UJu1sKL1O5TF+XbmIcx5fRFzAyERoR9gABnvT6uMfnqZG3GAL38c1siwfpZBeEdi0Y1l6NaCSA==","required":true,"disabled":false,"node_type":"input"},"messages":[],"meta":{}},{"type":"input","group":"password","attributes":{"name":"traits.email","type":"email","required":true,"autocomplete":"email","disabled":false,"node_type":"input"},"messages":[],"meta":{"label":{"id":1070002,"text":"E-Mail","type":"info"}}},{"type":"input","group":"password","attributes":{"name":"password","type":"password","required":true,"autocomplete":"new-password","disabled":false,"node_type":"input"},"messages":[],"meta":{"label":{"id":1070001,"text":"Password","type":"info"}}},{"type":"input","group":"password","attributes":{"name":"traits.name.first","type":"text","disabled":false,"node_type":"input"},"messages":[],"meta":{"label":{"id":1070002,"text":"First Name","type":"info"}}},{"type":"input","group":"password","attributes":{"name":"traits.name.last","type":"text","disabled":false,"node_type":"input"},"messages":[],"meta":{"label":{"id":1070002,"text":"Last Name","type":"info"}}},{"type":"input","group":"password","attributes":{"name":"method","type":"submit","value":"password","disabled":false,"node_type":"input"},"messages":[],"meta":{"label":{"id":1040001,"text":"Sign up","type":"info","context":{}}}}]}}
Jeremiah-Griffin commented 7 months ago

Hi, this issue is known, it's a bug with an upstream project.

https://github.com/ory/sdk/issues/276#issuecomment-1753229752

The nodetype is found in the field that serializes the UI. You can solve it by manually renaming that field in the correct snake case.

Not however that it is possible to simply deserialize the response into a nother type that omits the field entirely.

When serde encounters a struct field in the data stream not defined for the T it is deserializing into, it simply ignores that field gracefully. Not only will this skip this error in particular it should avoid quite a few allocations and the cpu overhead of deserializing into memory your program never otherwise accesses.

Additionally, the ory sdk doesn't follow semver, so deserializing only the fields you actually use minimizes the chance of running into breaking changes in production.

I'm a user not an employee of Ory, nor is this recommended anywhere I can find, and I could well be wrong here. But I've done this myself and it's been working fine so far. it's just my own common practice of trying to wrangle the messiness of REST in strongly typed languages.

its-danny commented 7 months ago

I stumbled on this while working on my project with the Rust SDK, having the same issue with create_browser_login_flow. It sounds like the workaround is to use reqwest and create my own types, but I wanted to add a +1 that this is a pretty work-blocking issue if you want to use your own UI.

Jeremiah-Griffin commented 7 months ago

I stumbled on this while working on my project with the Rust SDK, having the same issue with create_browser_login_flow. It sounds like the workaround is to use reqwest and create my own types, but I wanted to add a +1 that this is a pretty work-blocking issue if you want to use your own UI.

To be clear you can just fork the project and rename nodetype to node_type and it should solve the issue. It's a casing error.

My suggestion was a more general best practice that solves the issue incidentally. The API very eagerly overfetches a lot of data for most use cases.

aeneasr commented 2 months ago

We have released the latest version of the SDK as all the pipeline issues have been fixed. This should be addressed now by upgrading the package :)