mirror of
https://github.com/pfzetto/axum-oidc.git
synced 2024-11-21 11:02:50 +01:00
Merge Pull Request #5 "feat: Handle Grant error while refreshing token"
Expired refresh_tokens weren't removed from the session causing a 500 Internal Server Error. This PR removes the invalid request token when it is expired.
This commit is contained in:
commit
8d0be319ad
1 changed files with 50 additions and 33 deletions
|
@ -15,9 +15,12 @@ use tower_service::Service;
|
||||||
use tower_sessions::Session;
|
use tower_sessions::Session;
|
||||||
|
|
||||||
use openidconnect::{
|
use openidconnect::{
|
||||||
core::CoreAuthenticationFlow, reqwest::async_http_client, AccessTokenHash, AuthorizationCode,
|
core::{CoreAuthenticationFlow, CoreErrorResponseType},
|
||||||
CsrfToken, Nonce, OAuth2TokenResponse, PkceCodeChallenge, PkceCodeVerifier, RedirectUrl, Scope,
|
reqwest::async_http_client,
|
||||||
TokenResponse,
|
AccessTokenHash, AuthorizationCode, CsrfToken, Nonce, OAuth2TokenResponse, PkceCodeChallenge,
|
||||||
|
PkceCodeVerifier, RedirectUrl,
|
||||||
|
RequestTokenError::ServerResponse,
|
||||||
|
Scope, TokenResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -343,39 +346,53 @@ where
|
||||||
refresh_request.add_scope(Scope::new(scope.to_string()));
|
refresh_request.add_scope(Scope::new(scope.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let token_response =
|
match refresh_request.request_async(async_http_client).await {
|
||||||
refresh_request.request_async(async_http_client).await?;
|
Ok(token_response) => {
|
||||||
|
// Extract the ID token claims after verifying its authenticity and nonce.
|
||||||
|
let id_token = token_response
|
||||||
|
.id_token()
|
||||||
|
.ok_or(MiddlewareError::IdTokenMissing)?;
|
||||||
|
let claims = id_token.claims(
|
||||||
|
&oidcclient.client.id_token_verifier(),
|
||||||
|
&login_session.nonce,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Extract the ID token claims after verifying its authenticity and nonce.
|
// Verify the access token hash to ensure that the access token hasn't been substituted for
|
||||||
let id_token = token_response
|
// another user's.
|
||||||
.id_token()
|
if let Some(expected_access_token_hash) = claims.access_token_hash()
|
||||||
.ok_or(MiddlewareError::IdTokenMissing)?;
|
{
|
||||||
let claims = id_token
|
let actual_access_token_hash = AccessTokenHash::from_token(
|
||||||
.claims(&oidcclient.client.id_token_verifier(), &login_session.nonce)?;
|
token_response.access_token(),
|
||||||
|
&id_token.signing_alg()?,
|
||||||
|
)?;
|
||||||
|
if actual_access_token_hash != *expected_access_token_hash {
|
||||||
|
return Err(MiddlewareError::AccessTokenHashInvalid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the access token hash to ensure that the access token hasn't been substituted for
|
login_session.id_token = Some(id_token.to_string());
|
||||||
// another user's.
|
login_session.access_token =
|
||||||
if let Some(expected_access_token_hash) = claims.access_token_hash() {
|
Some(token_response.access_token().secret().to_string());
|
||||||
let actual_access_token_hash = AccessTokenHash::from_token(
|
login_session.refresh_token = token_response
|
||||||
token_response.access_token(),
|
.refresh_token()
|
||||||
&id_token.signing_alg()?,
|
.map(|x| x.secret().to_string());
|
||||||
)?;
|
|
||||||
if actual_access_token_hash != *expected_access_token_hash {
|
parts.extensions.insert(OidcClaims(claims.clone()));
|
||||||
return Err(MiddlewareError::AccessTokenHashInvalid);
|
parts.extensions.insert(OidcAccessToken(
|
||||||
|
login_session.access_token.clone().unwrap_or_default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
Err(ServerResponse(e))
|
||||||
|
if *e.error() == CoreErrorResponseType::InvalidGrant =>
|
||||||
login_session.id_token = Some(id_token.to_string());
|
{
|
||||||
login_session.access_token =
|
// Refresh failed, refresh_token most likely expired or
|
||||||
Some(token_response.access_token().secret().to_string());
|
// invalid, the session can be considered lost
|
||||||
login_session.refresh_token = token_response
|
login_session.refresh_token = None;
|
||||||
.refresh_token()
|
}
|
||||||
.map(|x| x.secret().to_string());
|
Err(err) => {
|
||||||
|
return Err(err.into());
|
||||||
parts.extensions.insert(OidcClaims(claims.clone()));
|
}
|
||||||
parts.extensions.insert(OidcAccessToken(
|
};
|
||||||
login_session.access_token.clone().unwrap_or_default(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let session = parts
|
let session = parts
|
||||||
.extensions
|
.extensions
|
||||||
|
|
Loading…
Reference in a new issue