Skip to content

Commit 48ed635

Browse files
Merge pull request #24 from depot/fix-claim-exchange
Fix marking claim as successfully exchanged before success
2 parents 2079239 + 6ed8633 commit 48ed635

File tree

2 files changed

+13
-15
lines changed

2 files changed

+13
-15
lines changed

src/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import {claimSchema} from './types'
1010
import {authenticateAdmin} from './utils/auth'
1111
import {
1212
createClaim,
13-
exchangeClaim,
1413
getAllKeys,
14+
getClaim,
1515
getLatestKey,
16+
markClaimAsExchanged,
1617
setGitHubSession,
1718
setLatestKey,
1819
storeKey,
@@ -57,8 +58,8 @@ app.post('/claim', async ({req, json}) => {
5758
app.post('/exchange/:id', async ({req, text}) => {
5859
const claimId = req.param('id')
5960

60-
const claim = await exchangeClaim(claimId)
61-
if (!claim) throw new Error('challenge already used or not found')
61+
const claim = await getClaim(claimId)
62+
if (!claim || claim.exchanged) throw new Error('challenge already used or not found')
6263

6364
const {issuer, claimData, challengeCode} = claim
6465

@@ -90,6 +91,8 @@ app.post('/exchange/:id', async ({req, text}) => {
9091
claims: validatedClaims,
9192
})
9293

94+
await markClaimAsExchanged(claimId)
95+
9396
return text(token)
9497
})
9598

src/utils/dynamodb.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {DynamoDBDocumentClient, GetCommand, PutCommand, QueryCommand, UpdateComm
33
import {addMinutes, addSeconds, getUnixTime} from 'date-fns'
44
import type {webcrypto} from 'node:crypto'
55
import type {ClaimSchema} from '../types'
6+
import {logger} from './logger'
67
import type {JsonWebKeyWithKid, Key} from './oidc'
78

89
/**
@@ -93,27 +94,21 @@ export async function getClaim(claimId: string): Promise<ClaimRecord | null> {
9394
}
9495

9596
/**
96-
* Atomically mark a claim as exchanged and return the claim data
97+
* Mark a claim as successfully exchanged
9798
*/
98-
export async function exchangeClaim(claimId: string): Promise<ClaimRecord | null> {
99+
export async function markClaimAsExchanged(claimId: string): Promise<void> {
99100
try {
100-
const result = await docClient.send(
101+
await docClient.send(
101102
new UpdateCommand({
102103
TableName: TABLE_NAME,
103104
Key: {pk: `CLAIM#${claimId}`, sk: 'CLAIM'},
104105
UpdateExpression: 'SET exchanged = :true',
105-
ConditionExpression: 'attribute_exists(pk) AND exchanged = :false',
106-
ExpressionAttributeValues: {':true': true, ':false': false},
107-
ReturnValues: 'ALL_OLD',
106+
ConditionExpression: 'attribute_exists(pk)',
107+
ExpressionAttributeValues: {':true': true},
108108
}),
109109
)
110-
if (!result.Attributes) return null
111-
return result.Attributes as ClaimRecord
112110
} catch (error) {
113-
if (error instanceof Error && error.name === 'ConditionalCheckFailedException') {
114-
return null
115-
}
116-
throw error
111+
logger.error('Failed to mark claim as exchanged', {claimId, error})
117112
}
118113
}
119114

0 commit comments

Comments
 (0)