http-signatures 0.8.0

An implementation of the HTTP Signatures RFC
// This file is part of HTTP Signatures

// HTTP Signatures is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// HTTP Signatures is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with HTTP Signatures  If not, see <http://www.gnu.org/licenses/>.

//! Available with the `use_rocket` feature. This module defines `VerifyHeader` for
//! `rocket::Request`.
//!
//! This allows easy verification of incomming requests in Rocket, and can be used with Request
//! guards.
//!
//! See
//! [this example](https://git.asonix.dog/asonix/http-signatures/src/branch/master/examples/rocket-server)
//! for usage information.

use rocket::Request;

use crate::{
    error::VerificationError,
    prelude::*,
    verify::{SignedHeader, VerifyKey},
};

impl<'r> VerifyHeader for Request<'r> {
    fn verify_signature_header(&self, key: VerifyKey) -> Result<(), VerificationError> {
        verify_header(self, "Signature", key)
    }

    fn verify_authorization_header(&self, key: VerifyKey) -> Result<(), VerificationError> {
        verify_header(self, "Authorization", key)
    }
}

fn verify_header<'r>(
    req: &Request<'r>,
    header: &str,
    key: VerifyKey,
) -> Result<(), VerificationError> {
    let auth_header = req
        .headers()
        .get_one(header)
        .ok_or(VerificationError::HeaderNotPresent)?;

    let auth_header = SignedHeader::new(auth_header)?;

    let headers: Vec<(String, String)> = req
        .headers()
        .iter()
        .map(|header| (header.name().into(), header.value().into()))
        .collect();

    let headers_borrowed: Vec<(&str, &str)> = headers
        .iter()
        .map(|&(ref key, ref val)| (key.as_ref(), val.as_ref()))
        .collect();

    auth_header.verify(
        headers_borrowed.as_ref(),
        req.method().as_str(),
        req.uri().path(),
        req.uri().query(),
        key,
    )
}