diff --git a/crates/cli/src/sync.rs b/crates/cli/src/sync.rs index 647ef2635..36f9568e8 100644 --- a/crates/cli/src/sync.rs +++ b/crates/cli/src/sync.rs @@ -189,10 +189,18 @@ pub async fn config_sync( let encrypted_client_secret = if let Some(client_secret) = provider.client_secret.as_deref() { Some(encrypter.encrypt_to_string(client_secret.as_bytes())?) - } else if let Some(siwa) = provider.sign_in_with_apple.as_ref() { - // For SIWA, we JSON-encode the config and encrypt it, reusing the client_secret - // field in the database - let encoded = serde_json::to_vec(siwa)?; + } else if let Some(mut siwa) = provider.sign_in_with_apple.clone() { + // if private key file is defined and not private key (raw), we populate the + // private key to hold the content of the private key file. + // private key (raw) takes precedence so both can be defined + // without issues + if siwa.private_key.is_none() { + if let Some(private_key_file) = siwa.private_key_file.take() { + let key = tokio::fs::read_to_string(private_key_file).await?; + siwa.private_key = Some(key); + } + } + let encoded = serde_json::to_vec(&siwa)?; Some(encrypter.encrypt_to_string(&encoded)?) } else { None diff --git a/crates/config/src/sections/upstream_oauth2.rs b/crates/config/src/sections/upstream_oauth2.rs index 98b5f3c3c..623a97c14 100644 --- a/crates/config/src/sections/upstream_oauth2.rs +++ b/crates/config/src/sections/upstream_oauth2.rs @@ -6,6 +6,7 @@ use std::collections::BTreeMap; +use camino::Utf8PathBuf; use mas_iana::jose::JsonWebSignatureAlg; use schemars::JsonSchema; use serde::{Deserialize, Serialize, de::Error}; @@ -383,8 +384,14 @@ fn signed_response_alg_default() -> JsonWebSignatureAlg { #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct SignInWithApple { + /// The private key file used to sign the `id_token` + #[serde(skip_serializing_if = "Option::is_none")] + #[schemars(with = "Option")] + pub private_key_file: Option, + /// The private key used to sign the `id_token` - pub private_key: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub private_key: Option, /// The Team ID of the Apple Developer Portal pub team_id: String, diff --git a/docs/config.schema.json b/docs/config.schema.json index e49a75754..165cf947d 100644 --- a/docs/config.schema.json +++ b/docs/config.schema.json @@ -2158,10 +2158,13 @@ "type": "object", "required": [ "key_id", - "private_key", "team_id" ], "properties": { + "private_key_file": { + "description": "The private key file used to sign the `id_token`", + "type": "string" + }, "private_key": { "description": "The private key used to sign the `id_token`", "type": "string" diff --git a/docs/setup/sso.md b/docs/setup/sso.md index 069bf349d..0f3994825 100644 --- a/docs/setup/sso.md +++ b/docs/setup/sso.md @@ -84,18 +84,23 @@ Sign-in with Apple uses special non-standard for authenticating clients, which r ```yaml upstream_oauth2: providers: - - client_id: 01JAYS74TCG3BTWKADN5Q4518C - client_name: "" # TO BE FILLED + - id: 01JAYS74TCG3BTWKADN5Q4518C + issuer: "https://appleid.apple.com" + human_name: "Apple" + brand_name: "apple" + client_id: "" # TO BE FILLED scope: "openid name email" response_mode: "form_post" - token_endpoint_auth_method: "sign_in_with_apple" sign_in_with_apple: - private_key: | - # Content of the PEM-encoded private key file, TO BE FILLED + + # Only one of the below should be filled for the private key + private_key_file: "" # TO BE FILLED + private_key: | # TO BE FILLED + # + team_id: "" # TO BE FILLED key_id: "" # TO BE FILLED - claims_imports: localpart: action: ignore @@ -549,4 +554,4 @@ To use a Rauthy-supported [Ephemeral Client](https://sebadob.github.io/rauthy/wo "access_token_signed_response_alg": "RS256", "id_token_signed_response_alg": "RS256" } -``` +``` \ No newline at end of file