A library for ATProtocol identities.

hack: bluesky-social/pds handles rpc scopes a very specific way

Changed files
+25 -4
crates
atproto-oauth
src
+25 -4
crates/atproto-oauth/src/scopes.rs
··· 682 682 } else { 683 683 "rpc:*".to_string() 684 684 } 685 + } else if scope.lxm.len() == 1 && scope.aud.len() == 1 { 686 + // Single lxm and single aud (aud is not All, handled above) 687 + if let (Some(lxm), Some(aud)) = 688 + (scope.lxm.iter().next(), scope.aud.iter().next()) 689 + { 690 + match (lxm, aud) { 691 + (RpcLexicon::Nsid(nsid), RpcAudience::Did(did)) => { 692 + format!("rpc:{}?aud={}", nsid, did) 693 + } 694 + (RpcLexicon::All, RpcAudience::Did(did)) => { 695 + format!("rpc:*?aud={}", did) 696 + } 697 + _ => "rpc:*".to_string(), 698 + } 699 + } else { 700 + "rpc:*".to_string() 701 + } 685 702 } else { 686 703 let mut params = Vec::new(); 687 704 ··· 1056 1073 ("repo:foo.bar", "repo:foo.bar"), 1057 1074 ("repo:foo.bar?action=create", "repo:foo.bar?action=create"), 1058 1075 ("rpc:*", "rpc:*"), 1076 + ("rpc:com.example.service", "rpc:com.example.service"), 1077 + ( 1078 + "rpc:com.example.service?aud=did:example:123", 1079 + "rpc:com.example.service?aud=did:example:123", 1080 + ), 1059 1081 ]; 1060 1082 1061 1083 for (input, expected) in tests { ··· 1677 1699 1678 1700 // Test with complex scopes including query parameters 1679 1701 let scopes = vec![ 1680 - Scope::parse("rpc:com.example.service?aud=did:example:123&lxm=com.example.method") 1681 - .unwrap(), 1702 + Scope::parse("rpc:com.example.service?aud=did:example:123").unwrap(), 1682 1703 Scope::parse("repo:foo.bar?action=create&action=update").unwrap(), 1683 1704 Scope::parse("blob:image/*?accept=image/png&accept=image/jpeg").unwrap(), 1684 1705 ]; 1685 1706 let result = Scope::serialize_multiple(&scopes); 1686 1707 // The result should be sorted alphabetically 1687 - // Note: RPC scope with query params is serialized as "rpc?aud=...&lxm=..." 1708 + // Single lxm + single aud is serialized as "rpc:[lxm]?aud=[aud]" 1688 1709 assert!(result.starts_with("blob:")); 1689 1710 assert!(result.contains(" repo:")); 1690 - assert!(result.contains("rpc?aud=did:example:123&lxm=com.example.service")); 1711 + assert!(result.contains("rpc:com.example.service?aud=did:example:123")); 1691 1712 1692 1713 // Test with transition scopes 1693 1714 let scopes = vec![