Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Unified the `Verified` and `Signed` token header types, since they represent the same state – a known, validated signature and related parameters are present.

## [1.0.1](https://github.com/alexrudy/jaws/releases/tag/1.0.1)

Every patch will bump dependencies as appropriate.
Expand Down
54 changes: 7 additions & 47 deletions src/token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ mod state;

use self::formats::TokenParseError;
pub use self::formats::{Compact, Flat, FlatUnprotected, TokenFormat, TokenFormattingError};
pub use self::state::{HasSignature, MaybeSigned, Signed, Unsigned, Unverified, Verified};
pub use self::state::{HasSignature, MaybeSigned, Signed, Unsigned, Unverified};

#[allow(deprecated)]
pub use self::state::Verified;

/// A JWT Playload. Most payloads are JSON objects, which are serialized, and then converted
/// to a base64url string. However, some payloads are empty, and are represented as an empty
Expand Down Expand Up @@ -373,7 +376,7 @@ impl<P, State: MaybeSigned, Fmt: TokenFormat> Token<P, State, Fmt> {

impl<P, H, Fmt: TokenFormat> Token<P, Unsigned<H>, Fmt> {
/// Mutable access to Token header values
pub fn header_mut(&mut self) -> HeaderAccessMut<H, crate::jose::UnsignedHeader> {
pub fn header_mut(&mut self) -> HeaderAccessMut<'_, H, crate::jose::UnsignedHeader> {
HeaderAccessMut::new(self.state.header_mut())
}
}
Expand Down Expand Up @@ -563,7 +566,7 @@ where
pub fn verify<A, S>(
self,
algorithm: &A,
) -> Result<Token<P, Verified<H, A, S>, Fmt>, TokenVerifyingError>
) -> Result<Token<P, Signed<H, A, S>, Fmt>, TokenVerifyingError>
where
A: crate::algorithms::TokenVerifier<S> + ?Sized,
S: SignatureEncoding,
Expand All @@ -590,7 +593,7 @@ where

Ok(Token {
payload: self.payload,
state: Verified {
state: Signed {
header,
signature,
_phantom_key: PhantomData,
Expand Down Expand Up @@ -656,49 +659,6 @@ where
}
}

impl<P, H, Alg, Sig, Fmt> Token<P, Verified<H, Alg, Sig>, Fmt>
where
Fmt: TokenFormat,
Alg: DynJsonWebAlgorithm + ?Sized,
Sig: SignatureEncoding,
H: Serialize,
P: Serialize,
{
/// Transition the token back into an unverified state.
///
/// This method consumes the token and returns a new one, which still includes the signature
/// but which is no longer considered verified.
pub fn unverify(self) -> Token<P, Unverified<H>, Fmt> {
let payload = self
.payload
.serialized_bytes()
.expect("valid payload bytes");
Token {
payload: self.payload,
state: Unverified {
payload,
header: self.state.header.into_rendered_header(),
signature: Base64Signature(self.state.signature.to_bytes().as_ref().into()),
},
fmt: self.fmt,
}
}
}

impl<H, Fmt, P, Alg, Sig> Token<P, Verified<H, Alg, Sig>, Fmt>
where
Fmt: TokenFormat,
Alg: DynJsonWebAlgorithm + ?Sized,
{
/// Get the payload of the token.
pub fn payload(&self) -> Option<&P> {
match &self.payload {
Payload::Json(data) => Some(data.as_ref()),
Payload::Empty => None,
}
}
}

#[cfg(feature = "fmt")]
impl<P, S, Fmt> fmt::JWTFormat for Token<P, S, Fmt>
where
Expand Down
63 changes: 7 additions & 56 deletions src/token/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ impl<H> MaybeSigned for Unsigned<H> {

/// This JWS has been signed.
///
/// This state is used when this program applied the signature, so we know that the
/// signature is both consistent and valid.
/// This state is used when this program applied or verified the signature,
/// so we know that the signature is both consistent and valid.
///
/// Since the signature has already been generated, this token cannot be modified.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(bound(serialize = "H: Serialize, Sig: Serialize",))]
pub struct Signed<H, Alg, Sig = SignatureBytes>
Expand Down Expand Up @@ -138,60 +140,9 @@ where
}
}

/// This JWS has been verified.
///
/// This state is used when this program has verified the signature, so we know that the
/// signature is valid and consistent with the header values. However, we also know that
/// we did not create the token, and modifying it may result in headers which are not
/// consistent with the signature.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(bound(serialize = "H: Serialize, Sig: Serialize",))]
pub struct Verified<H, Alg, Sig = SignatureBytes>
where
Alg: DynJsonWebAlgorithm + ?Sized,
{
pub(super) header: jose::Header<H, jose::SignedHeader>,
pub(super) signature: Sig,

#[serde(skip)]
pub(super) _phantom_key: PhantomData<Alg>,
}

impl<H, Alg, Sig> MaybeSigned for Verified<H, Alg, Sig>
where
Alg: DynJsonWebAlgorithm + ?Sized,
{
type HeaderState = jose::SignedHeader;
type Header = H;

fn header_mut(&mut self) -> &mut jose::Header<Self::Header, Self::HeaderState> {
&mut self.header
}

fn header(&self) -> &jose::Header<H, Self::HeaderState> {
&self.header
}

fn is_signed(&self) -> bool {
true
}

fn is_verified(&self) -> bool {
true
}
}

impl<H, Alg, Sig> HasSignature for Verified<H, Alg, Sig>
where
Alg: DynJsonWebAlgorithm + ?Sized,
Sig: SignatureEncoding,
{
type Signature = Sig;

fn signature(&self) -> &Self::Signature {
&self.signature
}
}
/// Alias for Signed.
#[deprecated(since = "1.1.0", note = "Verified is now an alias for Signed")]
pub type Verified<H, Alg, Sig> = Signed<H, Alg, Sig>;

/// This JWS has not been verified. It has a signature, but we have not checked it.
///
Expand Down
Loading