diff options
author | Vincent Ambo <mail@tazj.in> | 2018-09-04T08·58+0200 |
---|---|---|
committer | Vincent Ambo <mail@tazj.in> | 2018-09-04T10·45+0200 |
commit | d3b200e820589fa8af8f47cd7e2bb76be006475b (patch) | |
tree | 5c50959b7258cb62f13cea4e97a66743e77741fc | |
parent | 0f8231e99051c1a9703f951b19a5877fe474d92d (diff) |
refactor: Use error enum + result type alias for failures
This makes the library slightly more "rusty". Instead of returning a validation result which also represents potential success, use an enum representing the error variants and the standard library's `Result`-type to represent success/failure.
-rw-r--r-- | src/lib.rs | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/src/lib.rs b/src/lib.rs index a7638c524643..e424ca023191 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,7 @@ use base64::{decode_config, URL_SAFE}; use openssl::bn::BigNum; use openssl::pkey::Public; use openssl::rsa::{Rsa}; +use openssl::error::ErrorStack; /// JWT algorithm used. The only supported algorithm is currently /// RS256. @@ -112,22 +113,33 @@ pub struct JWT {} pub enum Validation {} /// Possible results of a token validation. -pub enum ValidationResult { - /// Signature and claim validation succeeded. - Valid, +#[derive(Debug)] +pub enum ValidationError { + /// Token was malformed (various possible reasons!) + MalformedJWT, /// Decoding of the provided JWK failed. - InvalidJWK(String), + InvalidJWK, /// Signature validation failed, i.e. because of a non-matching /// public key. InvalidSignature, + /// An OpenSSL operation failed along the way at a point at which + /// a more specific error variant could not be constructed. + OpenSSL(ErrorStack), + /// One or more claim validations failed. // TODO: Provide reasons? InvalidClaims, } +type JWTResult<T> = Result<T, ValidationError>; + +impl From<ErrorStack> for ValidationError { + fn from(err: ErrorStack) -> Self { ValidationError::OpenSSL(err) } +} + /// Attempt to extract the `kid`-claim out of a JWT's header claims. /// /// This function is normally used when a token provider has multiple @@ -147,7 +159,7 @@ pub fn token_kid(jwt: JWT) -> Option<String> { /// /// It is the user's task to ensure that the correct JWK is passed in /// for validation. -pub fn validate(jwt: JWT, jwk: JWK, validations: Vec<Validation>) -> ValidationResult { +pub fn validate(jwt: JWT, jwk: JWK, validations: Vec<Validation>) -> JWTResult<()> { unimplemented!() } @@ -156,18 +168,21 @@ pub fn validate(jwt: JWT, jwk: JWK, validations: Vec<Validation>) -> ValidationR // The functions in the following section are not part of the public // API of this library. -/// Decode a single key fragment to an OpenSSL BigNum. -fn decode_fragment(fragment: &str) -> Option<BigNum> { - let bytes = decode_config(fragment, URL_SAFE).ok()?; - BigNum::from_slice(&bytes).ok() +/// Decode a single key fragment (base64-url encoded integer) to an +/// OpenSSL BigNum. +fn decode_fragment(fragment: &str) -> JWTResult<BigNum> { + let bytes = decode_config(fragment, URL_SAFE) + .map_err(|_| ValidationError::InvalidJWK)?; + + BigNum::from_slice(&bytes).map_err(Into::into) } /// Decode an RSA public key from a JWK by constructing it directly /// from the public RSA key fragments. -fn public_key_from_jwk(jwk: &JWK) -> Option<Rsa<Public>> { +fn public_key_from_jwk(jwk: &JWK) -> JWTResult<Rsa<Public>> { let jwk_n = decode_fragment(&jwk.n)?; let jwk_e = decode_fragment(&jwk.e)?; - Rsa::from_public_components(jwk_n, jwk_e).ok() + Rsa::from_public_components(jwk_n, jwk_e).map_err(Into::into) } #[cfg(test)] |