Skip to main content

begin_authorization

Function begin_authorization 

Source
pub fn begin_authorization(
    model: &AuthorizationModel,
    client: &RegisteredClient,
    redirect_uri: &str,
    resource: ResourceParameters,
    secrets: &impl AuthorizationSecrets,
) -> Result<PendingAuthorization, BeginError>
Expand description

Build the authorization request and the state a client must keep for it.

§Errors

BeginError::Secrets if the source cannot produce both unguessable values, BeginError::Resource when the revision requires a resource indicator and the caller named none, and BeginError::Endpoint when the endpoint will not parse.

The result is deliberately a pair — the URL and the pending value — because the two are easy to take independently and must not be: a client that renders the URL and then persists a different pending value has a state mismatch on return and no way to tell whether that is an attack or a bug.

§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};
use protocol_droid::application::oauth::client::begin_authorization;
use protocol_droid::domain::oauth::pkce::{ChallengeMethod, CodeVerifier};

struct Fixed;
impl AuthorizationSecrets for Fixed {
    fn new_state(&self) -> Result<protocol_droid::application::oauth::client::State, SecretError> {
        Ok(protocol_droid::application::oauth::client::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 url = pending.authorization_url("https://auth.example.com/authorize", ChallengeMethod::S256)?;
assert!(url.as_str().contains("code_challenge_method=S256"));
assert!(url.as_str().contains("resource=https%3A%2F%2Fapi.example.com%2Fapp"));