-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat!: add 'handle' & 'team' to the client DPoP token and verify thes…
…e in the ACME server & wire-server
- Loading branch information
Showing
35 changed files
with
954 additions
and
453 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ mod thumbprint; | |
#[derive(Debug, Clone)] | ||
pub struct WireIdentity { | ||
pub client_id: String, | ||
pub handle: String, | ||
pub handle: QualifiedHandle, | ||
pub display_name: String, | ||
pub domain: String, | ||
pub status: IdentityStatus, | ||
|
@@ -118,7 +118,7 @@ fn try_extract_subject(cert: &x509_cert::TbsCertificate) -> RustyAcmeResult<(Str | |
} | ||
|
||
/// extract Subject Alternative Name to pick client-id & display name | ||
fn try_extract_san(cert: &x509_cert::TbsCertificate) -> RustyAcmeResult<(String, String)> { | ||
fn try_extract_san(cert: &x509_cert::TbsCertificate) -> RustyAcmeResult<(String, QualifiedHandle)> { | ||
let extensions = cert.extensions.as_ref().ok_or(CertificateError::InvalidFormat)?; | ||
|
||
let san = extensions | ||
|
@@ -141,13 +141,7 @@ fn try_extract_san(cert: &x509_cert::TbsCertificate) -> RustyAcmeResult<(String, | |
// a ClientId (since it's the most characterizable) and else fallback to a handle | ||
if let Ok(cid) = ClientId::try_from_uri(name) { | ||
client_id = Some(cid.to_qualified()); | ||
} else if name.starts_with(ClientId::URI_PREFIX) { | ||
let h = name | ||
.strip_prefix(ClientId::URI_PREFIX) | ||
.ok_or(RustyAcmeError::ImplementationError)? | ||
.strip_prefix(ClientId::HANDLE_PREFIX) | ||
.ok_or(RustyAcmeError::ImplementationError)? | ||
.to_string(); | ||
} else if let Ok(h) = QualifiedHandle::try_from(name) { | ||
handle = Some(h); | ||
} | ||
Ok(()) | ||
|
@@ -204,7 +198,7 @@ k9Jtg4ND98qu7qkUM3vtVVLiZkbCnRlFF04CIGCwhSo/78Kt8h6292SkT8c8eCS6 | |
|
||
let expected_client_id = "yl-8A_wZSfaS2uV8VuMEBw:[email protected]"; | ||
assert_eq!(&identity.client_id, expected_client_id); | ||
assert_eq!(&identity.handle, "alice_wire@wire.com"); | ||
assert_eq!(identity.handle.as_str(), "im:wireapp=%40alice_wire@wire.com"); | ||
assert_eq!(&identity.display_name, "Alice Smith"); | ||
assert_eq!(&identity.domain, "wire.com"); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,18 +17,28 @@ pub struct AccessGenerate { | |
/// base64Url encoded nonce generated by wire-server | ||
/// | ||
/// e.g. 'WE88EvOBzbqGerznM+2P/AadVf7374y0cH19sDSZA2A' | ||
#[arg(short = 'c', long)] | ||
#[arg(long)] | ||
nonce: String, | ||
/// wire-server uri this token will be fetched from | ||
/// | ||
/// e.g. 'https://wire.example.com/clients/token' | ||
#[arg(short = 'c', long)] | ||
#[arg(long)] | ||
htu: String, | ||
/// qualified wire client id | ||
/// | ||
/// e.g. 'im:wireapp=ODM5NDJkOWRlYmI4NGNhZWIzNzdmM2JmNjYwNzJjNmI/[email protected]' | ||
#[arg(short = 'i', long)] | ||
client_id: String, | ||
/// Wire handle | ||
/// | ||
/// e.g. 'beltram_wire' | ||
#[arg(long)] | ||
handle: String, | ||
/// Wire team the user belongs to | ||
/// | ||
/// e.g. 'wire' | ||
#[arg(short = 't', long)] | ||
team: Option<String>, | ||
/// client dpop & access token expiration in seconds | ||
/// | ||
/// e.g. '300' for 5 minutes | ||
|
@@ -54,15 +64,18 @@ impl AccessGenerate { | |
let challenge: AcmeNonce = self.challenge.into(); | ||
let htm = Htm::Post; | ||
let htu: Htu = self.htu.as_str().try_into().unwrap(); | ||
let client_id = ClientId::try_from_uri(&self.client_id).expect("Invalid 'client_id'"); | ||
let handle = Handle::from(self.handle.clone()).to_qualified(&client_id.domain); | ||
|
||
let dpop = Dpop { | ||
challenge, | ||
htm, | ||
htu: htu.clone(), | ||
handle: handle.clone(), | ||
team: self.team.clone(), | ||
extra_claims: None, | ||
}; | ||
let nonce: BackendNonce = self.nonce.into(); | ||
let client_id = ClientId::try_from_uri(&self.client_id).expect("Invalid 'client_id'"); | ||
let expiry = core::time::Duration::from_secs(self.expiry); | ||
|
||
let client_dpop_token = | ||
|
@@ -76,6 +89,8 @@ impl AccessGenerate { | |
let access_token = RustyJwtTools::generate_access_token( | ||
&client_dpop_token, | ||
&client_id, | ||
handle, | ||
self.team.into(), | ||
nonce, | ||
htu, | ||
htm, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,39 +12,44 @@ pub struct AccessVerify { | |
/// qualified wire client id | ||
/// | ||
/// e.g. 'im:wireapp=ODM5NDJkOWRlYmI4NGNhZWIzNzdmM2JmNjYwNzJjNmI/[email protected]' | ||
#[arg(short = 'i', long)] | ||
#[arg(long)] | ||
client_id: String, | ||
/// qualified wire handle | ||
/// | ||
/// e.g. 'beltram_wire' | ||
#[arg(long)] | ||
handle: String, | ||
/// challenge (nonce) generated by acme server | ||
/// | ||
/// e.g. 'okAJ33Ym/XS2qmmhhh7aWSbBlYy4Ttm1EysqW8I/9ng' | ||
#[arg(short = 'c', long)] | ||
#[arg(long)] | ||
challenge: String, | ||
/// maximum of clock skew in seconds allowed. Defaults to 360. | ||
/// | ||
/// e.g. '360' (5 min) | ||
#[arg(short = 'l', long, default_value = "360")] | ||
#[arg(long, default_value = "360")] | ||
leeway: u16, | ||
/// access token maximum allowed expiration expressed as unix timestamp | ||
/// | ||
/// e.g. '1701507459' | ||
#[arg(short = 'e', long)] | ||
#[arg(long)] | ||
max_expiry: u64, | ||
/// endpoint delivering the access-token on wire-server. | ||
/// Should be configured in `provisioners[*].options.dpop.dpop-target` config key on the ACME server | ||
/// | ||
/// e.g. 'https://wire.com/clients/123abef456/access-token' | ||
#[arg(short = 'e', long)] | ||
#[arg(long)] | ||
issuer: String, | ||
/// hash algorithm used to compute the JWK thumbprint. Supported values: ['SHA-256', 'SHA-384'] | ||
/// | ||
/// e.g. 'SHA-256' | ||
#[arg(short = 'a', long)] | ||
#[arg(long)] | ||
hash_algorithm: HashAlgorithm, | ||
/// Thumbprint of the dpop proof JWK | ||
#[arg(long)] | ||
kid: String, | ||
/// path to file with wire-server's signature public key in PEM format | ||
#[arg(short = 'k', long)] | ||
#[arg(long)] | ||
key: PathBuf, | ||
/// version of wire-server http API | ||
/// | ||
|
@@ -64,10 +69,12 @@ impl AccessVerify { | |
let challenge: AcmeNonce = self.challenge.into(); | ||
let (_, backend_pk) = parse_public_key_pem(read_file(Some(&self.key)).unwrap()); | ||
let issuer = self.issuer.as_str().try_into().expect("Invalid 'issuer'"); | ||
let handle = Handle::from(self.handle).to_qualified(&client_id.domain); | ||
|
||
let verification = RustyJwtTools::verify_access_token( | ||
&access_token, | ||
&client_id, | ||
&handle, | ||
challenge, | ||
self.leeway, | ||
self.max_expiry, | ||
|
Oops, something went wrong.