Skip to main content

wire_e2e_identity/acquisition/
oidc_challenge.rs

1use obfuscate::Obfuscated;
2use rusty_jwt_tools::{jsonwebtoken::jwk::ThumbprintHash, prelude::Pem};
3use x509_cert::Certificate;
4
5use super::{Result, X509CredentialAcquisition, states};
6use crate::{
7    acme,
8    pki_env::hooks::{HttpHeader, HttpMethod},
9};
10
11impl X509CredentialAcquisition<states::DpopChallengeCompleted> {
12    /// Complete the OIDC challenge and get the certificate chain.
13    ///
14    /// Returns (signing keypair in PEM format, certificate chain).
15    /// The first certificate in the chain is the end-entity certificate,
16    /// i.e. the one certifying the public portion of the signing keypair.
17    pub async fn complete_oidc_challenge(self) -> Result<(Pem, Vec<Certificate>)> {
18        let hooks = self.pki_env.hooks();
19
20        // Complete the OIDC challenge.
21        let oidc_challenge_token = &self.data.oidc_challenge.token;
22        // RFC 8555 section 8.1 mandates SHA-256 for the key authorization thumbprint.
23        let thumbprint = self.acme_jwk.thumbprint(ThumbprintHash::SHA256)?;
24        let key_auth = format!("{oidc_challenge_token}.{thumbprint}");
25        let snapshot = serde_json::to_vec(&self)?;
26
27        let url = &self.data.oidc_challenge.url;
28        let target = self.data.oidc_challenge.target.to_string();
29        let id_token = hooks.authenticate(target, key_auth, url.to_string(), snapshot).await?;
30        log::debug!(
31            "acquisition({:?}): got the ID token from the OIDC server",
32            Obfuscated::from(&self.sign_kp),
33        );
34
35        let oidc_challenge_request = acme::oidc_chall_request(
36            id_token,
37            &self.data.oidc_challenge,
38            &self.data.acme_account,
39            self.sign_alg,
40            &self.acme_kp,
41            self.data.nonce.clone(),
42        )?;
43        let (nonce, response) = self.acme_request(url, &oidc_challenge_request).await?;
44        let _ = acme::new_chall_response(response)?;
45        log::info!(
46            "acquisition({:?}): OIDC challenge completed",
47            Obfuscated::from(&self.sign_kp),
48        );
49
50        // Finalize the order. This generates a CSR (Certificate Signing Request) and
51        // sends it to the ACME server.
52        let finalize_request = acme::finalize_req(
53            &self.data.order,
54            &self.data.acme_account,
55            self.sign_alg,
56            &self.acme_kp,
57            &self.sign_kp,
58            nonce,
59        )?;
60        let (nonce, response) = self.acme_request(&self.data.order.finalize, &finalize_request).await?;
61        let finalize = acme::finalize_response(response)?;
62        log::debug!(
63            "acquisition({:?}): ACME order finalized",
64            Obfuscated::from(&self.sign_kp),
65        );
66
67        // Get the certificate chain.
68        //
69        // See [RFC 8555 Section 7.4.2](https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4.2).
70        let certificate_request =
71            acme::certificate_req(&finalize, &self.data.acme_account, self.sign_alg, &self.acme_kp, nonce)?;
72        let headers = vec![HttpHeader {
73            name: "content-type".into(),
74            value: "application/jose+json".into(),
75        }];
76        let body = serde_json::to_string(&certificate_request)?.into();
77        let response = hooks
78            .http_request(HttpMethod::Post, finalize.certificate.to_string(), headers, body)
79            .await?;
80        let response = String::from_utf8(response.body).map_err(|e| acme::Error::from(e.utf8_error()))?;
81        let certificates = acme::certificate_response(response, &self.data.order)?;
82        log::debug!(
83            "acquisition({:?}): got the certificate",
84            Obfuscated::from(&self.sign_kp),
85        );
86
87        self.verify_cert_chain(&certificates).await?;
88        log::info!(
89            "acquisition({:?}): certificate verified successfully",
90            Obfuscated::from(&self.sign_kp),
91        );
92
93        Ok((self.sign_kp, certificates))
94    }
95}