Auto-indexing service and GraphQL API for AT Protocol Records
at main 84 lines 2.6 kB view raw
1/// Secure token generation utilities 2import gleam/bit_array 3import gleam/crypto 4 5/// Generate a secure random authorization code 6pub fn generate_authorization_code() -> String { 7 let random_bytes = crypto.strong_random_bytes(32) 8 bit_array.base64_url_encode(random_bytes, False) 9} 10 11/// Generate a secure random access token 12pub fn generate_access_token() -> String { 13 let random_bytes = crypto.strong_random_bytes(32) 14 bit_array.base64_url_encode(random_bytes, False) 15} 16 17/// Generate a secure random refresh token 18pub fn generate_refresh_token() -> String { 19 let random_bytes = crypto.strong_random_bytes(32) 20 bit_array.base64_url_encode(random_bytes, False) 21} 22 23/// Generate a secure random client ID 24pub fn generate_client_id() -> String { 25 let random_bytes = crypto.strong_random_bytes(16) 26 let encoded = bit_array.base64_url_encode(random_bytes, False) 27 "client_" <> encoded 28} 29 30/// Generate a secure random client secret 31pub fn generate_client_secret() -> String { 32 let random_bytes = crypto.strong_random_bytes(32) 33 bit_array.base64_url_encode(random_bytes, False) 34} 35 36/// Generate a PAR request URI 37pub fn generate_par_request_uri() -> String { 38 let random_bytes = crypto.strong_random_bytes(16) 39 let encoded = bit_array.base64_url_encode(random_bytes, False) 40 "urn:ietf:params:oauth:request_uri:" <> encoded 41} 42 43/// Generate a DPoP nonce 44pub fn generate_dpop_nonce() -> String { 45 let random_bytes = crypto.strong_random_bytes(16) 46 bit_array.base64_url_encode(random_bytes, False) 47} 48 49/// Generate a session ID 50pub fn generate_session_id() -> String { 51 let random_bytes = crypto.strong_random_bytes(16) 52 bit_array.base64_url_encode(random_bytes, False) 53} 54 55/// Generate an OAuth state parameter 56pub fn generate_state() -> String { 57 let random_bytes = crypto.strong_random_bytes(16) 58 bit_array.base64_url_encode(random_bytes, False) 59} 60 61/// Compute JWK thumbprint (JKT) from a signing key 62pub fn compute_jkt(key: String) -> String { 63 let key_bytes = bit_array.from_string(key) 64 let hash = crypto.hash(crypto.Sha256, key_bytes) 65 bit_array.base64_url_encode(hash, False) 66} 67 68/// Get current timestamp (seconds since epoch) 69pub fn current_timestamp() -> Int { 70 get_system_time_native() / 1_000_000_000 71} 72 73/// Calculate expiration timestamp 74pub fn expiration_timestamp(lifetime_seconds: Int) -> Int { 75 current_timestamp() + lifetime_seconds 76} 77 78/// Check if a timestamp is expired 79pub fn is_expired(expires_at: Int) -> Bool { 80 current_timestamp() >= expires_at 81} 82 83@external(erlang, "os", "system_time") 84fn get_system_time_native() -> Int