systemprompt_api/routes/oauth/endpoints/token/
validation.rs1use super::{TokenError, TokenResult};
2use anyhow::Result;
3use systemprompt_identifiers::{AuthorizationCode, ClientId};
4use systemprompt_oauth::repository::{AuthCodeValidationResult, OAuthRepository};
5use systemprompt_oauth::services::validation::validate_client_credentials as validate_client_credentials_shared;
6
7pub fn extract_required_field<'a>(
8 field: Option<&'a str>,
9 field_name: &str,
10) -> TokenResult<&'a str> {
11 field.ok_or_else(|| TokenError::InvalidRequest {
12 field: field_name.to_string(),
13 message: "is required".to_string(),
14 })
15}
16
17pub async fn validate_client_credentials(
18 repo: &OAuthRepository,
19 client_id: &ClientId,
20 client_secret: Option<&str>,
21) -> Result<()> {
22 validate_client_credentials_shared(repo, client_id, client_secret).await
23}
24
25#[derive(Debug)]
26pub struct AuthCodeValidationParams<'a> {
27 pub repo: &'a OAuthRepository,
28 pub code: &'a AuthorizationCode,
29 pub client_id: &'a ClientId,
30 pub redirect_uri: Option<&'a str>,
31 pub code_verifier: Option<&'a str>,
32 pub request_resource: Option<&'a str>,
33}
34
35pub async fn validate_authorization_code(
36 params: AuthCodeValidationParams<'_>,
37) -> Result<AuthCodeValidationResult> {
38 let result = params
39 .repo
40 .validate_authorization_code(
41 params.code,
42 params.client_id,
43 params.redirect_uri,
44 params.code_verifier,
45 )
46 .await?;
47
48 if let Some(req_resource) = params.request_resource {
49 if let Some(ref stored_resource) = result.resource {
50 if req_resource != stored_resource {
51 return Err(anyhow::anyhow!(
52 "Resource parameter mismatch: expected '{}', got '{}'",
53 stored_resource,
54 req_resource
55 ));
56 }
57 }
58 }
59
60 Ok(result)
61}