Skip to content

Commit

Permalink
Merge branch 'main' into radup--703
Browse files Browse the repository at this point in the history
  • Loading branch information
raducristianpopa committed Nov 29, 2022
2 parents 6378e3f + 48cdfa2 commit c6eaaa9
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 24 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/lint_test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ jobs:
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter openapi test

mock-account-provider:
runs-on: ubuntu-latest
needs: checkout
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter mock-account-provider build

open-payments:
runs-on: ubuntu-latest
needs: checkout
Expand All @@ -82,6 +91,7 @@ jobs:
- frontend
- auth
- openapi
- mock-account-provider
- open-payments
steps:
- uses: actions/checkout@v2
Expand Down
9 changes: 6 additions & 3 deletions packages/auth/seeds/development/01_grants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ exports.seed = function (knex) {
startMethod: ['redirect'],
finishMethod: 'redirect',
finishUri: 'https://example.com/finish',
client: 'https://backend/accounts/gfranklin',
clientKeyId: 'keyid-742ab7cd-1624-4d2e-af6e-e15a71638669',
clientNonce: 'example-client-nonce',
clientKeyId: 'http://fynbos/keys/1234',
continueToken: '566a929a-86bb-41b8-b12d-718fa4ab2db2',
continueId: '92c98ab7-9240-43b4-a86f-402f1c6fd6f5',
interactId: 'example-interact-id',
Expand All @@ -27,8 +28,9 @@ exports.seed = function (knex) {
startMethod: ['redirect'],
finishMethod: 'redirect',
finishUri: 'http://peer-auth:3006/finish',
client: 'https://peer-backend/accounts/pfry',
clientKeyId: 'keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5',
clientNonce: 'example-client-nonce',
clientKeyId: 'http://local-bank/keys/1234',
continueToken: 'fc7d255b-66f7-46f5-af56-65831a110604',
continueId: '006856cd-a34a-4d4a-bb69-af1e07980834',
interactId: 'local-bank-interact-id',
Expand All @@ -43,8 +45,9 @@ exports.seed = function (knex) {
startMethod: ['redirect'],
finishMethod: 'redirect',
finishUri: 'http://localhost:3300/mock-idp/fake-client?',
client: 'https://backend/accounts/gfranklin',
clientKeyId: 'keyid-742ab7cd-1624-4d2e-af6e-e15a71638669',
clientNonce: 'demo-client-nonce',
clientKeyId: 'http://fynbos/keys/1234',
continueToken: '301294e4-db8d-445b-b77e-d27583719ecc',
continueId: 'edbe6928-7d80-44a8-94b8-514e75759439',
interactId: 'demo-interact-id',
Expand Down
22 changes: 22 additions & 0 deletions packages/mock-account-provider/app/lib/crypto.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createPublicKey, generateKeyPairSync, type JsonWebKey } from 'crypto'

type OpenPaymentsJWK = JsonWebKey & {
alg: 'EdDSA'
kid: string
}

export const generateJwk = ({ keyId }: { keyId: string }): OpenPaymentsJWK => {
const jwk = createPublicKey(generateKeyPairSync('ed25519').privateKey).export(
{
format: 'jwk'
}
)

return {
alg: 'EdDSA',
kid: keyId,
kty: jwk.kty,
crv: jwk.crv,
x: jwk.x
}
}
77 changes: 61 additions & 16 deletions packages/mock-account-provider/app/lib/requesters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { gql } from '@apollo/client'
import type {
CreatePeerMutationResponse,
LiquidityMutationResponse,
CreatePaymentPointerMutationResponse,
PaymentPointer
PaymentPointer,
CreatePaymentPointerKeyMutationResponse,
CreatePaymentPointerKeyInput,
CreatePaymentPointerInput
} from '../../generated/graphql'
import { apolloClient } from './apolloClient'

Expand Down Expand Up @@ -113,7 +115,7 @@ export async function createPaymentPointer(
accountUrl: string,
assetCode: string,
assetScale: number
): Promise<CreatePaymentPointerMutationResponse> {
): Promise<PaymentPointer> {
const createPaymentPointerMutation = gql`
mutation CreatePaymentPointer($input: CreatePaymentPointerInput!) {
createPaymentPointer(input: $input) {
Expand All @@ -128,27 +130,70 @@ export async function createPaymentPointer(
}
}
`
const createPaymentPointerInput = {
input: {
asset: {
code: assetCode,
scale: assetScale
},
url: accountUrl,
publicName: accountName
}
const createPaymentPointerInput: CreatePaymentPointerInput = {
asset: {
code: assetCode,
scale: assetScale
},
url: accountUrl,
publicName: accountName
}

return apolloClient
.mutate({
mutation: createPaymentPointerMutation,
variables: createPaymentPointerInput
variables: {
input: createPaymentPointerInput
}
})
.then(({ data }) => {
console.log(data)

if (
!data.createPaymentPointer.success ||
!data.createPaymentPointer.paymentPointer
) {
throw new Error('Data was empty')
}

return data.createPaymentPointer.paymentPointer
})
}

export async function createPaymentPointerKey({
paymentPointerId,
jwk
}: {
paymentPointerId: string
jwk: string
}): Promise<CreatePaymentPointerKeyMutationResponse> {
const createPaymentPointerKeyMutation = gql`
mutation CreatePaymentPointerKey($input: CreatePaymentPointerKeyInput!) {
createPaymentPointerKey(input: $input) {
code
success
message
}
}
`
const createPaymentPointerKeyInput: CreatePaymentPointerKeyInput = {
paymentPointerId,
jwk
}

return apolloClient
.mutate({
mutation: createPaymentPointerKeyMutation,
variables: {
input: createPaymentPointerKeyInput
}
})
.then(({ data }): CreatePaymentPointerMutationResponse => {
.then(({ data }): CreatePaymentPointerKeyMutationResponse => {
console.log(data)
if (!data.createPaymentPointer.success) {
if (!data.createPaymentPointerKey.success) {
throw new Error('Data was empty')
}
return data.createPaymentPointer
return data.createPaymentPointerKey
})
}

Expand Down
17 changes: 12 additions & 5 deletions packages/mock-account-provider/app/lib/run_seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import type { SeedInstance, Account, Peering } from './parse_config'
import {
createPeer,
addPeerLiquidity,
createPaymentPointer
createPaymentPointer,
createPaymentPointerKey
} from './requesters'
import { v4 } from 'uuid'
import { mockAccounts } from './accounts.server'
import { generateJwk } from './crypto.server'

export async function setupFromSeed(config: SeedInstance): Promise<void> {
const peerResponses = await Promise.all(
Expand Down Expand Up @@ -52,7 +54,7 @@ export async function setupFromSeed(config: SeedInstance): Promise<void> {
false
)
}
const pp = await createPaymentPointer(
const paymentPointer = await createPaymentPointer(
config.self.graphqlUrl,
account.name,
`https://${CONFIG.self.hostname}/${account.path}`,
Expand All @@ -62,11 +64,16 @@ export async function setupFromSeed(config: SeedInstance): Promise<void> {

await mockAccounts.setPaymentPointer(
account.id,
pp.paymentPointer?.id,
pp.paymentPointer?.url
paymentPointer.id,
paymentPointer.url
)

return pp
await createPaymentPointerKey({
paymentPointerId: paymentPointer.id,
jwk: JSON.stringify(generateJwk({ keyId: `keyid-${account.id}` }))
})

return paymentPointer
})
)
console.log(JSON.stringify(accountResponses, null, 2))
Expand Down
2 changes: 2 additions & 0 deletions packages/open-payments/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export {
AuthenticatedClient,
UnauthenticatedClient
} from './client'

export { generateJwk } from './jwk'
44 changes: 44 additions & 0 deletions packages/open-payments/src/jwk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { generateKeyPairSync } from 'crypto'
import { generateJwk } from './jwk'

describe('jwk', (): void => {
describe('generateJwk', (): void => {
test('properly generates jwk', async (): Promise<void> => {
expect(generateJwk({ keyId: 'keyid' })).toEqual({
alg: 'EdDSA',
kid: 'keyid',
kty: 'OKP',
crv: 'Ed25519',
x: expect.any(String)
})
})

test('properly generates jwk with defined private key', async (): Promise<void> => {
expect(
generateJwk({
keyId: 'keyid',
privateKey: generateKeyPairSync('ed25519').privateKey
})
).toEqual({
alg: 'EdDSA',
kid: 'keyid',
kty: 'OKP',
crv: 'Ed25519',
x: expect.any(String)
})
})

test('throws if empty keyId', async (): Promise<void> => {
expect(() => generateJwk({ keyId: '' })).toThrow('KeyId cannot be empty')
})

test('throws if provided key is not EdDSA-Ed25519', async (): Promise<void> => {
expect(() =>
generateJwk({
keyId: 'keyid',
privateKey: generateKeyPairSync('ed448').privateKey
})
).toThrow('Key is not EdDSA-Ed25519')
})
})
})
34 changes: 34 additions & 0 deletions packages/open-payments/src/jwk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createPublicKey, generateKeyPairSync, KeyObject } from 'crypto'
import { JWK } from './types'

export const generateJwk = ({
privateKey: providedPrivateKey,
keyId
}: {
privateKey?: KeyObject
keyId: string
}): JWK => {
if (!keyId.trim()) {
throw new Error('KeyId cannot be empty')
}

const privateKey = providedPrivateKey
? providedPrivateKey
: generateKeyPairSync('ed25519').privateKey

const jwk = createPublicKey(privateKey).export({
format: 'jwk'
})

if (jwk.crv !== 'Ed25519' || jwk.kty !== 'OKP') {
throw new Error('Key is not EdDSA-Ed25519')
}

return {
alg: 'EdDSA',
kid: keyId,
kty: jwk.kty,
crv: jwk.crv,
x: jwk.x
}
}

0 comments on commit c6eaaa9

Please sign in to comment.