clearing auth token on address change 🍡

This commit is contained in:
W.J. “dysbulic” H
2022-02-13 17:16:30 -05:00
committed by Scott Stevenson
parent 58baac0d44
commit 792609c2c0
5 changed files with 36 additions and 19 deletions

View File

@@ -11,10 +11,11 @@ const unauthorizedVariables = {
function getHeaderToken(req: Request): string | null {
const authHeader = req.headers.authorization;
if (!authHeader) return null;
if (authHeader.substring(0, 6) !== 'Bearer')
throw new Error('invalid token type');
if (!authHeader.startsWith('Bearer')) {
throw new Error(`Invalid Token Type: ${authHeader.split(/\s/)[0]}`);
}
const token = authHeader.replace('Bearer', '').trim();
const token = authHeader.replace(/^Bearer/, '').trim();
if (token.length === 0) return null;
return token;
}
@@ -40,13 +41,13 @@ export const authHandler = async (
return;
}
const id = await getOrCreatePlayerId(claim.iss);
const { id, created } = await getOrCreatePlayerId(claim.iss);
const hasuraVariables = {
'X-Hasura-Role': 'player',
'X-Hasura-User-Id': id,
};
res.json(hasuraVariables);
res.status(created ? 201 : 200).json(hasuraVariables);
}
};

View File

@@ -22,6 +22,7 @@ const status: Record<string, string> = {};
*/
export async function getOrCreatePlayerId(ethereumAddress: string) {
const ethAddress = ethereumAddress.toLowerCase();
let created = false;
const {
player: [existing],
} = await client.GetPlayerFromETH({
@@ -46,6 +47,7 @@ export async function getOrCreatePlayerId(ethereumAddress: string) {
status[ethAddress] = 'creating';
console.info(`Account Creation: ${ethAddress}`);
({ id } = await createPlayer(ethAddress));
created = true;
status[ethAddress] = 'created';
} catch (err) {
console.error(
@@ -57,13 +59,13 @@ export async function getOrCreatePlayerId(ethereumAddress: string) {
if (!id) {
const {
player: [created],
player: [newPlayer],
} = await client.GetPlayerFromETH({
ethereumAddress: ethAddress,
});
({ id } = created ?? {});
({ id } = newPlayer ?? {});
}
}
return id;
return { id, created };
}

View File

@@ -38,13 +38,20 @@ export async function createToken(
export async function verifyToken(
token: string,
provider: providers.Web3Provider,
provider: providers.JsonRpcProvider,
connectedAddress?: string,
): Promise<Maybe<Claim>> {
const address = provider.getSigner().getAddress();
const rawToken = Base64.decode(token, 'base64');
const [proof, rawClaim] = JSON.parse(rawToken);
const claim: Claim = JSON.parse(rawClaim);
const claimant = claim.iss;
if (connectedAddress != null && claimant !== connectedAddress) {
throw new Error(
`Connected address (${connectedAddress}) ≠ claim issuer (${claimant}).`,
);
}
const valid = await verifySignature(claimant, rawClaim, proof, provider);
if (!valid) {

View File

@@ -33,15 +33,21 @@ async function getWalletType(
address: string,
provider: providers.BaseProvider,
): Promise<WalletType> {
const code = await new Promise((resolve) => {
const code = await new Promise((resolve, reject) => {
const seconds = 45;
const id = setTimeout(() => {
throw new Error(`\`.getCode\` Timed Out After ${seconds}s`);
reject(new Error(`\`.getCode\` Timed Out After ${seconds}s`));
}, seconds * 1000);
provider.getCode(address).then((c) => {
clearTimeout(id);
resolve(c);
});
provider
.getCode(address)
.then((c) => {
clearTimeout(id);
resolve(c);
})
.catch((err) => {
console.error('`.getCode` Error', err);
reject(err);
});
});
return code === '0x' ? WalletType.EOA : WalletType.SMART;
}

View File

@@ -67,12 +67,13 @@ const web3Modal =
export async function getExistingAuth(
ethersProvider: providers.Web3Provider,
connectedAddress: string,
): Promise<Maybe<string>> {
const token = getTokenFromStore();
if (!token) return null;
try {
const res = await did.verifyToken(token, ethersProvider);
await did.verifyToken(token, ethersProvider, connectedAddress);
return token;
} catch (e) {
clearToken();
@@ -145,7 +146,7 @@ export const Web3ContextProvider: React.FC<Web3ContextProviderOptions> = ({
const web3Provider = new providers.Web3Provider(modal);
const addr = await web3Provider.getSigner().getAddress();
let token = await getExistingAuth(web3Provider);
let token = await getExistingAuth(web3Provider, addr);
if (!token) {
token = await authenticateWallet(web3Provider);
@@ -159,7 +160,7 @@ export const Web3ContextProvider: React.FC<Web3ContextProviderOptions> = ({
if (resetUrqlClient) resetUrqlClient();
} catch (error) {
console.error(error); // eslint-disable-line no-console
console.error('`connect` Error', error); // eslint-disable-line no-console
disconnect();
} finally {
setConnecting(false);