Router, implement OAuth authorization server metadata endpoint
This commit is contained in:
parent
3ea0861d8f
commit
8a88bb3e3d
1 changed files with 101 additions and 0 deletions
|
|
@ -1,2 +1,103 @@
|
|||
use serde::de::{
|
||||
Error,
|
||||
Unexpected,
|
||||
};
|
||||
use serde_json::{
|
||||
json,
|
||||
Result,
|
||||
Value
|
||||
};
|
||||
use bon::Builder;
|
||||
|
||||
trait Metadata {
|
||||
fn format_metadata(self, required: RequiredMetadata) -> Result<Value>;
|
||||
}
|
||||
|
||||
pub struct RequiredMetadata {
|
||||
issuer: String,
|
||||
authorization_endpoint: String,
|
||||
token_endpoint: String,
|
||||
}
|
||||
|
||||
impl RequiredMetadata {
|
||||
fn new(
|
||||
issuer: String,
|
||||
authorization_endpoint: String,
|
||||
token_endpoint: String
|
||||
) -> Self {
|
||||
RequiredMetadata {
|
||||
issuer, authorization_endpoint, token_endpoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Builder)]
|
||||
struct AtprotoMetadata {
|
||||
additional_response_types_supported: Option<Vec<String>>,
|
||||
additional_grant_types_supported: Option<Vec<String>>,
|
||||
additional_code_challenge_methods_supported: Option<Vec<String>>,
|
||||
additional_token_endpoint_auth_methods_supported: Option<Vec<String>>,
|
||||
additional_token_endpoint_auth_signing_alg_values_supported: Option<Vec<String>>,
|
||||
additional_scopes_supported: Option<Vec<String>>,
|
||||
pushed_authorization_request_endpoint: String,
|
||||
additional_dpop_signing_alg_values_supported: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl AtprotoMetadata {
|
||||
fn check_fields(&self) -> Result<()> {
|
||||
// TODO: Issuer check (https scheme, no default port, no path segments
|
||||
|
||||
if self.additional_token_endpoint_auth_signing_alg_values_supported
|
||||
.as_ref()
|
||||
.is_none_or(|vec| vec.iter().any(|s| s == "none")) {
|
||||
return Err(Error::invalid_value(
|
||||
Unexpected::Other("\"none\" in token_endpoint_auth_signing_alg_values_supported"),
|
||||
&"\"none\" to be omitted from token_endpoint_auth_signing_alg_values_supported"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Metadata for AtprotoMetadata {
|
||||
fn format_metadata(self, required: RequiredMetadata) -> Result<Value> {
|
||||
self.check_fields()?;
|
||||
Ok(json!({
|
||||
"issuer": required.issuer,
|
||||
"authorization_endpoint": required.authorization_endpoint,
|
||||
"token_endpoint": required.token_endpoint,
|
||||
"response_types_supported":
|
||||
self.additional_response_types_supported.unwrap_or_default()
|
||||
.extend(["code".to_string()]),
|
||||
"grant_types_supported":
|
||||
self.additional_grant_types_supported.unwrap_or_default()
|
||||
.extend([
|
||||
"authorization_code".to_string(),
|
||||
"refresh_token".to_string()
|
||||
]),
|
||||
"code_challenge_methods_supported":
|
||||
self.additional_code_challenge_methods_supported.unwrap_or_default()
|
||||
.extend(["S256".to_string()]),
|
||||
"token_endpoint_auth_methods_supported":
|
||||
self.additional_token_endpoint_auth_methods_supported.unwrap_or_default()
|
||||
.extend([
|
||||
"none".to_string(),
|
||||
"private_key_jwt".to_string()
|
||||
]),
|
||||
"token_endpoint_auth_signing_alg_values_supported":
|
||||
self.additional_token_endpoint_auth_signing_alg_values_supported.unwrap_or_default()
|
||||
.extend(["ES256".to_string()]),
|
||||
"scopes_supported":
|
||||
self.additional_scopes_supported.unwrap_or_default()
|
||||
.extend(["atproto".to_string()]),
|
||||
"authorization_response_iss_parameter_supported": true,
|
||||
"require_pushed_authorization_requests": true,
|
||||
"pushed_authorization_request_endpoint": self.pushed_authorization_request_endpoint,
|
||||
"dpop_signing_alg_values_supported":
|
||||
self.additional_dpop_signing_alg_values_supported.unwrap_or_default()
|
||||
.extend(["ES256".to_string()]),
|
||||
"client_id_metadata_document_supported": true,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue