| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- //! Token-exchange rejection rows for `tests/e2e_edge_matrix.rs`.
- //!
- //! Both rows reach the real `/token` dispatcher: a missing `subject_token` is
- //! a grant-level `invalid_grant`, while a repeated known parameter is rejected
- //! by the pre-dispatch duplicate gate as `invalid_request`.
- use d_oauth::db::TokenEndpointAuthMethod;
- use reqwest::StatusCode;
- use serde_json::json;
- use super::{
- dpop::DpopKey,
- edge::ensure_error,
- harness::{SeedClientOpts, TestError, World, open_rate_limit, seed_client_bound},
- };
- /// Token-exchange grant URN (RFC 8693).
- const EXCHANGE_GRANT: &str = "urn:ietf:params:oauth:grant-type:token-exchange";
- /// Access-token type URN used for both token-type members.
- const ACCESS_TOKEN_TYPE: &str = "urn:ietf:params:oauth:token-type:access_token";
- /// Exchange caller holding the exchange grant (DPoP-bound).
- const CALLER_ID: &str = "e2e-edge-exchange-caller";
- /// Exchange caller secret.
- const CALLER_SECRET: &str = "e2e-edge-exchange-secret-1a2b3c4d5e6f708192a0";
- /// A missing `subject_token` is `invalid_grant` at the grant, not
- /// `invalid_request`.
- pub async fn missing_subject_token() -> Result<(), TestError> {
- let world = World::start_with(open_rate_limit(), json!({"allow_token_exchange": true})).await?;
- seed_client_bound(
- &world.pool,
- &world.state.keys,
- CALLER_ID,
- Some(CALLER_SECRET),
- &SeedClientOpts {
- grants: &[EXCHANGE_GRANT],
- scope: "read",
- method: TokenEndpointAuthMethod::ClientSecretBasic,
- dpop_bound: true,
- },
- )
- .await?;
- let proof =
- DpopKey::generate()?.proof("POST", &format!("{}/token", world.state.config.issuer))?;
- let (status, _, body) = world
- .post_form(
- "/token",
- &[
- ("grant_type", EXCHANGE_GRANT),
- ("subject_token_type", ACCESS_TOKEN_TYPE),
- ("requested_token_type", ACCESS_TOKEN_TYPE),
- ],
- Some((CALLER_ID, CALLER_SECRET)),
- &[("dpop", proof.as_str())],
- )
- .await?;
- ensure_error(status, &body, StatusCode::BAD_REQUEST, "invalid_grant")
- }
- /// A repeated `scope` or `grant_type` is rejected before dispatch as
- /// `invalid_request`.
- pub async fn duplicate_parameter() -> Result<(), TestError> {
- let world = World::start_with(open_rate_limit(), json!({"allow_token_exchange": true})).await?;
- let duplicate_scope = [
- ("grant_type", EXCHANGE_GRANT),
- ("subject_token", "subject"),
- ("subject_token_type", ACCESS_TOKEN_TYPE),
- ("scope", "read"),
- ("scope", "read"),
- ];
- let duplicate_grant_type = [
- ("grant_type", EXCHANGE_GRANT),
- ("grant_type", "refresh_token"),
- ("scope", "read"),
- ];
- for params in [&duplicate_scope[..], &duplicate_grant_type[..]] {
- let (status, _, body) = world.post_form("/token", params, None, &[]).await?;
- ensure_error(status, &body, StatusCode::BAD_REQUEST, "invalid_request")?;
- }
- Ok(())
- }
|