huskarl 0.9.1

A modern OAuth2 client library.
Documentation
# Client credentials grant

[`ClientCredentialsGrant`](crate::grant::client_credentials::ClientCredentialsGrant)
(RFC 6749 ยง4.4) is used when the client is acting on its own behalf, not on
behalf of a user.

## 1. Set up your HTTP client and client authentication

See [Setting up an HTTP client and client
authentication](crate::_docs::guide::setup) for the shared setup the rest of
this page assumes. Client credentials **requires** authentication: the client
acts on its own behalf, so its credentials *are* the grant. The examples below
use a `ClientSecret`.

## 2a. Set up the grant with authorization server metadata

```rust
use huskarl::{
    core::{client_auth::ClientSecret, server_metadata::AuthorizationServerMetadata},
    grant::client_credentials::ClientCredentialsGrant,
};
# use huskarl::core::http::HttpClient;
# use huskarl::core::secrets::EnvVarSecret;
# use huskarl::core::secrets::encodings::StringEncoding;
# async fn setup_grant() -> Result<(), Box<dyn std::error::Error>> {
# let client = huskarl_reqwest::ReqwestClient::builder()
#     .build()
#     .await?;
#
# let env_secret = EnvVarSecret::new("CLIENT_SECRET", &StringEncoding)?;
# let client_auth: ClientSecret = ClientSecret::new(env_secret);

let metadata = AuthorizationServerMetadata::fetch()
    .http_client(&client)
    .issuer("https://my-issuer")
    .call()
    .await?;

let grant: ClientCredentialsGrant = ClientCredentialsGrant::builder_from_metadata(&metadata)
    .client_id("client_id")
    .http_client(client)
    .client_auth(client_auth)
    .build();
# Ok(())
# }
```

## 2b. Alternative: Set up the grant without metadata

```rust
use huskarl::{
    core::client_auth::ClientSecret, grant::client_credentials::ClientCredentialsGrant,
};
# use huskarl::core::http::HttpClient;
# use huskarl::core::secrets::EnvVarSecret;
# use huskarl::core::secrets::encodings::StringEncoding;
# async fn setup_grant() -> Result<(), Box<dyn std::error::Error>> {
# let client = huskarl_reqwest::ReqwestClient::builder()
#     .build()
#     .await?;
#
# let env_secret = EnvVarSecret::new("CLIENT_SECRET", &StringEncoding)?;
# let client_auth: ClientSecret = ClientSecret::new(env_secret);

let grant: ClientCredentialsGrant = ClientCredentialsGrant::builder()
    .token_endpoint("https://my-server/token".parse()?)
    .client_id("client_id")
    .http_client(client)
    .client_auth(client_auth)
    .build();
# Ok(())
# }
```

## 3. Get an access token

```rust
use huskarl::prelude::*; // Imports OAuth2ExchangeGrant which defines the exchange call.
use huskarl::grant::client_credentials::ClientCredentialsGrantParameters;
use huskarl::token::AccessToken;
# use huskarl::grant::client_credentials::ClientCredentialsGrant;
use huskarl::core::client_auth::ClientSecret;
# use huskarl::core::http::HttpClient;
# use huskarl::core::secrets::EnvVarSecret;
# use huskarl::core::secrets::encodings::StringEncoding;
# async fn setup_grant() -> Result<(), Box<dyn std::error::Error>> {
# let client = huskarl_reqwest::ReqwestClient::builder()
#     .build()
#     .await?;
#
# let client_auth: ClientSecret = ClientSecret::new(EnvVarSecret::new("CLIENT_SECRET", &StringEncoding)?);
#
# let grant: ClientCredentialsGrant = ClientCredentialsGrant::builder()
#     .token_endpoint("https://my-server/token".parse()?)
#     .client_id("client_id")
#     .http_client(client)
#     .client_auth(client_auth)
#     .build();

let params = ClientCredentialsGrantParameters::builder().scope(bon::vec!["read", "write"]).build();
let response = grant.exchange(params).await?;
let token: &AccessToken = response.access_token();

# Ok(())
# }
```