1982693e3e
* Extract verifySignatureWithKey out of verifyJwt * Accept optional verifySignatureWithKey as param * Impl. verifySignatureWithKey with native crypto * Test key validation * changesets * build * build (fix) * Move verifySig out * Trigger Build * Move test * Remove redundant check --------- Co-authored-by: Devin Ivy <devinivy@gmail.com>
93 lines
2.9 KiB
TypeScript
93 lines
2.9 KiB
TypeScript
import { AtpAgent } from '@atproto/api'
|
|
import { SeedClient, TestNetwork, usersSeed } from '@atproto/dev-env'
|
|
import { createServiceJwt } from '@atproto/xrpc-server'
|
|
import { Keypair, Secp256k1Keypair } from '@atproto/crypto'
|
|
import { ids } from '../src/lexicon/lexicons'
|
|
|
|
describe('auth', () => {
|
|
let network: TestNetwork
|
|
let agent: AtpAgent
|
|
let sc: SeedClient
|
|
|
|
// account dids, for convenience
|
|
let alice: string
|
|
let bob: string
|
|
|
|
beforeAll(async () => {
|
|
network = await TestNetwork.create({
|
|
dbPostgresSchema: 'bsky_auth',
|
|
})
|
|
agent = network.bsky.getClient()
|
|
sc = network.getSeedClient()
|
|
await usersSeed(sc)
|
|
await network.processAll()
|
|
alice = sc.dids.alice
|
|
bob = sc.dids.bob
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await network.close()
|
|
})
|
|
|
|
// @TODO invalidations do not originate from appview frontends: requires identity event on the repo stream.
|
|
it.skip('handles signing key change for service auth.', async () => {
|
|
const issuer = sc.dids.alice
|
|
const attemptWithKey = async (keypair: Keypair) => {
|
|
const jwt = await createServiceJwt({
|
|
iss: issuer,
|
|
aud: network.bsky.ctx.cfg.serverDid,
|
|
lxm: ids.AppBskyActorGetProfile,
|
|
keypair,
|
|
})
|
|
return agent.api.app.bsky.actor.getProfile(
|
|
{ actor: sc.dids.carol },
|
|
{ headers: { authorization: `Bearer ${jwt}` } },
|
|
)
|
|
}
|
|
const origSigningKey = await network.pds.ctx.actorStore.keypair(issuer)
|
|
const newSigningKey = await Secp256k1Keypair.create({ exportable: true })
|
|
// confirm original signing key works
|
|
await expect(attemptWithKey(origSigningKey)).resolves.toBeDefined()
|
|
// confirm next signing key doesn't work yet
|
|
await expect(attemptWithKey(newSigningKey)).rejects.toThrow(
|
|
'jwt signature does not match jwt issuer',
|
|
)
|
|
// update to new signing key
|
|
await network.plc
|
|
.getClient()
|
|
.updateAtprotoKey(
|
|
issuer,
|
|
network.pds.ctx.plcRotationKey,
|
|
newSigningKey.did(),
|
|
)
|
|
// old signing key still works due to did doc cache
|
|
await expect(attemptWithKey(origSigningKey)).resolves.toBeDefined()
|
|
// new signing key works
|
|
await expect(attemptWithKey(newSigningKey)).resolves.toBeDefined()
|
|
// old signing key no longer works after cache is updated
|
|
await expect(attemptWithKey(origSigningKey)).rejects.toThrow(
|
|
'jwt signature does not match jwt issuer',
|
|
)
|
|
})
|
|
|
|
it('throws if the user key is incorrect', async () => {
|
|
const bobKeypair = await network.pds.ctx.actorStore.keypair(bob)
|
|
|
|
const jwt = await createServiceJwt({
|
|
iss: alice,
|
|
aud: network.bsky.ctx.cfg.serverDid,
|
|
lxm: ids.AppBskyFeedGetTimeline,
|
|
keypair: bobKeypair,
|
|
})
|
|
|
|
await expect(
|
|
agent.api.app.bsky.actor.getProfile(
|
|
{ actor: sc.dids.carol },
|
|
{
|
|
headers: { authorization: `Bearer ${jwt}` },
|
|
},
|
|
),
|
|
).rejects.toThrow()
|
|
})
|
|
})
|