Skip to content

Commit

Permalink
Test entryway session handling (#1818)
Browse files Browse the repository at this point in the history
test entryway session handling
  • Loading branch information
devinivy authored Nov 21, 2023
1 parent 20bf2ce commit 2b05980
Showing 1 changed file with 123 additions and 1 deletion.
124 changes: 123 additions & 1 deletion packages/pds/tests/entryway.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import fs from 'node:fs/promises'
import * as ui8 from 'uint8arrays'
import * as jose from 'jose'
import AtpAgent from '@atproto/api'
import { XRPCError } from '@atproto/xrpc'
import { Secp256k1Keypair } from '@atproto/crypto'
import { getPdsEndpoint, isValidDidDoc } from '@atproto/common'
import {
SeedClient,
TestPds,
TestPlc,
mockNetworkUtilities,
} from '@atproto/dev-env'
import { ids } from '@atproto/api/src/client/lexicons'
import { getPdsEndpoint, isValidDidDoc } from '@atproto/common'

describe('entryway', () => {
let plc: TestPlc
Expand Down Expand Up @@ -492,4 +493,125 @@ describe('entryway', () => {
})
expect(profile.value['displayName']).toEqual('Carol!')
})

describe('agent sessions', () => {
let dan: string

it('updates service url on account creation based on did doc.', async () => {
await entryway.ctx.db.db.updateTable('pds').set({ weight: 1 }).execute()
const agent = new AtpAgent({ service: entryway.url })
const { data: session } = await agent.createAccount({
email: '[email protected]',
handle: 'dan.test',
password: 'test123',
})
dan = session.did
await entryway.ctx.db.db.updateTable('pds').set({ weight: 0 }).execute()
expect(session.handle).toBe('dan.test')
assert(isValidDidDoc(session.didDoc))
expect(session.didDoc.alsoKnownAs).toEqual(['at://dan.test'])
expect(getPdsEndpoint(session.didDoc)).toBe(pds.url)
expect(agent.api.xrpc.uri.origin).toBe(pds.url)
})

it('updates service url on session creation, resumption based on did doc.', async () => {
// creation
const agent1 = new AtpAgent({ service: entryway.url })
expect(agent1.api.xrpc.uri.origin).toBe(entryway.url)
const { data: session } = await agent1.login({
identifier: 'dan.test',
password: 'test123',
})
assert(agent1.session)
const agentSession = agent1.session
expect(session.handle).toBe('dan.test')
assert(isValidDidDoc(session.didDoc))
expect(session.didDoc.alsoKnownAs).toEqual(['at://dan.test'])
expect(getPdsEndpoint(session.didDoc)).toBe(pds.url)
expect(agent1.api.xrpc.uri.origin).toBe(pds.url)
// resumption
const agent2 = new AtpAgent({ service: entryway.url })
expect(agent2.api.xrpc.uri.origin).toBe(entryway.url)
const { data: resumedSession } = await agent2.resumeSession(agentSession)
expect(resumedSession.handle).toBe('dan.test')
assert(isValidDidDoc(resumedSession.didDoc))
expect(resumedSession.didDoc.alsoKnownAs).toEqual(['at://dan.test'])
expect(getPdsEndpoint(resumedSession.didDoc)).toBe(pds.url)
expect(agent2.api.xrpc.uri.origin).toBe(pds.url)
})

it('updates service url on session refresh based on did doc.', async () => {
const agent = new AtpAgent({ service: entryway.url })
const authService = entryway.ctx.services.auth(entryway.ctx.db)
const { refresh: refreshToken } = await authService.createSession({
did: dan,
pdsDid: pds.ctx.cfg.service.did,
appPasswordName: null,
})
const expiredAccessToken = await authService.createAccessToken({
did: dan,
pdsDid: pds.ctx.cfg.service.did,
expiresIn: -1,
})
agent.session = {
did: dan,
handle: 'dan.test',
accessJwt: expiredAccessToken,
refreshJwt: refreshToken,
}
expect(agent.api.xrpc.uri.origin).toBe(entryway.url)
// since access token is expired, will cause a refresh flow
await agent.com.atproto.server.getAccountInviteCodes()
expect(agent.api.xrpc.uri.origin).toBe(pds.url)
expect(agent.session).toBeDefined()
expect(agent.session.accessJwt).not.toBe(expiredAccessToken)
expect(agent.session.refreshJwt).not.toBe(refreshToken)
})

it('initiates token refresh when pds sees unknown user.', async () => {
const { data: session } =
await entrywayAgent.api.com.atproto.server.createAccount({
email: '[email protected]',
handle: 'eve.test',
password: 'test123',
})
const authService = entryway.ctx.services.auth(entryway.ctx.db)
const tokens = await authService.createSession({
did: session.did,
pdsDid: pds.ctx.cfg.service.did, // not eve's pds
appPasswordName: null,
})
const attempt = (agent: AtpAgent) =>
agent.api.app.bsky.actor.putPreferences(
{ preferences: [] },
{
headers: SeedClient.getHeaders(tokens.access),
encoding: 'application/json',
},
)
const pdsDirectErr = await attempt(pdsAgent).catch((err) => err)
const entrywayProxyErr = await attempt(entrywayAgent).catch((err) => err)
assert(pdsDirectErr instanceof XRPCError)
assert(entrywayProxyErr instanceof XRPCError)
expect(pdsDirectErr.status).toBe(403)
expect(pdsDirectErr.error).toBe('AccountNotFound')
expect(entrywayProxyErr.status).toBe(400)
expect(entrywayProxyErr.error).toBe('ExpiredToken')
// refresh handled by agent
const agent = new AtpAgent({ service: entryway.url })
agent.session = {
did: session.did,
handle: session.handle,
accessJwt: tokens.access,
refreshJwt: tokens.refresh,
}
expect(agent.api.xrpc.uri.origin).toBe(entryway.url)
// since entryway serves an expiration error, will cause a refresh flow
await agent.api.app.bsky.actor.putPreferences({ preferences: [] })
expect(agent.api.xrpc.uri.origin).toBe(entryway.url)
expect(agent.session).toBeDefined()
expect(agent.session.accessJwt).not.toBe(tokens.access)
expect(agent.session.refreshJwt).not.toBe(tokens.refresh)
})
})
})

0 comments on commit 2b05980

Please sign in to comment.