1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00

add CookieIdentityPolicy::http_only method (#102)

This commit is contained in:
Rob Ede 2020-09-17 18:10:27 +01:00 committed by GitHub
parent 400d889116
commit 6ae147d190
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 6 deletions

View File

@ -68,13 +68,13 @@ jobs:
args: --all --all-features --no-fail-fast -- --nocapture args: --all --all-features --no-fail-fast -- --nocapture
- name: Generate coverage file - name: Generate coverage file
if: matrix.version == 'stable' && (github.ref == 'master' || github.event_name == 'pull_request') if: matrix.version == 'stable' && (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
run: | run: |
cargo install cargo-tarpaulin --vers "^0.13" cargo install cargo-tarpaulin --vers "^0.13"
cargo tarpaulin --out Xml --workspace --all-features cargo tarpaulin --out Xml --workspace --all-features
- name: Upload to Codecov - name: Upload to Codecov
if: matrix.version == 'stable' && (github.ref == 'master' || github.event_name == 'pull_request') if: matrix.version == 'stable' && (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v1
with: with:
file: cobertura.xml file: cobertura.xml

View File

@ -1,6 +1,7 @@
# Changes # Changes
## Unreleased - 2020-xx-xx ## Unreleased - 2020-xx-xx
* Add method to set HttpOnly flag on cookie identity. [#102]
## 0.3.0 - 2020-09-11 ## 0.3.0 - 2020-09-11
@ -24,3 +25,8 @@
## 0.1.0 - 2019-06-xx ## 0.1.0 - 2019-06-xx
* Move identity middleware to separate crate * Move identity middleware to separate crate
<!-- PR Links -->
[#102]: https://github.com/actix/actix-extras/pull/102

View File

@ -47,7 +47,6 @@
//! } //! }
//! ``` //! ```
#![allow(clippy::needless_doctest_main)]
#![deny(rust_2018_idioms)] #![deny(rust_2018_idioms)]
use std::cell::RefCell; use std::cell::RefCell;
@ -319,6 +318,7 @@ struct CookieIdentityInner {
domain: Option<String>, domain: Option<String>,
secure: bool, secure: bool,
max_age: Option<Duration>, max_age: Option<Duration>,
http_only: Option<bool>,
same_site: Option<SameSite>, same_site: Option<SameSite>,
visit_deadline: Option<Duration>, visit_deadline: Option<Duration>,
login_deadline: Option<Duration>, login_deadline: Option<Duration>,
@ -327,14 +327,16 @@ struct CookieIdentityInner {
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
struct CookieValue { struct CookieValue {
identity: String, identity: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
login_timestamp: Option<SystemTime>, login_timestamp: Option<SystemTime>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
visit_timestamp: Option<SystemTime>, visit_timestamp: Option<SystemTime>,
} }
#[derive(Debug)] #[derive(Debug)]
struct CookieIdentityExtention { struct CookieIdentityExtension {
login_timestamp: Option<SystemTime>, login_timestamp: Option<SystemTime>,
} }
@ -349,6 +351,7 @@ impl CookieIdentityInner {
domain: None, domain: None,
secure: true, secure: true,
max_age: None, max_age: None,
http_only: None,
same_site: None, same_site: None,
visit_deadline: None, visit_deadline: None,
login_deadline: None, login_deadline: None,
@ -382,6 +385,10 @@ impl CookieIdentityInner {
cookie.set_max_age(max_age); cookie.set_max_age(max_age);
} }
if let Some(http_only) = self.http_only {
cookie.set_http_only(http_only);
}
if let Some(same_site) = self.same_site { if let Some(same_site) = self.same_site {
cookie.set_same_site(same_site); cookie.set_same_site(same_site);
} }
@ -524,6 +531,12 @@ impl CookieIdentityPolicy {
self self
} }
/// Sets the `http_only` field in the session cookie being built.
pub fn http_only(mut self, http_only: bool) -> Self {
Rc::get_mut(&mut self.0).unwrap().http_only = Some(http_only);
self
}
/// Sets the `same_site` field in the session cookie being built. /// Sets the `same_site` field in the session cookie being built.
pub fn same_site(mut self, same_site: SameSite) -> Self { pub fn same_site(mut self, same_site: SameSite) -> Self {
Rc::get_mut(&mut self.0).unwrap().same_site = Some(same_site); Rc::get_mut(&mut self.0).unwrap().same_site = Some(same_site);
@ -560,7 +573,7 @@ impl IdentityPolicy for CookieIdentityPolicy {
}| { }| {
if self.0.requires_oob_data() { if self.0.requires_oob_data() {
req.extensions_mut() req.extensions_mut()
.insert(CookieIdentityExtention { login_timestamp }); .insert(CookieIdentityExtension { login_timestamp });
} }
identity identity
}, },
@ -586,7 +599,7 @@ impl IdentityPolicy for CookieIdentityPolicy {
} else if self.0.always_update_cookie() && id.is_some() { } else if self.0.always_update_cookie() && id.is_some() {
let visit_timestamp = SystemTime::now(); let visit_timestamp = SystemTime::now();
let login_timestamp = if self.0.requires_oob_data() { let login_timestamp = if self.0.requires_oob_data() {
let CookieIdentityExtention { let CookieIdentityExtension {
login_timestamp: lt, login_timestamp: lt,
} = res.request().extensions_mut().remove().unwrap(); } = res.request().extensions_mut().remove().unwrap();
lt lt
@ -713,6 +726,37 @@ mod tests {
assert_eq!(duration, c.max_age().unwrap()); assert_eq!(duration, c.max_age().unwrap());
} }
#[actix_rt::test]
async fn test_http_only_same_site() {
let mut srv = test::init_service(
App::new()
.wrap(IdentityService::new(
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
.domain("www.rust-lang.org")
.name(COOKIE_NAME)
.path("/")
.http_only(true)
.same_site(SameSite::None),
))
.service(web::resource("/login").to(|id: Identity| {
id.remember("test".to_string());
HttpResponse::Ok()
})),
)
.await;
let resp =
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
.await;
assert_eq!(resp.status(), StatusCode::OK);
assert!(resp.headers().contains_key(header::SET_COOKIE));
let c = resp.response().cookies().next().unwrap().to_owned();
assert!(c.http_only().unwrap());
assert_eq!(SameSite::None, c.same_site().unwrap());
}
#[actix_rt::test] #[actix_rt::test]
async fn test_identity_max_age() { async fn test_identity_max_age() {
let seconds = 60; let seconds = 60;