use alloc::string::String;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
format::{self, Compact},
jws::{FromRawPayload, IntoPayload, JsonWebSignatureBuilder, PayloadData, PayloadKind},
Base64UrlString, JsonWebSignature, Jws,
};
pub type JsonWebToken<A> = JsonWebSignature<format::Compact, Claims<A>>;
impl JsonWebToken<()> {
pub fn builder_jwt() -> JsonWebSignatureBuilder<Compact> {
Jws::builder()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Claims<A = ()> {
#[serde(rename = "iss", skip_serializing_if = "Option::is_none")]
pub issuer: Option<String>,
#[serde(rename = "sub", skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[serde(rename = "aud", skip_serializing_if = "Option::is_none")]
pub audience: Option<String>,
#[serde(rename = "exp", skip_serializing_if = "Option::is_none")]
pub expiration: Option<u64>,
#[serde(rename = "nbf", skip_serializing_if = "Option::is_none")]
pub not_before: Option<u64>,
#[serde(rename = "iat", skip_serializing_if = "Option::is_none")]
pub issued_at: Option<u64>,
#[serde(rename = "jti", skip_serializing_if = "Option::is_none")]
pub jwt_id: Option<String>,
#[serde(flatten)]
pub additional: A,
}
impl<A> IntoPayload for Claims<A>
where
A: Serialize,
{
type Error = serde_json::Error;
fn into_payload(self) -> Result<PayloadKind, Self::Error> {
let encoded = serde_json::to_vec(&self)?;
Ok(PayloadKind::Attached(PayloadData::Standard(
Base64UrlString::encode(encoded),
)))
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ClaimsDecodeError {
#[error("Operation not supported.")]
OperationUnsupported,
#[error(transparent)]
Json(#[from] serde_json::Error),
}
impl<A> FromRawPayload for Claims<A>
where
A: DeserializeOwned,
{
type Context = ();
type Error = ClaimsDecodeError;
fn from_attached(_: &Self::Context, payload: PayloadData) -> Result<Self, Self::Error> {
let data = match payload {
PayloadData::Standard(data) => data.decode(),
};
let claims: Claims<A> = serde_json::from_slice(&data)?;
Ok(claims)
}
fn from_detached<F, T>(
_: &Self::Context,
_: &crate::JoseHeader<F, T>,
) -> Result<(Self, PayloadData), Self::Error> {
Err(ClaimsDecodeError::OperationUnsupported)
}
fn from_detached_many<F, T>(
_: &Self::Context,
_: &[crate::JoseHeader<F, T>],
) -> Result<(Self, PayloadData), Self::Error> {
Err(ClaimsDecodeError::OperationUnsupported)
}
}