cache the passkey JWANT access token for multiple signatures
This commit is contained in:
@@ -85,7 +85,7 @@ export const generateSeed = (): string => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Retreive an access token
|
||||
* Retrieve an access token, or "" if no DID is provided.
|
||||
*
|
||||
* @return {*}
|
||||
*/
|
||||
|
||||
@@ -5,9 +5,10 @@ import * as R from "ramda";
|
||||
import { DEFAULT_IMAGE_API_SERVER } from "@/constants/app";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
import { accessToken } from "@/libs/crypto";
|
||||
import { NonsensitiveDexie } from "@/db/index";
|
||||
import { getAccount } from "@/libs/util";
|
||||
import { db, NonsensitiveDexie } from "@/db/index";
|
||||
import { getAccount, getPasskeyExpirationSeconds } from "@/libs/util";
|
||||
import { createEndorserJwtForKey, KeyMeta } from "@/libs/crypto/vc";
|
||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||
|
||||
export const SCHEMA_ORG_CONTEXT = "https://schema.org";
|
||||
// the object in RegisterAction claims
|
||||
@@ -447,12 +448,57 @@ export function didInfo(
|
||||
return didInfoForContact(did, activeDid, contact, allMyDids).displayName;
|
||||
}
|
||||
|
||||
let passkeyAccessToken: string = "";
|
||||
let passkeyTokenExpirationEpochSeconds: number = 0;
|
||||
|
||||
export function clearPasskeyToken() {
|
||||
passkeyAccessToken = "";
|
||||
passkeyTokenExpirationEpochSeconds = 0;
|
||||
}
|
||||
|
||||
export function tokenExpiryTimeDescription() {
|
||||
if (
|
||||
!passkeyAccessToken ||
|
||||
passkeyTokenExpirationEpochSeconds < new Date().getTime() / 1000
|
||||
) {
|
||||
return "Token has expired";
|
||||
} else {
|
||||
return (
|
||||
"Token expires at " +
|
||||
new Date(passkeyTokenExpirationEpochSeconds * 1000).toLocaleString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the headers for a request, potentially including Authorization
|
||||
*/
|
||||
export async function getHeaders(did?: string) {
|
||||
const headers: { "Content-Type": string; Authorization?: string } = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
if (did) {
|
||||
const token = await accessToken(did);
|
||||
let token;
|
||||
const account = await getAccount(did);
|
||||
if (account?.passkeyCredIdHex) {
|
||||
if (
|
||||
passkeyAccessToken &&
|
||||
passkeyTokenExpirationEpochSeconds > Date.now() / 1000
|
||||
) {
|
||||
// there's an active current passkey token
|
||||
token = passkeyAccessToken;
|
||||
} else {
|
||||
// there's no current passkey token or it's expired
|
||||
token = await accessToken(did);
|
||||
|
||||
passkeyAccessToken = token;
|
||||
const passkeyExpirationSeconds = await getPasskeyExpirationSeconds();
|
||||
passkeyTokenExpirationEpochSeconds =
|
||||
Date.now() / 1000 + passkeyExpirationSeconds;
|
||||
}
|
||||
} else {
|
||||
token = await accessToken(did);
|
||||
}
|
||||
headers["Authorization"] = "Bearer " + token;
|
||||
} else {
|
||||
// it's often OK to request without auth; we assume necessary checks are done earlier
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
// many of these are also found in endorser-mobile utility.ts
|
||||
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
import { IIdentifier } from "@veramo/core";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
|
||||
import { DEFAULT_PUSH_SERVER } from "@/constants/app";
|
||||
import { accountsDB, db } from "@/db/index";
|
||||
import { Account } from "@/db/tables/accounts";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import {DEFAULT_PASSKEY_EXPIRATION_MINUTES, MASTER_SETTINGS_KEY} from "@/db/tables/settings";
|
||||
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
||||
import { GenericCredWrapper, containsHiddenDid } from "@/libs/endorserServer";
|
||||
import * as serverUtil from "@/libs/endorserServer";
|
||||
import { registerCredential } from "@/libs/crypto/vc/passkeyDidPeer";
|
||||
|
||||
import { Buffer } from "buffer";
|
||||
import {KeyMeta} from "@/libs/crypto/vc";
|
||||
import {createPeerDid} from "@/libs/crypto/vc/didPeer";
|
||||
import { KeyMeta } from "@/libs/crypto/vc";
|
||||
import { createPeerDid } from "@/libs/crypto/vc/didPeer";
|
||||
|
||||
export const PRIVACY_MESSAGE =
|
||||
"The data you send will be visible to the world -- except: your IDs and the IDs of anyone you tag will stay private, only visible to them and others you explicitly allow.";
|
||||
@@ -273,6 +272,15 @@ export const registerSaveAndActivatePasskey = async (
|
||||
return account;
|
||||
};
|
||||
|
||||
export const getPasskeyExpirationSeconds = async (): Promise<number> => {
|
||||
await db.open();
|
||||
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||
const passkeyExpirationSeconds =
|
||||
(settings?.passkeyExpirationMinutes ?? DEFAULT_PASSKEY_EXPIRATION_MINUTES) *
|
||||
60;
|
||||
return passkeyExpirationSeconds;
|
||||
};
|
||||
|
||||
export const sendTestThroughPushServer = async (
|
||||
subscriptionJSON: PushSubscriptionJSON,
|
||||
skipFilter: boolean,
|
||||
|
||||
Reference in New Issue
Block a user