An easy-to-host PDS on the ATProtocol, iPhone and MacOS. Maintain control of your keys and data, always.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(relay): register identity-wallet as OAuth client (MM-149 phase 1)

Add V013 migration that seeds the identity-wallet as a known OAuth client
in the relay database. The PAR handler already performs client lookup by
client_id; this row makes the relay accept identity-wallet PAR requests.

authored by

Malpercio and committed by
Tangled
9ab2dfc0 c6c15f28

+56
+20
crates/relay/src/db/migrations/V013__identity_wallet_oauth_client.sql
··· 1 + -- Seed the identity-wallet as a registered OAuth client. 2 + -- 3 + -- client_metadata is a RFC 7591 JSON object. The PAR handler parses 4 + -- metadata["redirect_uris"] to validate the redirect_uri parameter. 5 + -- INSERT OR IGNORE makes this migration idempotent on re-run. 6 + INSERT OR IGNORE INTO oauth_clients (client_id, client_metadata, created_at) 7 + VALUES ( 8 + 'dev.malpercio.identitywallet', 9 + json('{ 10 + "client_id": "dev.malpercio.identitywallet", 11 + "application_type": "native", 12 + "token_endpoint_auth_method": "none", 13 + "dpop_bound_access_tokens": true, 14 + "redirect_uris": ["dev.malpercio.identitywallet:/oauth/callback"], 15 + "grant_types": ["authorization_code", "refresh_token"], 16 + "scope": "atproto", 17 + "client_name": "Malpercio Identity Wallet" 18 + }'), 19 + datetime('now') 20 + );
+36
crates/relay/src/db/mod.rs
··· 79 79 version: 12, 80 80 sql: include_str!("migrations/V012__oauth_token_endpoint.sql"), 81 81 }, 82 + Migration { 83 + version: 13, 84 + sql: include_str!("migrations/V013__identity_wallet_oauth_client.sql"), 85 + }, 82 86 ]; 83 87 84 88 /// Open a WAL-mode SQLite connection pool with a maximum of 1 connection. ··· 1052 1056 updated_pending_did, 1053 1057 Some("did:plc:test123".to_string()), 1054 1058 "pending_did should be updated" 1059 + ); 1060 + } 1061 + 1062 + #[tokio::test] 1063 + async fn v013_seeds_identity_wallet_oauth_client() { 1064 + let pool = in_memory_pool().await; 1065 + run_migrations(&pool) 1066 + .await 1067 + .expect("migrations must apply cleanly"); 1068 + 1069 + let row = oauth::get_oauth_client(&pool, "dev.malpercio.identitywallet") 1070 + .await 1071 + .expect("db query must not fail"); 1072 + 1073 + assert!( 1074 + row.is_some(), 1075 + "V013 migration must insert the identity-wallet client row" 1076 + ); 1077 + 1078 + let row = row.unwrap(); 1079 + let metadata: serde_json::Value = 1080 + serde_json::from_str(&row.client_metadata).expect("client_metadata must be valid JSON"); 1081 + 1082 + assert_eq!( 1083 + metadata["redirect_uris"][0].as_str(), 1084 + Some("dev.malpercio.identitywallet:/oauth/callback"), 1085 + "redirect_uri must match the custom URL scheme" 1086 + ); 1087 + assert_eq!( 1088 + metadata["dpop_bound_access_tokens"].as_bool(), 1089 + Some(true), 1090 + "DPoP must be required for this client" 1055 1091 ); 1056 1092 } 1057 1093 }