1use std::time::UNIX_EPOCH;
4
5use ts_crypto::any::{SigningKey, VerifyingKey};
6
7use crate::{
8 Algorithm, Curve, JsonWebKey, JsonWebToken,
9 jwt::{Claims, Header, TokenType},
10};
11
12pub struct TokenIssuer {
14 jwk: JsonWebKey,
16 key: SigningKey,
18}
19
20impl TokenIssuer {
21 pub fn issue_token(&self, subject: String, token_type: TokenType) -> JsonWebToken {
26 let valid_for = token_type.valid_for();
27
28 let now_seconds = UNIX_EPOCH
29 .elapsed()
30 .expect("system time should be ahead of unix epoch")
31 .as_secs();
32
33 let claims = Claims {
34 exp: now_seconds + valid_for.as_secs(),
35 iat: now_seconds,
36 sub: subject,
37 typ: token_type,
38 };
39
40 let header = Header {
41 alg: self.jwk.alg.to_string(),
42 typ: "JWT".to_string(),
43 kid: self.jwk.kid.clone(),
44 };
45
46 let message = JsonWebToken::create_message(&header, &claims);
47
48 let signature = match &self.key {
49 SigningKey::Ecdsa(key) => match self.jwk.alg {
50 Algorithm::ES256 => key.sign_sha256(&message),
51 Algorithm::ES384 => key.sign_sha384(&message),
52 Algorithm::ES512 => key.sign_sha512(&message),
53 _ => panic!("ECDSA key with non-ECDSA algorithm"),
54 },
55 SigningKey::EdDsa(key) => match (self.jwk.alg, self.jwk.crv) {
56 (Algorithm::Ed448, _)
57 | (Algorithm::Ed25519, _)
58 | (Algorithm::EdDSA, Some(Curve::Ed448))
59 | (Algorithm::EdDSA, Some(Curve::Ed25519)) => key.sign(&message),
60 _ => panic!("EdDSA key with non-EdDSA curve/algorithm"),
61 },
62 SigningKey::Rsa(key) => match self.jwk.alg {
63 Algorithm::RS256 => key.sign_rs256(&message),
64 Algorithm::RS384 => key.sign_rs384(&message),
65 Algorithm::RS512 => key.sign_rs512(&message),
66 Algorithm::PS256 => key.sign_ps256(&message),
67 Algorithm::PS384 => key.sign_ps384(&message),
68 Algorithm::PS512 => key.sign_ps512(&message),
69 _ => panic!("RSA key with non-RSA algorithm"),
70 },
71 };
72
73 JsonWebToken {
74 header,
75 claims,
76 signature,
77 }
78 }
79
80 pub fn jwk(&self) -> &JsonWebKey {
82 &self.jwk
83 }
84
85 pub fn from_key(key: SigningKey) -> Option<Self> {
87 let verifier = match key {
88 SigningKey::Ecdsa(ref key) => VerifyingKey::Ecdsa(key.verifying_key()),
89 SigningKey::EdDsa(ref key) => VerifyingKey::EdDsa(key.verifying_key()),
90 SigningKey::Rsa(ref key) => VerifyingKey::Rsa(key.verifying_key()),
91 };
92 let jwk = JsonWebKey::from_key(&verifier)?;
93
94 Some(Self { jwk, key })
95 }
96}