Something went wrong. Try again.
Browser extension: detect and subscribe to standard.site publications on ATProto
Something went wrong. Try again.
5.8 kB · 147 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'import { tmpdir } from 'node:os'import { join } from 'node:path'import { afterEach, describe, expect, it } from 'vitest'import { checkBundle, checkHostedMatchesLocal, checkManifestKey, checkRedirectUris, extensionIdFromKey, redirectUriFor,} from './check-oauth-metadata.mjs'
// The real pair from public/manifest.json, so a key or derivation change// that would silently move the unpacked id fails here.const MANIFEST_KEY = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9X42ElF0Js6o5Q4khUvEZJCEnEJuXEswyH4AXc9pA98vP5K/wIyj3grJIREAVHvJYCtAfvWPlLq//WQdnoRt5j7RljVDrwRxuxqDXZ7k3M6ipX8czg7wKfS0Gq2rTgVZD1po96eHTFNyxbaR08maLNIwNNWYqbwCECRR41uXdpw+XS66KvGZ8RybnPArkk0jW9lQ5ro/WlDpyjmTxWWYIM2nkZ/m2e66ZLCuT7HcYpHJmsEOH/xBUkgRZMzmEcQJk5m3rSuEOaB4DzSGZTaRy2OLzxMbAnpgKPTOSqa2RLYvb4MsrUgs2akezzGD0pJD46FkeB6eaLxqCprrIn3fIQIDAQAB'const UNPACKED = 'degljbilkggdpbobomfbgnellecgbkjj'const STORE = 'mecbfognmmefgjekidnddjjlddnfnlki'const IDS = { store: STORE, unpacked: UNPACKED }
let dirs = []afterEach(() => { for (const dir of dirs) rmSync(dir, { recursive: true, force: true }) dirs = []})
function distWith(contents) { const dir = mkdtempSync(join(tmpdir(), 'check-oauth-')) dirs.push(dir) writeFileSync(join(dir, 'bundle.js'), contents) return dir}
describe('extensionIdFromKey', () => { it('derives the unpacked id Chrome assigns to the manifest key', () => { expect(extensionIdFromKey(MANIFEST_KEY)).toBe(UNPACKED) })
it('only ever produces the a-p alphabet Chrome uses', () => { expect(extensionIdFromKey(MANIFEST_KEY)).toMatch(/^[a-p]{32}$/) })})
describe('checkRedirectUris', () => { it('passes when every declared id has a redirect uri', () => { const metadata = { redirect_uris: [redirectUriFor(STORE), redirectUriFor(UNPACKED)] } expect(checkRedirectUris(metadata, IDS)).toEqual([]) })
// The v1.2.1 regression: metadata carrying only the unpacked dev id, which // makes sign-in throw "Invalid redirect_uri" in every store install. it('fails the exact shape that shipped broken in v1.2.1', () => { const metadata = { redirect_uris: [redirectUriFor(UNPACKED)] } const problems = checkRedirectUris(metadata, IDS) expect(problems).toHaveLength(1) expect(problems[0]).toContain('store') expect(problems[0]).toContain(STORE) })
it('fails a redirect uri that belongs to no declared id', () => { const metadata = { redirect_uris: [ redirectUriFor(STORE), redirectUriFor(UNPACKED), redirectUriFor('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), ], } expect(checkRedirectUris(metadata, IDS)).toEqual([ expect.stringContaining('not a declared id'), ]) })
it('reports missing metadata rather than throwing', () => { expect(checkRedirectUris({}, IDS)).toHaveLength(2) })})
describe('checkManifestKey', () => { it('accepts the key that derives the declared unpacked id', () => { expect(checkManifestKey({ key: MANIFEST_KEY }, IDS)).toEqual([]) })
it('fails when the key and the declared unpacked id disagree', () => { expect(checkManifestKey({ key: MANIFEST_KEY }, { ...IDS, unpacked: 'b'.repeat(32) })).toEqual([ expect.stringContaining(UNPACKED), ]) })
it('skips the check for a store build, whose key is stripped', () => { expect(checkManifestKey({}, IDS)).toEqual([]) })})
describe('checkHostedMatchesLocal', () => { const local = { client_id: 'https://example.test/m.json', redirect_uris: ['a'] }
it('passes on identical documents regardless of key order', () => { expect( checkHostedMatchesLocal(local, { redirect_uris: ['a'], client_id: local.client_id }), ).toEqual([]) })
it('fails when the hosted copy is missing a redirect uri', () => { const problems = checkHostedMatchesLocal(local, { ...local, redirect_uris: [] }) expect(problems).toEqual([expect.stringContaining('differs from')]) })
// The v1.4.0 scope change failed here with two identical redirect_uris lists // printed as the evidence: the field that had drifted was never named. it('names the field that differs, not always redirect_uris', () => { const withScope = { ...local, scope: 'atproto include:app.userinput.authBasic' } const problems = checkHostedMatchesLocal(withScope, { ...local, scope: 'atproto' }) expect(problems).toHaveLength(1) expect(problems[0]).toContain('in scope:') expect(problems[0]).toContain('include:app.userinput.authBasic') expect(problems[0]).not.toContain('redirect_uris') })
it('reports a field the hosted copy does not have at all', () => { const problems = checkHostedMatchesLocal({ ...local, scope: 'atproto' }, local) expect(problems).toEqual([expect.stringContaining('hosted=(absent)')]) })
it('reports every drifted field, not just the first', () => { const problems = checkHostedMatchesLocal( { ...local, scope: 'atproto', client_name: 'substandard' }, { ...local, scope: 'x', client_name: 'y' }, ) expect(problems).toHaveLength(2) })})
describe('checkBundle', () => { it('passes when the built JS carries every declared redirect uri', () => { const dir = distWith(`x=${JSON.stringify([redirectUriFor(STORE), redirectUriFor(UNPACKED)])}`) expect(checkBundle(dir, IDS)).toEqual([]) })
// A rebuild from stale sources is invisible everywhere else: the metadata // file, the id list and the hosted copy can all agree while the artifact // about to be uploaded predates them. it('fails a stale bundle that predates the store id', () => { const dir = distWith(`x=${JSON.stringify([redirectUriFor(UNPACKED)])}`) expect(checkBundle(dir, IDS)).toEqual([expect.stringContaining(redirectUriFor(STORE))]) })})