feat: Add support for reading the OIDC client secret from a file

This commit is contained in:
Ginger committed 2026-07-02 16:34:56 -04:00
1 parent 910925b906
commit 45809b7970
4 files changed
+43 -8

No files matched your search

+7
View File
@@ -2057,6 +2057,13 @@
#
#client_secret =
# A path to a file which Continuwuity will read the client secret from.
# If this option is set, it will override `client_secret`.
#
# The server will fail to start if the file cannot be read.
#
#client_secret_file =
# Additional scopes Continuwuity should request from the IDP. This may be
# necessary to access certain claims. Continuwuity always requests the
# `openid` scope.
+9
View File
@@ -289,6 +289,15 @@ pub fn check(config: &Config) -> Result {
| _ => (),
}
if let Some(oidc) = &config.oauth.oidc
&& oidc.client_secret.is_none()
&& oidc.client_secret_file.is_none()
{
return Err!(
"Either `client_secret` or `client_secret_file` must be set if OIDC is configured."
);
}
Ok(())
}
+7 -1
View File
@@ -2484,7 +2484,13 @@ pub struct OidcConfig {
/// The OAuth client secret for Continuwuity to use when communicating with
/// the identity provider.
pub client_secret: ClientSecret,
pub client_secret: Option<ClientSecret>,
/// A path to a file which Continuwuity will read the client secret from.
/// If this option is set, it will override `client_secret`.
///
/// The server will fail to start if the file cannot be read.
pub client_secret_file: Option<PathBuf>,
/// Additional scopes Continuwuity should request from the IDP. This may be
/// necessary to access certain claims. Continuwuity always requests the
+20 -7
View File
@@ -9,9 +9,9 @@ use conduwuit::{
use database::{Deserialized, Map};
use lettre::Address;
use openidconnect::{
AdditionalClaims, AuthorizationCode, CsrfToken, EmptyExtraTokenFields, EndpointMaybeSet,
EndpointNotSet, EndpointSet, IdTokenClaims, IdTokenFields, IssuerUrl, Nonce,
PkceCodeChallenge, PkceCodeVerifier, RedirectUrl, StandardErrorResponse,
AdditionalClaims, AuthorizationCode, ClientSecret, CsrfToken, EmptyExtraTokenFields,
EndpointMaybeSet, EndpointNotSet, EndpointSet, IdTokenClaims, IdTokenFields, IssuerUrl,
Nonce, PkceCodeChallenge, PkceCodeVerifier, RedirectUrl, StandardErrorResponse,
StandardTokenResponse, TokenResponse,
core::{
CoreAuthDisplay, CoreAuthPrompt, CoreAuthenticationFlow, CoreErrorResponseType,
@@ -59,6 +59,7 @@ struct Services {
struct OidcClient {
config: OidcConfig,
client_secret: ClientSecret,
machine: SetOnce<OidcClientMachine>,
client: reqwest::Client,
}
@@ -130,8 +131,19 @@ impl crate::Service for Service {
openidsubject_localpart: args.db["openidsubject_localpart"].clone(),
openidsubject_currentpictureurl: args.db["openidsubject_currentpictureurl"].clone(),
},
client: args.server.config.oauth.oidc.as_ref().map(|config| OidcClient {
client: args.server.config.oauth.oidc.as_ref().map(|config| -> Result<OidcClient> {
Ok(OidcClient {
config: config.clone(),
client_secret: if let Some(client_secret_file) = &config.client_secret_file {
std::fs::read_to_string(client_secret_file)
.map(ClientSecret::new)
.map_err(|err| err!("Failed to read OIDC client secret file: {err}"))?
} else if let Some(client_secret) = &config.client_secret {
client_secret.clone()
} else {
// The config check function should cause an early exit before this happens
panic!("neither client secret or client secret file were set");
},
machine: SetOnce::new(),
// This isn't in the client service because it has to use the `reqwest` shipped by `openidconnect`
client: reqwest::ClientBuilder::new()
@@ -145,12 +157,13 @@ impl crate::Service for Service {
.danger_accept_invalid_certs(args.server.config.allow_invalid_tls_certificates_yes_i_know_what_the_fuck_i_am_doing_with_this_and_i_know_this_is_insecure)
.build()
.expect("client should build")
}),
})}
).transpose()?,
}))
}
async fn worker(self: Arc<Self>) -> Result {
if let Some(OidcClient { config, machine, client }) = &self.client {
if let Some(OidcClient { config, client_secret, machine, client }) = &self.client {
let redirect_url = self
.services
.config
@@ -170,7 +183,7 @@ impl crate::Service for Service {
OidcClientMachine::from_provider_metadata(
provider_metadata,
config.client_id.clone(),
Some(config.client_secret.clone()),
Some(client_secret.clone()),
)
.set_redirect_uri(RedirectUrl::from_url(redirect_url)),
)