feat(dpop): provide nonce on immediate login
provide the DPoP nonce via cookie on login, this reduce the amount of API call and prevent having any first call returning in 401
This commit is contained in:
@@ -439,6 +439,14 @@ pub async fn login(
|
||||
state.core.config.auth.refresh_token_expiry_secs,
|
||||
);
|
||||
cookie_auth::append_csrf_cookie(response.headers_mut(), auth_response.expires_in);
|
||||
// Seed the SPA's DPoP-nonce cache so the first bound request
|
||||
// after login doesn't eat a `use_dpop_nonce` challenge → retry.
|
||||
// No-op when `dpop_mode = off`.
|
||||
cookie_auth::maybe_append_dpop_nonce_cookie(
|
||||
response.headers_mut(),
|
||||
&state.dpop_nonce_service,
|
||||
state.core.config.auth.dpop_mode,
|
||||
);
|
||||
|
||||
// Diagnostic: warn when Secure cookies are set but the request
|
||||
// arrived over plain HTTP, the browser will reject them (#241).
|
||||
@@ -604,6 +612,12 @@ pub async fn refresh_token(
|
||||
state.core.config.auth.refresh_token_expiry_secs,
|
||||
);
|
||||
cookie_auth::append_csrf_cookie(response.headers_mut(), auth_response.expires_in);
|
||||
// Seed the SPA's DPoP-nonce cache — see the login handler above.
|
||||
cookie_auth::maybe_append_dpop_nonce_cookie(
|
||||
response.headers_mut(),
|
||||
&state.dpop_nonce_service,
|
||||
state.core.config.auth.dpop_mode,
|
||||
);
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
@@ -1797,6 +1811,12 @@ pub async fn oidc_exchange(
|
||||
state.core.config.auth.refresh_token_expiry_secs,
|
||||
);
|
||||
cookie_auth::append_csrf_cookie(response.headers_mut(), auth_response.expires_in);
|
||||
// Seed the SPA's DPoP-nonce cache — see the login handler above.
|
||||
cookie_auth::maybe_append_dpop_nonce_cookie(
|
||||
response.headers_mut(),
|
||||
&state.dpop_nonce_service,
|
||||
state.core.config.auth.dpop_mode,
|
||||
);
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
|
||||
@@ -582,6 +582,17 @@ fn build_success_response(state: &Arc<AppState>, redemption: MagicLinkRedemption
|
||||
state.core.config.auth.refresh_token_expiry_secs,
|
||||
);
|
||||
cookie_auth::append_csrf_cookie(response.headers_mut(), redemption.auth.expires_in);
|
||||
// Seed the SPA's DPoP-nonce cache so the first bound request after
|
||||
// the redirect (typically the `bindDpopIfPossible` POST or the layout's
|
||||
// `session.load()` probe) has a valid nonce and doesn't eat a
|
||||
// `use_dpop_nonce` challenge → retry cycle. Cookie survives the 302
|
||||
// follow (Set-Cookie is applied by the browser across redirects,
|
||||
// unlike other response headers). No-op when `dpop_mode = off`.
|
||||
cookie_auth::maybe_append_dpop_nonce_cookie(
|
||||
response.headers_mut(),
|
||||
&state.dpop_nonce_service,
|
||||
state.core.config.auth.dpop_mode,
|
||||
);
|
||||
// Clear the request-challenge cookie — it's single-use and we don't
|
||||
// want a stale value on the browser confusing a later flow.
|
||||
cookie_auth::append_clear_magic_request_cookie(response.headers_mut());
|
||||
|
||||
@@ -829,6 +829,14 @@ pub async fn login_ke3(
|
||||
state.core.config.auth.refresh_token_expiry_secs,
|
||||
);
|
||||
cookie_auth::append_csrf_cookie(response.headers_mut(), session.expires_in);
|
||||
// Seed the SPA's DPoP-nonce cache so the first bound request after
|
||||
// login doesn't eat a `use_dpop_nonce` challenge → retry cycle.
|
||||
// No-op when `dpop_mode = off`.
|
||||
cookie_auth::maybe_append_dpop_nonce_cookie(
|
||||
response.headers_mut(),
|
||||
&state.dpop_nonce_service,
|
||||
state.core.config.auth.dpop_mode,
|
||||
);
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user