Skip to content

Commit

Permalink
Merge pull request #97 from bluesky-social/bound-service-auth
Browse files Browse the repository at this point in the history
Update usage of xrpc-server to check bound service auth
  • Loading branch information
devinivy authored Aug 13, 2024
2 parents a3dd8d2 + c18bee7 commit fadd462
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 11 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@atproto/lexicon": "^0.2.2",
"@atproto/repo": "^0.3.2",
"@atproto/syntax": "^0.1.2",
"@atproto/xrpc-server": "^0.3.2",
"@atproto/xrpc-server": "^0.6.0",
"better-sqlite3": "^8.3.0",
"dotenv": "^16.0.3",
"express": "^4.18.2",
Expand Down
81 changes: 81 additions & 0 deletions scripts/publishFeedGen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import dotenv from 'dotenv'
import { AtpAgent, BlobRef } from '@atproto/api'
import fs from 'fs/promises'
import { ids } from '../src/lexicon/lexicons'

const run = async () => {
dotenv.config()

// YOUR bluesky handle
// Ex: user.bsky.social
const handle = ''

// YOUR bluesky password, or preferably an App Password (found in your client settings)
// Ex: abcd-1234-efgh-5678
const password = ''

// A short name for the record that will show in urls
// Lowercase with no spaces.
// Ex: whats-hot
const recordName = ''

// A display name for your feed
// Ex: What's Hot
const displayName = ''

// (Optional) A description of your feed
// Ex: Top trending content from the whole network
const description = ''

// (Optional) The path to an image to be used as your feed's avatar
// Ex: ~/path/to/avatar.jpeg
const avatar: string = ''

// -------------------------------------
// NO NEED TO TOUCH ANYTHING BELOW HERE
// -------------------------------------

if (!process.env.FEEDGEN_SERVICE_DID && !process.env.FEEDGEN_HOSTNAME) {
throw new Error('Please provide a hostname in the .env file')
}
const feedGenDid =
process.env.FEEDGEN_SERVICE_DID ?? `did:web:${process.env.FEEDGEN_HOSTNAME}`

// only update this if in a test environment
const agent = new AtpAgent({ service: 'https://bsky.social' })
await agent.login({ identifier: handle, password })

let avatarRef: BlobRef | undefined
if (avatar) {
let encoding: string
if (avatar.endsWith('png')) {
encoding = 'image/png'
} else if (avatar.endsWith('jpg') || avatar.endsWith('jpeg')) {
encoding = 'image/jpeg'
} else {
throw new Error('expected png or jpeg')
}
const img = await fs.readFile(avatar)
const blobRes = await agent.api.com.atproto.repo.uploadBlob(img, {
encoding,
})
avatarRef = blobRes.data.blob
}

await agent.api.com.atproto.repo.putRecord({
repo: agent.session?.did ?? '',
collection: ids.AppBskyFeedGenerator,
rkey: recordName,
record: {
did: feedGenDid,
displayName: displayName,
description: description,
avatar: avatarRef,
createdAt: new Date().toISOString(),
},
})

console.log('All done 🎉')
}

run()
6 changes: 4 additions & 2 deletions src/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express'
import { verifyJwt, AuthRequiredError } from '@atproto/xrpc-server'
import { verifyJwt, AuthRequiredError, parseReqNsid } from '@atproto/xrpc-server'
import { DidResolver } from '@atproto/identity'

export const validateAuth = async (
Expand All @@ -12,7 +12,9 @@ export const validateAuth = async (
throw new AuthRequiredError()
}
const jwt = authorization.replace('Bearer ', '').trim()
return verifyJwt(jwt, serviceDid, async (did: string) => {
const nsid = parseReqNsid(req)
const parsed = await verifyJwt(jwt, serviceDid, nsid, async (did: string) => {
return didResolver.resolveAtprotoKey(did)
})
return parsed.iss
}
121 changes: 113 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@
uint8arrays "3.0.0"
zod "^3.21.4"

"@atproto/common-web@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.3.0.tgz#36da8c2c31d8cf8a140c3c8f03223319bf4430bb"
integrity sha512-67VnV6JJyX+ZWyjV7xFQMypAgDmjVaR9ZCuU/QW+mqlqI7fex2uL4Fv+7/jHadgzhuJHVd6OHOvNn0wR5WZYtA==
dependencies:
graphemer "^1.4.0"
multiformats "^9.9.0"
uint8arrays "3.0.0"
zod "^3.21.4"

"@atproto/common@^0.3.1":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.3.1.tgz#ee131c170bdb564ed4f9692db0a80ada825220c7"
Expand All @@ -38,6 +48,18 @@
pino "^8.15.0"
zod "3.21.4"

"@atproto/common@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.1.tgz#ca6fce47001ce8d031acd3fb4942fbfd81f72c43"
integrity sha512-uL7kQIcBTbvkBDNfxMXL6lBH4fO2DQpHd2BryJxMtbw/4iEPKe9xBYApwECHhEIk9+zhhpTRZ15FJ3gxTXN82Q==
dependencies:
"@atproto/common-web" "^0.3.0"
"@ipld/dag-cbor" "^7.0.3"
cbor-x "^1.5.1"
iso-datestring-validator "^2.2.2"
multiformats "^9.9.0"
pino "^8.21.0"

"@atproto/crypto@^0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@atproto/crypto/-/crypto-0.2.2.tgz#9832dda885512a36401d24f95990489f521593ef"
Expand All @@ -47,6 +69,15 @@
"@noble/hashes" "^1.3.1"
uint8arrays "3.0.0"

"@atproto/crypto@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/crypto/-/crypto-0.4.0.tgz#dcdd6bf5ba98261ae0ff3b96d7b8695c1ef788e6"
integrity sha512-Kj/4VgJ7hzzXvE42L0rjzP6lM0tai+OfPnP1rxJ+UZg/YUDtuewL4uapnVoWXvlNceKgaLZH98g5n9gXBVTe5Q==
dependencies:
"@noble/curves" "^1.1.0"
"@noble/hashes" "^1.3.1"
uint8arrays "3.0.0"

"@atproto/identity@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@atproto/identity/-/identity-0.2.1.tgz#8203ba53a25c3300d1aec0c28eb10a106919b410"
Expand All @@ -68,6 +99,17 @@
multiformats "^9.9.0"
zod "^3.21.4"

"@atproto/lexicon@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.0.tgz#63e8829945d80c25524882caa8ed27b1151cc576"
integrity sha512-RvCBKdSI4M8qWm5uTNz1z3R2yIvIhmOsMuleOj8YR6BwRD+QbtUBy3l+xQ7iXf4M5fdfJFxaUNa6Ty0iRwdKqQ==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/syntax" "^0.3.0"
iso-datestring-validator "^2.2.2"
multiformats "^9.9.0"
zod "^3.21.4"

"@atproto/repo@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.3.2.tgz#46cd9f8a16b82de7fda6760e611999a9d42f5545"
Expand All @@ -92,22 +134,28 @@
dependencies:
"@atproto/common-web" "^0.2.1"

"@atproto/xrpc-server@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.3.2.tgz#85bc901991c3de896d463c0cd1d396ab1c772387"
integrity sha512-aracV1+1t88AU+zN/RTmZGvvjlMiNIooLotz23FvD4qoiUSx6KxrTwttHZdw5ZJE14XTDR1D9brpyvdCJHsKNA==
"@atproto/syntax@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3"
integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA==

"@atproto/xrpc-server@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.6.0.tgz#00ce91af703287d8a93ea46b20aa18debee0aa24"
integrity sha512-c0UhLQIjkVGxcRIbWLEjJsW0NzKs9uIIUYQWJ27zUUAet5tzgYOyTDuZ5v8FvAJ4wkfJUIZH2GazqxrQDW4G3g==
dependencies:
"@atproto/common" "^0.3.1"
"@atproto/crypto" "^0.2.2"
"@atproto/lexicon" "^0.2.2"
"@atproto/common" "^0.4.1"
"@atproto/crypto" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/xrpc" "^0.5.0"
cbor-x "^1.5.1"
express "^4.17.2"
http-errors "^2.0.0"
mime-types "^2.1.35"
rate-limiter-flexible "^2.4.1"
uint8arrays "3.0.0"
ws "^8.12.0"
zod "^3.21.4"
zod "^3.23.8"

"@atproto/xrpc@^0.3.2":
version "0.3.2"
Expand All @@ -117,6 +165,14 @@
"@atproto/lexicon" "^0.2.2"
zod "^3.21.4"

"@atproto/xrpc@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.5.0.tgz#dacbfd8f7b13f0ab5bd56f8fdd4b460e132a6032"
integrity sha512-swu+wyOLvYW4l3n+VAuJbHcPcES+tin2Lsrp8Bw5aIXIICiuFn1YMFlwK9JwVUzTH21Py1s1nHEjr4CJeElJog==
dependencies:
"@atproto/lexicon" "^0.4.0"
zod "^3.21.4"

"@cbor-extract/[email protected]":
version "2.1.1"
resolved "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.1.1.tgz"
Expand Down Expand Up @@ -887,6 +943,14 @@ [email protected]:
resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz"
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==

pino-abstract-transport@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz#97f9f2631931e242da531b5c66d3079c12c9d1b5"
integrity sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==
dependencies:
readable-stream "^4.0.0"
split2 "^4.0.0"

[email protected]:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8"
Expand Down Expand Up @@ -917,6 +981,23 @@ pino@^8.15.0:
sonic-boom "^3.1.0"
thread-stream "^2.0.0"

pino@^8.21.0:
version "8.21.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-8.21.0.tgz#e1207f3675a2722940d62da79a7a55a98409f00d"
integrity sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.1.1"
on-exit-leak-free "^2.1.0"
pino-abstract-transport "^1.2.0"
pino-std-serializers "^6.0.0"
process-warning "^3.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.2.0"
safe-stable-stringify "^2.3.1"
sonic-boom "^3.7.0"
thread-stream "^2.6.0"

prebuild-install@^7.1.0:
version "7.1.1"
resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz"
Expand All @@ -940,6 +1021,11 @@ process-warning@^2.0.0:
resolved "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz"
integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==

process-warning@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b"
integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==

process@^0.11.10:
version "0.11.10"
resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz"
Expand Down Expand Up @@ -1120,6 +1206,13 @@ sonic-boom@^3.1.0:
dependencies:
atomic-sleep "^1.0.0"

sonic-boom@^3.7.0:
version "3.8.1"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.1.tgz#d5ba8c4e26d6176c9a1d14d549d9ff579a163422"
integrity sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==
dependencies:
atomic-sleep "^1.0.0"

split2@^4.0.0:
version "4.2.0"
resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz"
Expand Down Expand Up @@ -1170,6 +1263,13 @@ thread-stream@^2.0.0:
dependencies:
real-require "^0.2.0"

thread-stream@^2.6.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.7.0.tgz#d8a8e1b3fd538a6cca8ce69dbe5d3d097b601e11"
integrity sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==
dependencies:
real-require "^0.2.0"

tlds@^1.234.0:
version "1.238.0"
resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.238.0.tgz#ffe7c19c8940c35b497cda187a6927f9450325a4"
Expand Down Expand Up @@ -1297,3 +1397,8 @@ zod@^3.21.4:
version "3.22.2"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.2.tgz#3add8c682b7077c05ac6f979fea6998b573e157b"
integrity sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==

zod@^3.23.8:
version "3.23.8"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==

0 comments on commit fadd462

Please sign in to comment.