Auto-indexing service and GraphQL API for AT Protocol Records quickslice.slices.network/
atproto gleam graphql
at main 92 lines 3.1 kB view raw
1/// OAuth server metadata endpoint handler 2/// GET /.well-known/oauth-authorization-server 3import gleam/json 4import wisp 5 6pub type ServerMetadata { 7 ServerMetadata( 8 issuer: String, 9 authorization_endpoint: String, 10 token_endpoint: String, 11 jwks_uri: String, 12 registration_endpoint: String, 13 scopes_supported: List(String), 14 response_types_supported: List(String), 15 grant_types_supported: List(String), 16 token_endpoint_auth_methods_supported: List(String), 17 code_challenge_methods_supported: List(String), 18 pushed_authorization_request_endpoint: String, 19 dpop_signing_alg_values_supported: List(String), 20 ) 21} 22 23/// Generate server metadata for the given base URL 24pub fn generate_metadata( 25 base_url: String, 26 scopes_supported: List(String), 27) -> ServerMetadata { 28 ServerMetadata( 29 issuer: base_url, 30 authorization_endpoint: base_url <> "/oauth/authorize", 31 token_endpoint: base_url <> "/oauth/token", 32 jwks_uri: base_url <> "/.well-known/jwks.json", 33 registration_endpoint: base_url <> "/oauth/register", 34 scopes_supported: scopes_supported, 35 response_types_supported: ["code"], 36 grant_types_supported: ["authorization_code", "refresh_token"], 37 token_endpoint_auth_methods_supported: [ 38 "client_secret_basic", 39 "client_secret_post", 40 "none", 41 ], 42 code_challenge_methods_supported: ["S256"], 43 pushed_authorization_request_endpoint: base_url <> "/oauth/par", 44 dpop_signing_alg_values_supported: ["ES256"], 45 ) 46} 47 48/// Encode metadata as JSON 49pub fn encode_metadata(meta: ServerMetadata) -> json.Json { 50 json.object([ 51 #("issuer", json.string(meta.issuer)), 52 #("authorization_endpoint", json.string(meta.authorization_endpoint)), 53 #("token_endpoint", json.string(meta.token_endpoint)), 54 #("jwks_uri", json.string(meta.jwks_uri)), 55 #("registration_endpoint", json.string(meta.registration_endpoint)), 56 #("scopes_supported", json.array(meta.scopes_supported, json.string)), 57 #( 58 "response_types_supported", 59 json.array(meta.response_types_supported, json.string), 60 ), 61 #( 62 "grant_types_supported", 63 json.array(meta.grant_types_supported, json.string), 64 ), 65 #( 66 "token_endpoint_auth_methods_supported", 67 json.array(meta.token_endpoint_auth_methods_supported, json.string), 68 ), 69 #( 70 "code_challenge_methods_supported", 71 json.array(meta.code_challenge_methods_supported, json.string), 72 ), 73 #( 74 "pushed_authorization_request_endpoint", 75 json.string(meta.pushed_authorization_request_endpoint), 76 ), 77 #( 78 "dpop_signing_alg_values_supported", 79 json.array(meta.dpop_signing_alg_values_supported, json.string), 80 ), 81 ]) 82} 83 84/// Handle GET /.well-known/oauth-authorization-server 85pub fn handle(base_url: String, scopes_supported: List(String)) -> wisp.Response { 86 let meta = generate_metadata(base_url, scopes_supported) 87 let json_response = encode_metadata(meta) 88 89 wisp.response(200) 90 |> wisp.set_header("content-type", "application/json") 91 |> wisp.set_body(wisp.Text(json.to_string(json_response))) 92}