Browse Source

Use 'ring' and 'base64' instead of 'rand' for state generation.

tags/0.2.0-rc.1
Jeb Rosen 4 months ago
parent
commit
e7389c7949
3 changed files with 22 additions and 8 deletions
  1. +2
    -1
      Cargo.toml
  2. +20
    -2
      src/core.rs
  3. +0
    -5
      src/lib.rs

+ 2
- 1
Cargo.toml View File

@@ -18,8 +18,9 @@ default = ["hyper_sync_rustls_adapter"]
hyper_sync_rustls_adapter = ["hyper", "hyper-sync-rustls"]

[dependencies]
base64 = "0.10"
log = "0.4.4"
rand = "0.7"
ring = { version = "0.13", default-features = false }
rocket = { version = "0.4", default-features = false, features = ["private-cookies"] }
serde_json = "1.0"
url = "2.0"


+ 20
- 2
src/core.rs View File

@@ -1,5 +1,6 @@
use std::fmt;

use ring::rand::{SecureRandom, SystemRandom};
use rocket::fairing::{AdHoc, Fairing};
use rocket::handler;
use rocket::http::uri::Absolute;
@@ -14,6 +15,19 @@ use crate::{Error, ErrorKind, OAuthConfig};

const STATE_COOKIE_NAME: &str = "rocket_oauth2_state";

// Random generation of state for defense against CSRF.
// See RFC 6749 §10.12 for more details.
fn generate_state(rng: &dyn SecureRandom) -> Result<String, Error> {
let mut buf = [0; 16]; // 128 bits
rng.fill(&mut buf).map_err(|_| {
Error::new_from(
ErrorKind::Other,
String::from("Failed to generate random data"),
)
})?;
Ok(base64::encode_config(&buf, base64::URL_SAFE_NO_PAD))
}

/// The token types which can be exchanged with the token endpoint
#[derive(Clone, PartialEq, Debug)]
pub enum TokenRequest {
@@ -181,6 +195,7 @@ pub struct OAuth2<C> {
callback: C,
config: OAuthConfig,
login_scopes: Vec<String>,
rng: SystemRandom,
}

impl<C: Callback> OAuth2<C> {
@@ -250,6 +265,7 @@ impl<C: Callback> OAuth2<C> {
callback,
config,
login_scopes,
rng: SystemRandom::new(),
};

AdHoc::on_attach("OAuth Mount", |rocket| {
@@ -264,8 +280,10 @@ impl<C: Callback> OAuth2<C> {
cookies: &mut Cookies<'_>,
scopes: &[&str],
) -> Result<Redirect, Error> {
let state = super::generate_state();
let uri = self.adapter.authorization_uri(&self.config, &state, scopes)?;
let state = generate_state(&self.rng)?;
let uri = self
.adapter
.authorization_uri(&self.config, &state, scopes)?;
cookies.add_private(
Cookie::build(STATE_COOKIE_NAME, state)
.same_site(SameSite::Lax)


+ 0
- 5
src/lib.rs View File

@@ -139,8 +139,3 @@ pub use self::provider::*;

#[cfg(feature = "hyper_sync_rustls_adapter")]
pub mod hyper_sync_rustls_adapter;

fn generate_state() -> String {
use rand::{distributions::Alphanumeric, thread_rng, Rng};
thread_rng().sample_iter(&Alphanumeric).take(20).collect()
}

Loading…
Cancel
Save