openrouter_rs/api/
auth.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{error::OpenRouterError, utils::handle_error};
4
5#[derive(Serialize, Deserialize, Debug)]
6pub struct AuthRequest {
7    code: String,
8    code_verifier: Option<String>,
9    code_challenge_method: Option<CodeChallengeMethod>,
10}
11
12#[derive(Serialize, Deserialize, Debug)]
13pub enum CodeChallengeMethod {
14    S256,
15
16    #[serde(rename_all = "lowercase")]
17    Plain,
18}
19
20#[derive(Serialize, Deserialize, Debug)]
21pub struct AuthResponse {
22    key: String,
23    user_id: Option<String>,
24}
25
26/// Exchange an authorization code from the PKCE flow for a user-controlled API key
27///
28/// # Arguments
29///
30/// * `base_url` - The base URL of the OpenRouter API.
31/// * `code` - The authorization code received from the OAuth redirect.
32/// * `code_verifier` - The code verifier if code_challenge was used in the authorization request.
33/// * `code_challenge_method` - The method used to generate the code challenge.
34///
35/// # Returns
36///
37/// * `Result<AuthResponse, OpenRouterError>` - The API key and user ID associated with the API key.
38pub async fn exchange_code_for_api_key(
39    base_url: &str,
40    code: &str,
41    code_verifier: Option<&str>,
42    code_challenge_method: Option<CodeChallengeMethod>,
43) -> Result<AuthResponse, OpenRouterError> {
44    let url = format!("{}/auth/keys", base_url);
45    let request = AuthRequest {
46        code: code.to_string(),
47        code_verifier: code_verifier.map(|s| s.to_string()),
48        code_challenge_method,
49    };
50
51    let mut response = surf::post(url).body_json(&request)?.await?;
52
53    if response.status().is_success() {
54        let auth_response = response.body_json().await?;
55        Ok(auth_response)
56    } else {
57        handle_error(response).await?;
58        unreachable!()
59    }
60}