Skip to content

Commit 2aecf6e

Browse files
authored
feat: add DISABLE_REFRESH_TOKEN_NBF to disable refresh_token.nbf (#653)
* add `DISABLE_REFRESH_TOKEN_NBF` * add "catch all" error log on the `/token` endpoint * update reference config
1 parent cfa04e7 commit 2aecf6e

File tree

8 files changed

+78
-5
lines changed

8 files changed

+78
-5
lines changed

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# Changelog
22

3+
## UNRELEASED
4+
5+
### Changes
6+
7+
Even though not recommended at all, it is not possible to opt-out of the `refresh_token` nbf claim, and disable it.
8+
9+
By default, A `refresh_token` will not valid before `access_token_lifetime - 60 seconds`, but some (bad) client
10+
implementations try to refresh `access_tokens` while they are still valid for a long time. To opt-out, you get a new
11+
config variable:
12+
13+
```
14+
# By default, `refresh_token`s will have an `nbf` claim, making them valid
15+
# at `access_token_lifetime - 60 seconds`. Any usage before this time will
16+
# result in invalidation of not only the token itself, but also all other
17+
# linked sessions and tokens for this user to prevent damage in case a client
18+
# leaked the token by accident.
19+
# However, there are bad / lazy client implementations that do not respect
20+
# either `nbf` in the `refresh_token`, or the `exp` claim in `access_token`
21+
# and will refresh early while the current access_token is still valid.
22+
# This does not only waste resources and time, but also makes it possible
23+
# to have multiple valid `access_token`s at the same time for the same
24+
# session. You should only disable the `nbf` claim if you have a good
25+
# reasons to do so.
26+
# If disabled, the `nbf` claim will still exist, but always set to *now*.
27+
# default: false
28+
DISABLE_REFRESH_TOKEN_NBF=false
29+
```
30+
31+
[]()
32+
333
## v0.27.1
434

535
### Bugfix

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

book/src/config/config.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ deploying with Kubernetes, extract these values into Kubernetes Secrets.
6262
# default: false
6363
#DANGER_DISABLE_INTROSPECT_AUTH=false
6464
65+
# By default, `refresh_token`s will have an `nbf` claim, making them valid
66+
# at `access_token_lifetime - 60 seconds`. Any usage before this time will
67+
# result in invalidation of not only the token itself, but also all other
68+
# linked sessions and tokens for this user to prevent damage in case a client
69+
# leaked the token by accident.
70+
# However, there are bad / lazy client implementations that do not respect
71+
# either `nbf` in the `refresh_token`, or the `exp` claim in `access_token`
72+
# and will refresh early while the current access_token is still valid.
73+
# This does not only waste resources and time, but also makes it possible
74+
# to have multiple valid `access_token`s at the same time for the same
75+
# session. You should only disable the `nbf` claim if you have a good
76+
# reasons to do so.
77+
# If disabled, the `nbf` claim will still exist, but always set to *now*.
78+
# default: false
79+
#DISABLE_REFRESH_TOKEN_NBF=false
80+
6581
# Can be used when 'OPEN_USER_REG=true' to restrict the domains
6682
# for a registration. For instance, set it to
6783
# 'USER_REG_DOMAIN_RESTRICTION=gmail.com' to allow only

rauthy.cfg

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@ USERINFO_STRICT=true
5757
# default: false
5858
#DANGER_DISABLE_INTROSPECT_AUTH=false
5959

60+
# By default, `refresh_token`s will have an `nbf` claim, making them valid
61+
# at `access_token_lifetime - 60 seconds`. Any usage before this time will
62+
# result in invalidation of not only the token itself, but also all other
63+
# linked sessions and tokens for this user to prevent damage in case a client
64+
# leaked the token by accident.
65+
# However, there are bad / lazy client implementations that do not respect
66+
# either `nbf` in the `refresh_token`, or the `exp` claim in `access_token`
67+
# and will refresh early while the current access_token is still valid.
68+
# This does not only waste resources and time, but also makes it possible
69+
# to have multiple valid `access_token`s at the same time for the same
70+
# session. You should only disable the `nbf` claim if you have a good
71+
# reasons to do so.
72+
# If disabled, the `nbf` claim will still exist, but always set to *now*.
73+
# default: false
74+
#DISABLE_REFRESH_TOKEN_NBF=false
75+
6076
# Can be used when 'OPEN_USER_REG=true' to restrict the domains for a registration. For instance, set it to
6177
# 'USER_REG_DOMAIN_RESTRICTION=gmail.com' to allow only registrations with 'user@gmail.com'.
6278
# default: ''

src/api/src/oidc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ pub async fn post_token(
907907
Ok(resp)
908908
}
909909
Err(err) => {
910+
error!("{}", err.message);
910911
if !has_password_been_hashed {
911912
return Err(err);
912913
}

src/common/src/constants.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ lazy_static! {
170170
.unwrap_or_else(|_| String::from("false"))
171171
.parse::<bool>()
172172
.expect("DANGER_DISABLE_INTROSPECT_AUTH cannot be parsed to bool - bad format");
173+
pub static ref DISABLE_REFRESH_TOKEN_NBF: bool = env::var("DISABLE_REFRESH_TOKEN_NBF")
174+
.unwrap_or_else(|_| String::from("false"))
175+
.parse::<bool>()
176+
.expect("DISABLE_REFRESH_TOKEN_NBF cannot be parsed to bool - bad format");
173177

174178
pub static ref SEC_HEADER_BLOCK: bool = env::var("SEC_HEADER_BLOCK")
175179
.unwrap_or_else(|_| String::from("true"))

src/common/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2024 Sebastian Dobe <sebastiandobe@mailbox.org>
22
#![forbid(unsafe_code)]
33
// needed because the lazy_static! initialization of constants grew quite a bit
4-
#![recursion_limit = "256"]
4+
#![recursion_limit = "512"]
55

66
use crate::constants::DB_TYPE;
77
use std::env;

src/service/src/token_set.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use jwt_simple::claims::Claims;
55
use jwt_simple::prelude::{coarsetime, UnixTimeStamp};
66
use rauthy_api_types::oidc::JktClaim;
77
use rauthy_common::constants::{
8-
DEVICE_GRANT_REFRESH_TOKEN_LIFETIME, ENABLE_SOLID_AUD, ENABLE_WEB_ID, REFRESH_TOKEN_LIFETIME,
8+
DEVICE_GRANT_REFRESH_TOKEN_LIFETIME, DISABLE_REFRESH_TOKEN_NBF, ENABLE_SOLID_AUD,
9+
ENABLE_WEB_ID, REFRESH_TOKEN_LIFETIME,
910
};
1011
use rauthy_common::utils::base64_url_no_pad_encode;
1112
use rauthy_error::{ErrorResponse, ErrorResponseType};
@@ -382,7 +383,11 @@ impl TokenSet {
382383
did: did.clone(),
383384
};
384385

385-
let nbf = Utc::now().add(chrono::Duration::seconds(access_token_lifetime - 60));
386+
let nbf = if *DISABLE_REFRESH_TOKEN_NBF {
387+
Utc::now()
388+
} else {
389+
Utc::now().add(chrono::Duration::seconds(access_token_lifetime - 60))
390+
};
386391
let nbf_unix = UnixTimeStamp::from_secs(nbf.timestamp() as u64);
387392

388393
let claims =

0 commit comments

Comments
 (0)