+12
-6
server/services/auth.ts
+12
-6
server/services/auth.ts
···
136
136
) {
137
137
userDid = payload.sub;
138
138
139
-
// App password tokens from PDS: sub=userDID, aud=pdsDID, scope=com.atproto.appPassPrivileged
139
+
// PDS-issued tokens: sub=userDID, aud=pdsDID, scope=com.atproto.access or com.atproto.appPassPrivileged
140
140
// SECURITY: All JWTs MUST have their cryptographic signatures verified
141
-
// Even app password tokens need signature verification to prevent forgery
142
141
const pdsDid = payload.aud;
143
142
if (
144
-
payload.scope === 'com.atproto.appPassPrivileged' &&
143
+
(payload.scope === 'com.atproto.appPassPrivileged' || payload.scope === 'com.atproto.access') &&
145
144
pdsDid &&
146
145
typeof pdsDid === 'string' &&
147
146
pdsDid.startsWith('did:')
148
147
) {
149
-
// For app password tokens, the PDS is the issuer
148
+
// For PDS-issued tokens, the PDS is the signer
150
149
signingDid = pdsDid;
151
150
console.log(
152
-
`[AUTH] PDS app password token detected for DID: ${payload.sub} (from PDS: ${pdsDid}) - verifying signature`
151
+
`[AUTH] PDS token detected (scope: ${payload.scope}) for DID: ${payload.sub} (from PDS: ${pdsDid}) - verifying signature`
153
152
);
154
153
}
155
154
// OAuth tokens with iss field need signature verification
156
155
else if (payload.iss && typeof payload.iss === 'string') {
157
156
signingDid = payload.iss;
157
+
}
158
+
// Fallback: use aud as signing DID if present
159
+
else if (pdsDid && typeof pdsDid === 'string' && pdsDid.startsWith('did:')) {
160
+
signingDid = pdsDid;
161
+
console.log(
162
+
`[AUTH] Using aud field as signing DID for token from: ${pdsDid}`
163
+
);
158
164
} else {
159
-
console.log(`[AUTH] OAuth token missing iss field`);
165
+
console.log(`[AUTH] OAuth token missing iss/aud field`);
160
166
return null;
161
167
}
162
168
}