mas_oidc_client/requests/
token.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2022-2024 Kévin Commaille.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7//! Requests for the Token endpoint.
8
9use chrono::{DateTime, Utc};
10use http::header::ACCEPT;
11use mas_http::RequestBuilderExt;
12use mime::APPLICATION_JSON;
13use oauth2_types::requests::{AccessTokenRequest, AccessTokenResponse};
14use rand::Rng;
15use url::Url;
16
17use crate::{
18    error::{ResponseExt, TokenRequestError},
19    types::client_credentials::ClientCredentials,
20};
21
22/// Request an access token.
23///
24/// # Arguments
25///
26/// * `http_client` - The reqwest client to use for making HTTP requests.
27///
28/// * `client_credentials` - The credentials obtained when registering the
29///   client.
30///
31/// * `token_endpoint` - The URL of the issuer's Token endpoint.
32///
33/// * `request` - The request to make at the Token endpoint.
34///
35/// * `now` - The current time.
36///
37/// * `rng` - A random number generator.
38///
39/// # Errors
40///
41/// Returns an error if the request fails or the response is invalid.
42#[tracing::instrument(skip_all, fields(token_endpoint, request))]
43pub async fn request_access_token(
44    http_client: &reqwest::Client,
45    client_credentials: ClientCredentials,
46    token_endpoint: &Url,
47    request: AccessTokenRequest,
48    now: DateTime<Utc>,
49    rng: &mut impl Rng,
50) -> Result<AccessTokenResponse, TokenRequestError> {
51    tracing::debug!(?request, "Requesting access token...");
52
53    let token_request = http_client
54        .post(token_endpoint.as_str())
55        .header(ACCEPT, APPLICATION_JSON.as_ref());
56
57    let token_response = client_credentials
58        .authenticated_form(token_request, &request, now, rng)?
59        .send_traced()
60        .await?
61        .error_from_oauth2_error_response()
62        .await?
63        .json()
64        .await?;
65
66    Ok(token_response)
67}