Skip to main content

authorize_callback

Function authorize_callback 

Source
pub fn authorize_callback(
    model: &AuthorizationModel,
    pending: &PendingAuthorization,
    callback: &AuthorizationCallback,
) -> Result<AuthorizedCode, CallbackError>
Expand description

Validate an authorization callback against the request that started it.

Checks, in this order and for the reasons in the module documentation: state, then iss, then whether the response carries a grant or a refusal.

§Errors

CallbackError::StateMismatch if the state is absent or different — checked first so that neither a forged success nor a forged refusal can be acted on. CallbackError::Issuer if a present iss names another server. CallbackError::Refused if the server refused, carrying its error code. CallbackError::NoOutcome if the response carries neither a code nor an error.

§Examples

use protocol_droid::domain::ProtocolVersion;
use protocol_droid::domain::mcp::authorization::authorization_model;
use protocol_droid::domain::mcp::resource_metadata::ResourceUri;
use protocol_droid::domain::oauth::registration::{ClientId, RegisteredClient};
use protocol_droid::domain::oauth::resource::ResourceParameters;
use protocol_droid::application::oauth::client::{AuthorizationSecrets, SecretError, State, begin_authorization};
use protocol_droid::application::oauth::callback::{AuthorizationCallback, authorize_callback};
use protocol_droid::domain::oauth::pkce::{ChallengeMethod, CodeVerifier};

struct Fixed;
impl AuthorizationSecrets for Fixed {
    fn new_state(&self) -> Result<State, SecretError> { Ok(State::new("state-value")) }
    fn new_code_verifier(&self) -> Result<CodeVerifier, SecretError> {
        CodeVerifier::new("a".repeat(43)).map_err(|_| SecretError::Rejected)
    }
}

let model = authorization_model(ProtocolVersion::V2026_07_28);
let client = RegisteredClient::from_metadata_document(
    "https://auth.example.com",
    ClientId::metadata_url("https://client.example.com/metadata.json")?,
);
let resource = ResourceUri::new("https://api.example.com/app")?;
let pending = begin_authorization(
    &model, &client, "https://client.example.com/callback",
    ResourceParameters::single(&resource), &Fixed,
)?;

let callback = AuthorizationCallback::granted("the-code", "state-value");
let authorized = authorize_callback(&model, &pending, &callback)?;
assert_eq!(authorized.code(), "the-code");
assert!(authorize_callback(&model, &pending, &AuthorizationCallback::granted("c", "wrong")).is_err());