feat: OpenAICompatibleOAuthProvider (config-driven OAuthProvider impl)

This commit is contained in:
2026-07-20 12:55:30 -06:00
parent 68177fdb6a
commit 66bbb34d7f
7 changed files with 105 additions and 11 deletions
+92
View File
@@ -0,0 +1,92 @@
use super::oauth::{OAuthConfig, OAuthFlow, OAuthProvider, TokenRequestFormat};
pub struct OpenAICompatibleOAuthProvider {
pub config: OAuthConfig,
pub client_name: String,
}
impl OAuthProvider for OpenAICompatibleOAuthProvider {
fn provider_name(&self) -> &str {
&self.client_name
}
fn client_id(&self) -> &str {
&self.config.client_id
}
fn authorize_url(&self) -> &str {
self.config.authorize_url.as_deref().unwrap_or("")
}
fn token_url(&self) -> &str {
&self.config.token_url
}
fn redirect_uri(&self) -> &str {
self.config.redirect_uri.as_deref().unwrap_or("")
}
fn scopes(&self) -> String {
self.config.scopes.join(" ")
}
fn client_secret(&self) -> Option<&str> {
self.config.client_secret.as_deref()
}
fn extra_authorize_params(&self) -> Vec<(&str, &str)> {
self.config
.extra_authorize_params
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect()
}
fn token_request_format(&self) -> TokenRequestFormat {
self.config
.token_request_format
.unwrap_or(TokenRequestFormat::FormUrlEncoded)
}
fn uses_localhost_redirect(&self) -> bool {
self.config.redirect_uri.is_none() && self.config.redirect_port.is_none()
}
fn fixed_redirect_uri(&self) -> Option<String> {
if let Some(uri) = &self.config.redirect_uri {
return Some(uri.clone());
}
if let Some(port) = self.config.redirect_port {
return Some(format!("http://127.0.0.1:{port}/callback"));
}
None
}
fn extra_token_headers(&self) -> Vec<(&str, &str)> {
self.config
.extra_token_headers
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect()
}
fn extra_request_headers(&self) -> Vec<(&str, &str)> {
self.config
.extra_request_headers
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect()
}
fn flow(&self) -> OAuthFlow {
self.config.flow
}
fn echo_pkce_in_token_exchange(&self) -> bool {
self.config.echo_pkce_in_token_exchange
}
fn include_state_in_token_exchange(&self) -> bool {
self.config.include_state_in_token_exchange
}
}