Skip to content

Commit 245b530

Browse files
committed
feat: provide better error message for expired refresh token
1 parent 362e06e commit 245b530

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

src/cmd/list.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl List {
5353
}
5454

5555
if let Some(state) = &client.state {
56-
let access = self.token::<_, AccessTokenClaims>(&state.access_token, |token| {
56+
let access = Self::token::<_, AccessTokenClaims>(&state.access_token, |token| {
5757
self.expiration(
5858
token
5959
.exp
@@ -67,7 +67,7 @@ impl List {
6767
.refresh_token
6868
.as_ref()
6969
.map(|refresh| {
70-
self.token::<_, RefreshTokenClaims>(refresh, |token| {
70+
Self::token::<_, RefreshTokenClaims>(refresh, |token| {
7171
self.expiration(
7272
token
7373
.exp
@@ -91,7 +91,7 @@ impl List {
9191
/// Decode a token and call the function to extract cell information
9292
///
9393
/// NOTE: The token is not being verified.
94-
fn token<F, T>(&self, token: &str, f: F) -> Cell
94+
fn token<F, T>(token: &str, f: F) -> Cell
9595
where
9696
F: FnOnce(T) -> Cell,
9797
T: CompactJson,

src/oidc.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use crate::{
2+
claims::RefreshTokenClaims,
23
config::{Client, ClientState, ClientType},
34
http::{HttpOptions, create_client},
45
utils::OrNone,
56
};
67
use anyhow::{anyhow, bail};
8+
use biscuit::{Empty, jws::Compact};
79
use oauth2::RefreshToken;
810
use openidconnect::{
911
ClientId, ClientSecret, IssuerUrl, Scope,
@@ -18,6 +20,8 @@ pub enum TokenResult {
1820

1921
/// Fetch a new token
2022
pub async fn fetch_token(config: &Client, http: &HttpOptions) -> anyhow::Result<TokenResult> {
23+
log::debug!("Fetching new token");
24+
2125
let http = create_client(http).await?;
2226

2327
match &config.r#type {
@@ -61,14 +65,29 @@ pub async fn fetch_token(config: &Client, http: &HttpOptions) -> anyhow::Result<
6165
)
6266
.await?;
6367

68+
let refresh_token = state.refresh_token.clone().ok_or_else(|| anyhow!("Expired token of a public client, without having a refresh token. You will need to re-login."))?;
69+
70+
if let Ok(token) = Compact::<RefreshTokenClaims, Empty>::new_encoded(&refresh_token)
71+
.unverified_payload()
72+
{
73+
log::debug!("refresh token expiration: {:?}", token.exp);
74+
75+
if let Some(exp) = token
76+
.exp
77+
.and_then(|exp| OffsetDateTime::from_unix_timestamp(exp).ok())
78+
{
79+
if exp < OffsetDateTime::now_utc() {
80+
bail!("Refresh token expired. You need to re-login.");
81+
}
82+
}
83+
}
84+
6485
let client = CoreClient::from_provider_metadata(
6586
provider_metadata,
6687
ClientId::new(client_id.clone()),
6788
client_secret.clone().map(ClientSecret::new),
6889
);
6990

70-
let refresh_token= state.refresh_token.clone().ok_or_else(|| anyhow!("Expired token of a public client, without having a refresh token. You will need to re-login."))?;
71-
7291
let token = client
7392
.exchange_refresh_token(&RefreshToken::new(refresh_token))?
7493
.add_scopes(extra_scopes(config.scope.as_deref()))

0 commit comments

Comments
 (0)