* Add linting rule to sort imports * remove spacing between import groups * changeset * changeset * prettier config fine tuning * forbid use of deprecated imports * tidy
		
			
				
	
	
		
			93 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { AtpAgent } from '@atproto/api'
 | 
						|
import { Keypair, Secp256k1Keypair } from '@atproto/crypto'
 | 
						|
import { SeedClient, TestNetwork, usersSeed } from '@atproto/dev-env'
 | 
						|
import { createServiceJwt } from '@atproto/xrpc-server'
 | 
						|
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()
 | 
						|
  })
 | 
						|
})
 |