this repo has no description
1mod grants;
2mod helpers;
3mod introspect;
4mod types;
5
6use crate::oauth::OAuthError;
7use crate::state::{AppState, RateLimitKind};
8use axum::{Form, Json, extract::State, http::HeaderMap};
9
10pub use grants::{handle_authorization_code_grant, handle_refresh_token_grant};
11pub use helpers::{TokenClaims, create_access_token, extract_token_claims, verify_pkce};
12pub use introspect::{
13 IntrospectRequest, IntrospectResponse, RevokeRequest, introspect_token, revoke_token,
14};
15pub use types::{TokenRequest, TokenResponse};
16
17fn extract_client_ip(headers: &HeaderMap) -> String {
18 if let Some(forwarded) = headers.get("x-forwarded-for")
19 && let Ok(value) = forwarded.to_str()
20 && let Some(first_ip) = value.split(',').next() {
21 return first_ip.trim().to_string();
22 }
23 if let Some(real_ip) = headers.get("x-real-ip")
24 && let Ok(value) = real_ip.to_str() {
25 return value.trim().to_string();
26 }
27 "unknown".to_string()
28}
29
30pub async fn token_endpoint(
31 State(state): State<AppState>,
32 headers: HeaderMap,
33 Form(request): Form<TokenRequest>,
34) -> Result<(HeaderMap, Json<TokenResponse>), OAuthError> {
35 let client_ip = extract_client_ip(&headers);
36 if !state
37 .check_rate_limit(RateLimitKind::OAuthToken, &client_ip)
38 .await
39 {
40 tracing::warn!(ip = %client_ip, "OAuth token rate limit exceeded");
41 return Err(OAuthError::InvalidRequest(
42 "Too many requests. Please try again later.".to_string(),
43 ));
44 }
45 let dpop_proof = headers
46 .get("DPoP")
47 .and_then(|v| v.to_str().ok())
48 .map(|s| s.to_string());
49 match request.grant_type.as_str() {
50 "authorization_code" => {
51 handle_authorization_code_grant(state, headers, request, dpop_proof).await
52 }
53 "refresh_token" => handle_refresh_token_grant(state, headers, request, dpop_proof).await,
54 _ => Err(OAuthError::UnsupportedGrantType(format!(
55 "Unsupported grant_type: {}",
56 request.grant_type
57 ))),
58 }
59}