use crate::{
AccessToken, AuthType, AuthUrl, AuthorizationCode, AuthorizationRequest,
ClientCredentialsTokenRequest, ClientId, ClientSecret, CodeTokenRequest, ConfigurationError,
CsrfToken, DeviceAccessTokenRequest, DeviceAuthorizationRequest, DeviceAuthorizationResponse,
DeviceAuthorizationUrl, ErrorResponse, ExtraDeviceAuthorizationFields, IntrospectionRequest,
IntrospectionUrl, PasswordTokenRequest, RedirectUrl, RefreshToken, RefreshTokenRequest,
ResourceOwnerPassword, ResourceOwnerUsername, RevocableToken, RevocationRequest, RevocationUrl,
TokenIntrospectionResponse, TokenResponse, TokenUrl,
};
use std::marker::PhantomData;
mod private {
pub trait EndpointStateSealed {}
}
pub trait EndpointState: private::EndpointStateSealed {}
#[derive(Clone, Debug)]
pub struct EndpointNotSet;
impl EndpointState for EndpointNotSet {}
impl private::EndpointStateSealed for EndpointNotSet {}
#[derive(Clone, Debug)]
pub struct EndpointSet;
impl EndpointState for EndpointSet {}
impl private::EndpointStateSealed for EndpointSet {}
#[derive(Clone, Debug)]
pub struct EndpointMaybeSet;
impl EndpointState for EndpointMaybeSet {}
impl private::EndpointStateSealed for EndpointMaybeSet {}
#[derive(Clone, Debug)]
pub struct Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl = EndpointNotSet,
HasDeviceAuthUrl = EndpointNotSet,
HasIntrospectionUrl = EndpointNotSet,
HasRevocationUrl = EndpointNotSet,
HasTokenUrl = EndpointNotSet,
> where
TE: ErrorResponse,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub(crate) client_id: ClientId,
pub(crate) client_secret: Option<ClientSecret>,
pub(crate) auth_url: Option<AuthUrl>,
pub(crate) auth_type: AuthType,
pub(crate) token_url: Option<TokenUrl>,
pub(crate) redirect_url: Option<RedirectUrl>,
pub(crate) introspection_url: Option<IntrospectionUrl>,
pub(crate) revocation_url: Option<RevocationUrl>,
pub(crate) device_authorization_url: Option<DeviceAuthorizationUrl>,
#[allow(clippy::type_complexity)]
pub(crate) phantom: PhantomData<(
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
)>,
}
impl<TE, TR, TIR, RT, TRE>
Client<
TE,
TR,
TIR,
RT,
TRE,
EndpointNotSet,
EndpointNotSet,
EndpointNotSet,
EndpointNotSet,
EndpointNotSet,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
{
pub fn new(client_id: ClientId) -> Self {
Self {
client_id,
client_secret: None,
auth_url: None,
auth_type: AuthType::BasicAuth,
token_url: None,
redirect_url: None,
introspection_url: None,
revocation_url: None,
device_authorization_url: None,
phantom: PhantomData,
}
}
}
impl<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn set_auth_type(mut self, auth_type: AuthType) -> Self {
self.auth_type = auth_type;
self
}
pub fn set_auth_uri(
self,
auth_url: AuthUrl,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
EndpointSet,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: Some(auth_url),
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: self.revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_auth_uri_option(
self,
auth_url: Option<AuthUrl>,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
EndpointMaybeSet,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: self.revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_client_secret(mut self, client_secret: ClientSecret) -> Self {
self.client_secret = Some(client_secret);
self
}
pub fn set_device_authorization_url(
self,
device_authorization_url: DeviceAuthorizationUrl,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
EndpointSet,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: self.revocation_url,
device_authorization_url: Some(device_authorization_url),
phantom: PhantomData,
}
}
pub fn set_device_authorization_url_option(
self,
device_authorization_url: Option<DeviceAuthorizationUrl>,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
EndpointMaybeSet,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: self.revocation_url,
device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_introspection_url(
self,
introspection_url: IntrospectionUrl,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
EndpointSet,
HasRevocationUrl,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: Some(introspection_url),
revocation_url: self.revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_introspection_url_option(
self,
introspection_url: Option<IntrospectionUrl>,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
EndpointMaybeSet,
HasRevocationUrl,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url,
revocation_url: self.revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_redirect_uri(mut self, redirect_url: RedirectUrl) -> Self {
self.redirect_url = Some(redirect_url);
self
}
pub fn set_revocation_url(
self,
revocation_url: RevocationUrl,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
EndpointSet,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: Some(revocation_url),
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_revocation_url_option(
self,
revocation_url: Option<RevocationUrl>,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
EndpointMaybeSet,
HasTokenUrl,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: self.token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_token_uri(
self,
token_url: TokenUrl,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
EndpointSet,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url: Some(token_url),
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: self.revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn set_token_uri_option(
self,
token_url: Option<TokenUrl>,
) -> Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
EndpointMaybeSet,
> {
Client {
client_id: self.client_id,
client_secret: self.client_secret,
auth_url: self.auth_url,
auth_type: self.auth_type,
token_url,
redirect_url: self.redirect_url,
introspection_url: self.introspection_url,
revocation_url: self.revocation_url,
device_authorization_url: self.device_authorization_url,
phantom: PhantomData,
}
}
pub fn client_id(&self) -> &ClientId {
&self.client_id
}
pub fn auth_type(&self) -> &AuthType {
&self.auth_type
}
pub fn redirect_uri(&self) -> Option<&RedirectUrl> {
self.redirect_url.as_ref()
}
}
impl<
TE,
TR,
TIR,
RT,
TRE,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
Client<
TE,
TR,
TIR,
RT,
TRE,
EndpointSet,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn auth_uri(&self) -> &AuthUrl {
self.auth_url.as_ref().expect("should have auth_url")
}
pub fn authorize_url<S>(&self, state_fn: S) -> AuthorizationRequest
where
S: FnOnce() -> CsrfToken,
{
self.authorize_url_impl(self.auth_uri(), state_fn)
}
}
impl<
TE,
TR,
TIR,
RT,
TRE,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
Client<
TE,
TR,
TIR,
RT,
TRE,
EndpointMaybeSet,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn auth_uri(&self) -> Option<&AuthUrl> {
self.auth_url.as_ref()
}
pub fn authorize_url<S>(&self, state_fn: S) -> Result<AuthorizationRequest, ConfigurationError>
where
S: FnOnce() -> CsrfToken,
{
Ok(self.authorize_url_impl(
self.auth_uri()
.ok_or(ConfigurationError::MissingUrl("authorization"))?,
state_fn,
))
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasDeviceAuthUrl, HasIntrospectionUrl, HasRevocationUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
EndpointSet,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
{
pub fn exchange_client_credentials(&self) -> ClientCredentialsTokenRequest<TE, TR> {
self.exchange_client_credentials_impl(self.token_uri())
}
pub fn exchange_code(&self, code: AuthorizationCode) -> CodeTokenRequest<TE, TR> {
self.exchange_code_impl(self.token_uri(), code)
}
pub fn exchange_device_access_token<'a, EF>(
&'a self,
auth_response: &'a DeviceAuthorizationResponse<EF>,
) -> DeviceAccessTokenRequest<'a, 'static, TR, EF>
where
EF: ExtraDeviceAuthorizationFields,
{
self.exchange_device_access_token_impl(self.token_uri(), auth_response)
}
pub fn exchange_password<'a>(
&'a self,
username: &'a ResourceOwnerUsername,
password: &'a ResourceOwnerPassword,
) -> PasswordTokenRequest<'a, TE, TR> {
self.exchange_password_impl(self.token_uri(), username, password)
}
pub fn exchange_refresh_token<'a>(
&'a self,
refresh_token: &'a RefreshToken,
) -> RefreshTokenRequest<'a, TE, TR> {
self.exchange_refresh_token_impl(self.token_uri(), refresh_token)
}
pub fn token_uri(&self) -> &TokenUrl {
self.token_url.as_ref().expect("should have token_url")
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasDeviceAuthUrl, HasIntrospectionUrl, HasRevocationUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
EndpointMaybeSet,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
{
pub fn exchange_client_credentials(
&self,
) -> Result<ClientCredentialsTokenRequest<TE, TR>, ConfigurationError> {
Ok(self.exchange_client_credentials_impl(
self.token_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("token"))?,
))
}
pub fn exchange_code(
&self,
code: AuthorizationCode,
) -> Result<CodeTokenRequest<TE, TR>, ConfigurationError> {
Ok(self.exchange_code_impl(
self.token_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("token"))?,
code,
))
}
pub fn exchange_device_access_token<'a, EF>(
&'a self,
auth_response: &'a DeviceAuthorizationResponse<EF>,
) -> Result<DeviceAccessTokenRequest<'a, 'static, TR, EF>, ConfigurationError>
where
EF: ExtraDeviceAuthorizationFields,
{
Ok(self.exchange_device_access_token_impl(
self.token_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("token"))?,
auth_response,
))
}
pub fn exchange_password<'a>(
&'a self,
username: &'a ResourceOwnerUsername,
password: &'a ResourceOwnerPassword,
) -> Result<PasswordTokenRequest<'a, TE, TR>, ConfigurationError> {
Ok(self.exchange_password_impl(
self.token_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("token"))?,
username,
password,
))
}
pub fn exchange_refresh_token<'a>(
&'a self,
refresh_token: &'a RefreshToken,
) -> Result<RefreshTokenRequest<'a, TE, TR>, ConfigurationError> {
Ok(self.exchange_refresh_token_impl(
self.token_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("token"))?,
refresh_token,
))
}
pub fn token_uri(&self) -> Option<&TokenUrl> {
self.token_url.as_ref()
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasIntrospectionUrl, HasRevocationUrl, HasTokenUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
EndpointSet,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn exchange_device_code(&self) -> DeviceAuthorizationRequest<TE> {
self.exchange_device_code_impl(self.device_authorization_url())
}
pub fn device_authorization_url(&self) -> &DeviceAuthorizationUrl {
self.device_authorization_url
.as_ref()
.expect("should have device_authorization_url")
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasIntrospectionUrl, HasRevocationUrl, HasTokenUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
EndpointMaybeSet,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn exchange_device_code(
&self,
) -> Result<DeviceAuthorizationRequest<TE>, ConfigurationError> {
Ok(self.exchange_device_code_impl(
self.device_authorization_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("device authorization"))?,
))
}
pub fn device_authorization_url(&self) -> Option<&DeviceAuthorizationUrl> {
self.device_authorization_url.as_ref()
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasDeviceAuthUrl, HasRevocationUrl, HasTokenUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
EndpointSet,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn introspect<'a>(&'a self, token: &'a AccessToken) -> IntrospectionRequest<'a, TE, TIR> {
self.introspect_impl(self.introspection_url(), token)
}
pub fn introspection_url(&self) -> &IntrospectionUrl {
self.introspection_url
.as_ref()
.expect("should have introspection_url")
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasDeviceAuthUrl, HasRevocationUrl, HasTokenUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
EndpointMaybeSet,
HasRevocationUrl,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasRevocationUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn introspect<'a>(
&'a self,
token: &'a AccessToken,
) -> Result<IntrospectionRequest<'a, TE, TIR>, ConfigurationError> {
Ok(self.introspect_impl(
self.introspection_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("introspection"))?,
token,
))
}
pub fn introspection_url(&self) -> Option<&IntrospectionUrl> {
self.introspection_url.as_ref()
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasDeviceAuthUrl, HasIntrospectionUrl, HasTokenUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
EndpointSet,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn revoke_token(
&self,
token: RT,
) -> Result<RevocationRequest<RT, TRE>, ConfigurationError> {
self.revoke_token_impl(self.revocation_url(), token)
}
pub fn revocation_url(&self) -> &RevocationUrl {
self.revocation_url
.as_ref()
.expect("should have revocation_url")
}
}
impl<TE, TR, TIR, RT, TRE, HasAuthUrl, HasDeviceAuthUrl, HasIntrospectionUrl, HasTokenUrl>
Client<
TE,
TR,
TIR,
RT,
TRE,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
EndpointMaybeSet,
HasTokenUrl,
>
where
TE: ErrorResponse + 'static,
TR: TokenResponse,
TIR: TokenIntrospectionResponse,
RT: RevocableToken,
TRE: ErrorResponse + 'static,
HasAuthUrl: EndpointState,
HasDeviceAuthUrl: EndpointState,
HasIntrospectionUrl: EndpointState,
HasTokenUrl: EndpointState,
{
pub fn revoke_token(
&self,
token: RT,
) -> Result<RevocationRequest<RT, TRE>, ConfigurationError> {
self.revoke_token_impl(
self.revocation_url
.as_ref()
.ok_or(ConfigurationError::MissingUrl("revocation"))?,
token,
)
}
pub fn revocation_url(&self) -> Option<&RevocationUrl> {
self.revocation_url.as_ref()
}
}