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