Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OpenID Federation playground #27

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions agent/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "agent",
"dependencies": {
"@credo-ts/askar": "0.6.0-alpha-20241119125554",
"@credo-ts/core": "0.6.0-alpha-20241119125554",
"@credo-ts/node": "0.6.0-alpha-20241119125554",
"@credo-ts/openid4vc": "0.6.0-alpha-20241119125554",
"@credo-ts/askar": "0.6.0-pr-2094-20241120112900",
"@credo-ts/core": "0.6.0-pr-2094-20241120112900",
"@credo-ts/node": "0.6.0-pr-2094-20241120112900",
"@credo-ts/openid4vc": "0.6.0-pr-2094-20241120112900",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"@animo-id/mdoc": "^0.2.38",
"cors": "^2.8.5",
Expand All @@ -24,6 +24,6 @@
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node dist/server.js",
"dev": "tsx watch -r dotenv/config src/server.ts dotenv_config_path=.env.development"
"dev": "tsx watch -r dotenv/config src/server.ts dotenv_config_path=.env.development dotenv_config_path=.env"
}
}
27 changes: 17 additions & 10 deletions agent/src/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,19 @@ apiRouter.get('/verifier', async (_, response: Response) => {
})

const zCreatePresentationRequestBody = z.object({
requestSignerType: z.enum(['x5c', 'openid-federation']),
presentationDefinitionId: z.string(),
requestScheme: z.string(),
responseMode: z.enum(['direct_post.jwt', 'direct_post']),
})

apiRouter.post('/requests/create', async (request: Request, response: Response) => {
const createPresentationRequestBody = zCreatePresentationRequestBody.parse(request.body)
const { presentationDefinitionId, requestScheme, responseMode, requestSignerType } =
await zCreatePresentationRequestBody.parseAsync(request.body)

const x509Certificate = getX509Certificate()

const definitionId = createPresentationRequestBody.presentationDefinitionId
const definitionId = presentationDefinitionId
const definition = allDefinitions.find((d) => d.id === definitionId)
if (!definition) {
return response.status(404).json({
Expand All @@ -209,22 +211,27 @@ apiRouter.post('/requests/create', async (request: Request, response: Response)
const { authorizationRequest, verificationSession } =
await agent.modules.openId4VcVerifier.createAuthorizationRequest({
verifierId: verifier.verifierId,
requestSigner: {
method: 'x5c',
x5c: [x509Certificate],
// FIXME: remove issuer param from credo as we can infer it from the url
issuer: `${AGENT_HOST}/siop/${verifier.verifierId}/authorize`,
},
requestSigner:
requestSignerType === 'x5c'
? {
method: 'x5c',
x5c: [x509Certificate],
// FIXME: remove issuer param from credo as we can infer it from the url
issuer: `${AGENT_HOST}/siop/${verifier.verifierId}/authorize`,
}
: {
method: 'openid-federation',
},
presentationExchange: {
definition,
},
responseMode: createPresentationRequestBody.responseMode,
responseMode,
})

console.log(authorizationRequest)

return response.json({
authorizationRequestUri: authorizationRequest.replace('openid4vp://', createPresentationRequestBody.requestScheme),
authorizationRequestUri: authorizationRequest.replace('openid4vp://', requestScheme),
verificationSessionId: verificationSession.id,
})
})
Expand Down
47 changes: 34 additions & 13 deletions app/components/VerifyBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@radix
import Link from 'next/link'
import { type FormEvent, useEffect, useState } from 'react'
import QRCode from 'react-qr-code'
import type { CreateRequestOptions, CreateRequestResponse } from './VerifyTab'
import { HighLight } from './highLight'
import { Alert, AlertDescription, AlertTitle } from './ui/alert'
import { Button } from './ui/button'
Expand All @@ -19,20 +20,11 @@ export type ResponseMode = 'direct_post' | 'direct_post.jwt'
type VerifyBlockProps = {
flowName: string
x509Certificate?: string
createRequest: ({
presentationDefinitionId,
requestScheme,
responseMode,
}: {
presentationDefinitionId: string
requestScheme: string
responseMode: ResponseMode
}) => Promise<{
verificationSessionId: string
authorizationRequestUri: string
}>
createRequest: (options: CreateRequestOptions) => Promise<CreateRequestResponse>
}

type RequestSignerType = CreateRequestOptions['requestSignerType']

export const VerifyBlock: React.FC<VerifyBlockProps> = ({ createRequest, flowName, x509Certificate }) => {
const [authorizationRequestUri, setAuthorizationRequestUri] = useState<string>()
const [verificationSessionId, setVerificationSessionId] = useState<string>()
Expand Down Expand Up @@ -62,6 +54,7 @@ export const VerifyBlock: React.FC<VerifyBlockProps> = ({ createRequest, flowNam
const isSuccess = requestStatus?.responseStatus === 'ResponseVerified'
const [presentationDefinitionId, setPresentationDefinitionId] = useState<string>()
const [requestScheme, setRequestScheme] = useState<string>('openid4vp://')
const [requestSignerType, setRequestSignerType] = useState<RequestSignerType>('x5c')

useEffect(() => {
getVerifier().then(setVerifier)
Expand Down Expand Up @@ -90,7 +83,12 @@ export const VerifyBlock: React.FC<VerifyBlockProps> = ({ createRequest, flowNam
if (!id) {
throw new Error('No definition')
}
const request = await createRequest({ presentationDefinitionId: id, requestScheme, responseMode })
const request = await createRequest({
requestSignerType,
presentationDefinitionId: id,
requestScheme,
responseMode,
})

setVerificationSessionId(request.verificationSessionId)
setAuthorizationRequestUri(request.authorizationRequestUri)
Expand Down Expand Up @@ -135,6 +133,29 @@ export const VerifyBlock: React.FC<VerifyBlockProps> = ({ createRequest, flowNam
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="response-mode">Request Signer Type</Label>
<Select
name="request-signer-type"
required
value={requestSignerType}
onValueChange={(value) => setRequestSignerType(value as RequestSignerType)}
>
<SelectTrigger className="w-1/2">
<SelectValue placeholder="Select request signer type" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem key="x5c" value="x5c">
<pre>X509 certificate</pre>
</SelectItem>
<SelectItem key="openid-federation" value="openid-federation">
<pre>OpenID Federation</pre>
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="request-scheme">Scheme</Label>
<Input
Expand Down
19 changes: 5 additions & 14 deletions app/components/VerifyTab.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
import { useEffect, useState } from 'react'
import { createRequest, getX509Certificate } from '../lib/api'
import { type ResponseMode, VerifyBlock } from './VerifyBlock'
import { VerifyBlock } from './VerifyBlock'

export type CreateRequestOptions = Parameters<typeof createRequest>[0]
export type CreateRequestResponse = Awaited<ReturnType<typeof createRequest>>

export function VerifyTab() {
const [x509Certificate, setX509Certificate] = useState<string>()

const createRequestForVerification = async (options: {
presentationDefinitionId: string
requestScheme: string
responseMode: ResponseMode
}) => {
return await createRequest({
requestScheme: options.requestScheme,
presentationDefinitionId: options.presentationDefinitionId,
responseMode: options.responseMode,
})
}

useEffect(() => {
getX509Certificate().then(({ certificate }) => setX509Certificate(certificate))
}, [])

return (
<>
<VerifyBlock flowName="Verify" createRequest={createRequestForVerification} x509Certificate={x509Certificate} />
<VerifyBlock flowName="Verify" createRequest={createRequest} x509Certificate={x509Certificate} />
</>
)
}
3 changes: 3 additions & 0 deletions app/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ export async function createRequest({
presentationDefinitionId,
requestScheme,
responseMode,
requestSignerType,
}: {
requestSignerType: 'x5c' | 'openid-federation'
presentationDefinitionId: string
requestScheme: string
responseMode: 'direct_post' | 'direct_post.jwt'
Expand All @@ -88,6 +90,7 @@ export async function createRequest({
'Content-Type': 'application/json',
},
body: JSON.stringify({
requestSignerType,
presentationDefinitionId,
requestScheme,
responseMode,
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
},
"devDependencies": {
"@biomejs/biome": "^1.8.3"
},
"pnpm": {
"resolutions": {
"@openid-federation/core": "0.1.1-alpha.14"
}
}
}
Loading