Skip to content

Commit

Permalink
Merge pull request #6 from windingtree/fix/jwt-creation
Browse files Browse the repository at this point in the history
fix: Fixed JWT creation for ethereum and pem types of keys pair
  • Loading branch information
kostysh authored Nov 3, 2022
2 parents 7328207 + 6aa7252 commit 79a7747
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 70 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@windingtree/org.id-cli",
"version": "3.1.1",
"version": "3.1.2",
"description": "The ORGiD command-line utility",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
162 changes: 93 additions & 69 deletions src/api/jwt.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,57 @@
import type { ParsedArgv } from '../utils/env';
import { ethers, utils } from 'ethers';
import { parsers } from '@windingtree/org.id-utils';
import { createAuthJWTWithEthers } from '@windingtree/org.id-auth/dist/tokens';
import { createAuthJWTWithEthers, createAuthJWT } from '@windingtree/org.id-auth/dist/tokens';
import { initOrgIdResolver } from './resolveOrgId';
import { printInfo, printWarn } from '../utils/console';
import { getKeyPairsFromProject } from './project';
import prompts from 'prompts';
import { decrypt } from './common';
import { parseDid } from '@windingtree/org.id-utils/dist/parsers';
import { JWK } from '@windingtree/org.id-auth/dist/keys';

const createJwtWithEthereum = async (
issuer: string,
audience: string,
scope: string[] | undefined,
expiration: number | undefined,
accountAddress: string,
signerKey: string
): Promise<string> => {
const signer = new ethers.Wallet(signerKey);

const signerAddress = await signer.getAddress();

if (utils.getAddress(accountAddress) !== signerAddress) {
throw new Error(
`blockchainAccountId address is different from the signer address: ${signerAddress}`
);
}

return await createAuthJWTWithEthers(
signer,
issuer,
audience,
scope,
expiration
);
};

const createJwtWithPem = async (
issuer: string,
audience: string,
scope: string[] | undefined,
expiration: number | undefined,
signerKey: JWK
): Promise<string> => {
return await createAuthJWT(
signerKey,
issuer,
audience,
scope,
expiration
);
};

export const createJwt = async (
basePath: string,
Expand Down Expand Up @@ -49,6 +94,8 @@ export const createJwt = async (

const resolver = await initOrgIdResolver(basePath, args['--issuer']);

printInfo(`Resolving the ${args['--issuer']} please wait...`);

const { didDocument, didResolutionMetadata } = await resolver.resolve(
args['--issuer']
);
Expand All @@ -59,6 +106,8 @@ export const createJwt = async (
);
printWarn(didResolutionMetadata.error || 'Unknown error');
return;
} else {
printInfo('Success. The issuer DID is resolved and valid');
}

const verificationMethod = didDocument?.verificationMethod?.find(
Expand All @@ -69,82 +118,57 @@ export const createJwt = async (
throw Error(`Verification method ${args['--issuer']} not found`);
}

if (!verificationMethod.blockchainAccountId) {
throw Error('blockchainAccountId not found');
}
const keyPairRecords = await getKeyPairsFromProject(basePath);

const { accountAddress } = parsers.parseBlockchainAccountId(
verificationMethod.blockchainAccountId
);
const { fragment } = parseDid(args['--issuer']);

const keyPairRecords = await getKeyPairsFromProject(basePath);
if (!fragment) {
throw new Error(`Unable to extract verification method key Id from ${args['--issuer']}`);
}

const keyPair = keyPairRecords.find(
k => utils.getAddress(k.publicKey as string) === utils.getAddress(accountAddress)
k => k.tag === fragment
);

let signerKey: string;

if (keyPair) {
const { password } = await prompts({
type: 'password',
name: 'password',
message: `Enter the password for the key pair "${keyPair.tag}"`
});
signerKey = decrypt(keyPair.privateKey, password);
} else {
printWarn(`A key associated with blockchainAccountId ${accountAddress} not found`);

const { useCustomKey } = await prompts({
type: 'select',
name: 'useCustomKey',
message: 'Do you want to enter a custom key?',
choices: [
{
title: 'Yes',
value: true
},
{
title: 'No',
value: false
}
],
initial: 0
});

if (!useCustomKey) {
printWarn('Unable to create JWT without a key. Process terminated.');
return;
}

const { privateKey } = await prompts([
{
type: 'password',
name: 'privateKey',
message: `Please enter a private key for the account ${accountAddress}`,
}
]);

signerKey = privateKey;
if (!keyPair) {
throw new Error(`Key pair ${fragment} not found in the project`);
}

const signer = new ethers.Wallet(signerKey);

const signerAddress = await signer.getAddress();

if (utils.getAddress(accountAddress) !== signerAddress) {
throw new Error(
`blockchainAccountId address is different from the signer address: ${signerAddress}`
);
const { password } = await prompts({
type: 'password',
name: 'password',
message: `Enter the password for the key pair "${keyPair.tag}"`
});

let signerKey = decrypt(keyPair.privateKey, password);
let token: string;

switch (keyPair.type) {
case 'ethereum':
token = await createJwtWithEthereum(
args['--issuer'],
args['--audience'],
scope,
expiration,
keyPair.publicKey,
signerKey
);
break;
case 'pem':
signerKey = JSON.parse(signerKey);
token = await createJwtWithPem(
args['--issuer'],
args['--audience'],
scope,
expiration,
signerKey as unknown as JWK
);
break;
default:
throw new Error(
`Key pair ${keyPair.tag} of type ${keyPair.type} cannot be used for the JWT signing`
);
}

const token = await createAuthJWTWithEthers(
signer,
args['--issuer'],
args['--audience'],
scope,
expiration
);

printInfo(`JWT: ${token}`);
printInfo(`\n\nJWT: ${token}`);
};

0 comments on commit 79a7747

Please sign in to comment.