+8
-12
pocket/src/server.rs
+8
-12
pocket/src/server.rs
···
4
endpoint::{StaticFileEndpoint, make_sync},
5
http::Method,
6
listener::TcpListener,
7
-
middleware::{CatchPanic, Cors, Tracing},
8
};
9
use poem_openapi::{
10
ApiResponse, ContactObject, ExternalDocumentObject, Object, OpenApi, OpenApiService,
···
94
verifier: TokenVerifier,
95
}
96
97
-
// app.bsky.actor.getPreferences
98
-
// com.bad-example.pocket.getPreferences
99
-
100
#[OpenApi]
101
impl Xrpc {
102
/// com.bad-example.pocket.getPreferences
103
///
104
-
/// get stored bluesky prefs
105
#[oai(
106
-
path = "/app.bsky.actor.getPreferences",
107
method = "get",
108
tag = "ApiTags::Pocket"
109
)]
110
-
async fn app_bsky_get_prefs(&self, XrpcAuth(auth): XrpcAuth) -> GetBskyPrefsResponse {
111
let (did, aud) = match self
112
.verifier
113
-
.verify("app.bsky.actor.getPreferences", &auth.token)
114
.await
115
{
116
Ok(d) => d,
···
129
method = "post",
130
tag = "ApiTags::Pocket"
131
)]
132
-
async fn app_bsky_put_prefs(
133
&self,
134
XrpcAuth(auth): XrpcAuth,
135
Json(prefs): Json<Value>,
136
) -> PutBskyPrefsResponse {
137
let (did, aud) = match self
138
.verifier
139
-
.verify("app.bsky.actor.getPreferences", &auth.token)
140
.await
141
{
142
Ok(d) => d,
···
168
service: [
169
AppViewService {
170
id: "#pocket_prefs".to_string(),
171
-
// id: "#bsky_appview".to_string(),
172
r#type: "PocketPreferences".to_string(),
173
service_endpoint: format!("https://{domain}"),
174
},
175
AppViewService {
176
id: "#bsky_appview".to_string(),
177
-
// id: "#bsky_appview".to_string(),
178
r#type: "BlueskyAppview".to_string(),
179
service_endpoint: format!("https://{domain}"),
180
},
···
201
.nest("/xrpc/", api_service)
202
.at("/.well-known/did.json", get_did_doc(domain))
203
.at("/", StaticFileEndpoint::new("./static/index.html"))
204
.with(
205
Cors::new()
206
.allow_method(Method::GET)
···
4
endpoint::{StaticFileEndpoint, make_sync},
5
http::Method,
6
listener::TcpListener,
7
+
middleware::{CatchPanic, Cors, SizeLimit, Tracing},
8
};
9
use poem_openapi::{
10
ApiResponse, ContactObject, ExternalDocumentObject, Object, OpenApi, OpenApiService,
···
94
verifier: TokenVerifier,
95
}
96
97
#[OpenApi]
98
impl Xrpc {
99
/// com.bad-example.pocket.getPreferences
100
///
101
+
/// get stored preferencess
102
#[oai(
103
+
path = "/com.bad-example.pocket.getPreferences",
104
method = "get",
105
tag = "ApiTags::Pocket"
106
)]
107
+
async fn pocket_get_prefs(&self, XrpcAuth(auth): XrpcAuth) -> GetBskyPrefsResponse {
108
let (did, aud) = match self
109
.verifier
110
+
.verify("com.bad-example.pocket.getPreferences", &auth.token)
111
.await
112
{
113
Ok(d) => d,
···
126
method = "post",
127
tag = "ApiTags::Pocket"
128
)]
129
+
async fn pocket_put_prefs(
130
&self,
131
XrpcAuth(auth): XrpcAuth,
132
Json(prefs): Json<Value>,
133
) -> PutBskyPrefsResponse {
134
let (did, aud) = match self
135
.verifier
136
+
.verify("com.bad-example.pocket.putPreferences", &auth.token)
137
.await
138
{
139
Ok(d) => d,
···
165
service: [
166
AppViewService {
167
id: "#pocket_prefs".to_string(),
168
r#type: "PocketPreferences".to_string(),
169
service_endpoint: format!("https://{domain}"),
170
},
171
AppViewService {
172
id: "#bsky_appview".to_string(),
173
r#type: "BlueskyAppview".to_string(),
174
service_endpoint: format!("https://{domain}"),
175
},
···
196
.nest("/xrpc/", api_service)
197
.at("/.well-known/did.json", get_did_doc(domain))
198
.at("/", StaticFileEndpoint::new("./static/index.html"))
199
+
.with(SizeLimit::new(100 * 2_usize.pow(10)))
200
.with(
201
Cors::new()
202
.allow_method(Method::GET)
+5
-4
pocket/src/token.rs
+5
-4
pocket/src/token.rs
···
118
let Some(aud) = claims.custom.get("aud") else {
119
return Err(VerifyError::VerificationFailed("missing aud"));
120
};
121
-
let Some(aud) = aud.strip_prefix("did:web:") else {
122
return Err(VerifyError::VerificationFailed("expected a did:web aud"));
123
};
124
-
let Some((aud, _)) = aud.split_once("#") else {
125
-
return Err(VerifyError::VerificationFailed("aud missing #fragment"));
126
-
};
127
let Some(lxm) = claims.custom.get("lxm") else {
128
return Err(VerifyError::VerificationFailed("missing lxm"));
129
};
···
118
let Some(aud) = claims.custom.get("aud") else {
119
return Err(VerifyError::VerificationFailed("missing aud"));
120
};
121
+
let Some(mut aud) = aud.strip_prefix("did:web:") else {
122
return Err(VerifyError::VerificationFailed("expected a did:web aud"));
123
};
124
+
if let Some((aud_without_hash, _)) = aud.split_once("#") {
125
+
log::warn!("aud claim is missing service id fragment: {aud:?}");
126
+
aud = aud_without_hash;
127
+
}
128
let Some(lxm) = claims.custom.get("lxm") else {
129
return Err(VerifyError::VerificationFailed("missing lxm"));
130
};