this repo has no description
1use axum::{Json, extract::State}; 2use serde::{Deserialize, Serialize}; 3use crate::state::AppState; 4use crate::oauth::jwks::{JwkSet, create_jwk_set}; 5#[derive(Debug, Serialize, Deserialize)] 6pub struct ProtectedResourceMetadata { 7 pub resource: String, 8 pub authorization_servers: Vec<String>, 9 pub bearer_methods_supported: Vec<String>, 10 pub scopes_supported: Vec<String>, 11 #[serde(skip_serializing_if = "Option::is_none")] 12 pub resource_documentation: Option<String>, 13} 14#[derive(Debug, Serialize, Deserialize)] 15pub struct AuthorizationServerMetadata { 16 pub issuer: String, 17 pub authorization_endpoint: String, 18 pub token_endpoint: String, 19 pub jwks_uri: String, 20 #[serde(skip_serializing_if = "Option::is_none")] 21 pub registration_endpoint: Option<String>, 22 #[serde(skip_serializing_if = "Option::is_none")] 23 pub scopes_supported: Option<Vec<String>>, 24 pub response_types_supported: Vec<String>, 25 #[serde(skip_serializing_if = "Option::is_none")] 26 pub response_modes_supported: Option<Vec<String>>, 27 #[serde(skip_serializing_if = "Option::is_none")] 28 pub grant_types_supported: Option<Vec<String>>, 29 #[serde(skip_serializing_if = "Option::is_none")] 30 pub token_endpoint_auth_methods_supported: Option<Vec<String>>, 31 #[serde(skip_serializing_if = "Option::is_none")] 32 pub code_challenge_methods_supported: Option<Vec<String>>, 33 #[serde(skip_serializing_if = "Option::is_none")] 34 pub pushed_authorization_request_endpoint: Option<String>, 35 #[serde(skip_serializing_if = "Option::is_none")] 36 pub require_pushed_authorization_requests: Option<bool>, 37 #[serde(skip_serializing_if = "Option::is_none")] 38 pub dpop_signing_alg_values_supported: Option<Vec<String>>, 39 #[serde(skip_serializing_if = "Option::is_none")] 40 pub authorization_response_iss_parameter_supported: Option<bool>, 41 #[serde(skip_serializing_if = "Option::is_none")] 42 pub revocation_endpoint: Option<String>, 43 #[serde(skip_serializing_if = "Option::is_none")] 44 pub introspection_endpoint: Option<String>, 45} 46pub async fn oauth_protected_resource( 47 State(_state): State<AppState>, 48) -> Json<ProtectedResourceMetadata> { 49 let pds_hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string()); 50 let public_url = format!("https://{}", pds_hostname); 51 Json(ProtectedResourceMetadata { 52 resource: public_url.clone(), 53 authorization_servers: vec![public_url], 54 bearer_methods_supported: vec!["header".to_string()], 55 scopes_supported: vec![], 56 resource_documentation: Some("https://atproto.com".to_string()), 57 }) 58} 59pub async fn oauth_authorization_server( 60 State(_state): State<AppState>, 61) -> Json<AuthorizationServerMetadata> { 62 let pds_hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string()); 63 let issuer = format!("https://{}", pds_hostname); 64 Json(AuthorizationServerMetadata { 65 issuer: issuer.clone(), 66 authorization_endpoint: format!("{}/oauth/authorize", issuer), 67 token_endpoint: format!("{}/oauth/token", issuer), 68 jwks_uri: format!("{}/oauth/jwks", issuer), 69 registration_endpoint: None, 70 scopes_supported: Some(vec![ 71 "atproto".to_string(), 72 "transition:generic".to_string(), 73 "transition:chat.bsky".to_string(), 74 ]), 75 response_types_supported: vec!["code".to_string()], 76 response_modes_supported: Some(vec!["query".to_string(), "fragment".to_string()]), 77 grant_types_supported: Some(vec![ 78 "authorization_code".to_string(), 79 "refresh_token".to_string(), 80 ]), 81 token_endpoint_auth_methods_supported: Some(vec![ 82 "none".to_string(), 83 "private_key_jwt".to_string(), 84 ]), 85 code_challenge_methods_supported: Some(vec!["S256".to_string()]), 86 pushed_authorization_request_endpoint: Some(format!("{}/oauth/par", issuer)), 87 require_pushed_authorization_requests: Some(true), 88 dpop_signing_alg_values_supported: Some(vec![ 89 "ES256".to_string(), 90 "ES384".to_string(), 91 "ES512".to_string(), 92 "EdDSA".to_string(), 93 ]), 94 authorization_response_iss_parameter_supported: Some(true), 95 revocation_endpoint: Some(format!("{}/oauth/revoke", issuer)), 96 introspection_endpoint: Some(format!("{}/oauth/introspect", issuer)), 97 }) 98} 99pub async fn oauth_jwks(State(_state): State<AppState>) -> Json<JwkSet> { 100 use crate::config::AuthConfig; 101 use crate::oauth::jwks::Jwk; 102 let config = AuthConfig::get(); 103 let server_key = Jwk { 104 kty: "EC".to_string(), 105 key_use: Some("sig".to_string()), 106 kid: Some(config.signing_key_id.clone()), 107 alg: Some("ES256".to_string()), 108 crv: Some("P-256".to_string()), 109 x: Some(config.signing_key_x.clone()), 110 y: Some(config.signing_key_y.clone()), 111 }; 112 Json(create_jwk_set(vec![server_key])) 113}