Skip to content

Commit

Permalink
Merge pull request argentlabs#1981 from argentlabs/fix/BLO-934-2fa-ti…
Browse files Browse the repository at this point in the history
…me-skew

BLO-934 fix: 2fa time skew
  • Loading branch information
gergold committed Apr 3, 2023
2 parents ee03b76 + 3e78103 commit a53d2de
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
47 changes: 47 additions & 0 deletions packages/extension/src/shared/shield/backend/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import urlJoin from "url-join"

import { ARGENT_API_BASE_URL } from "../../api/constants"
import { fetcherWithArgentApiHeaders } from "../../api/fetcher"

interface GetTimeResponse {
time: number
}

/** backend time - at the time the response was generated - in seconds (aka 'epoch') - */

export const getBackendTimeSeconds = async () => {
try {
const fetcher = fetcherWithArgentApiHeaders()
const { time } = await fetcher<GetTimeResponse>(
urlJoin(ARGENT_API_BASE_URL, `time`),
)
return time
} catch (error) {
throw new Error("failed to request time")
}
}

/** determine skew (difference) between local time and backend time */

export const getBackendTimeSkew = async () => {
const timeStart = new Date().getTime()
const backendTimeSeconds = await getBackendTimeSeconds()
const timeNow = new Date().getTime()
/** average how long it took for one hop client -> server, or server -> client */
const responseTime = (timeNow - timeStart) / 2
/** approximate what backend time should be right now */
const backendTimeNow = backendTimeSeconds * 1000 + responseTime
/** determine skew (difference) between local time and backend time */
const backendTimeSkew = backendTimeNow - timeNow
return backendTimeSkew
}

/** determine the expected backend time right now in seconds (aka 'epoch') */

export const getBackendTimeNowSeconds = async () => {
const backendTimeSkew = await getBackendTimeSkew()
const timeNow = new Date().getTime()
const backendTimeNow = timeNow + backendTimeSkew
/** conver to epoch */
return Math.floor(backendTimeNow / 1000)
}
6 changes: 5 additions & 1 deletion packages/extension/src/shared/shield/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
generateKeyPair,
} from "jose"

import { getBackendTimeNowSeconds } from "./backend/time"
import { idb } from "./idb"

/** important that signingKey stays not 'extractable' from browser */
Expand Down Expand Up @@ -45,9 +46,12 @@ export const generateJwt = async () => {
const publicJwk = await exportJWK(publicKey)
const thumbprint = await calculateJwkThumbprint(publicJwk)

/** set issuer time from backend in case of discrepancy with local machine time */
const backendTimeNowSeconds = await getBackendTimeNowSeconds()

const jwt = await new SignJWT({})
.setProtectedHeader({ alg, jwk: publicJwk })
.setIssuedAt()
.setIssuedAt(backendTimeNowSeconds)
.setIssuer("kid:" + thumbprint)
.setExpirationTime("5m")
.sign(privateKey)
Expand Down

0 comments on commit a53d2de

Please sign in to comment.