From 697ff0c40dda90e81214331c1d4df62a75c7b93b Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 16:03:36 +0100 Subject: [PATCH 01/10] feat: federation in the wallet Signed-off-by: Jan --- apps/easypid/src/app/(app)/issuer.tsx | 13 +- .../FunkeCredentialNotificationScreen.tsx | 2 +- .../receive/slides/VerifyPartySlide.tsx | 21 ++- ...keOpenIdPresentationNotificationScreen.tsx | 12 +- .../FunkePresentationNotificationScreen.tsx | 7 +- .../wallet/FunkeIssuerDetailScreen.tsx | 127 +++++++++--------- apps/easypid/src/utils/issuer.ts | 52 ------- packages/agent/src/invitation/handler.ts | 37 +++-- .../agent/src/providers/AgentProvider.tsx | 5 +- .../src/providers/TrustedEntitiesProvider.tsx | 69 ++++++++++ packages/agent/src/providers/index.ts | 1 + 11 files changed, 193 insertions(+), 153 deletions(-) delete mode 100644 apps/easypid/src/utils/issuer.ts create mode 100644 packages/agent/src/providers/TrustedEntitiesProvider.tsx diff --git a/apps/easypid/src/app/(app)/issuer.tsx b/apps/easypid/src/app/(app)/issuer.tsx index 12e186cf..0d3916db 100644 --- a/apps/easypid/src/app/(app)/issuer.tsx +++ b/apps/easypid/src/app/(app)/issuer.tsx @@ -2,7 +2,16 @@ import { FunkeIssuerDetailScreen } from '@easypid/features/wallet/FunkeIssuerDet import { useLocalSearchParams } from 'expo-router' export default function Screen() { - const { host } = useLocalSearchParams() + const { entityId, trustedEntityIds, name, logo } = useLocalSearchParams() - return + const trustedEntityIdsArray = Array.isArray(trustedEntityIds) ? trustedEntityIds : trustedEntityIds?.split(',') ?? [] + + return ( + + ) } diff --git a/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx b/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx index e7194bf8..31fb3525 100644 --- a/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx +++ b/apps/easypid/src/features/receive/FunkeCredentialNotificationScreen.tsx @@ -352,8 +352,8 @@ export function FunkeCredentialNotificationScreen() { logo={credentialDisplay.issuer.logo} entityId={issuerMetadata?.credential_issuer as string} lastInteractionDate={activities[0]?.date} - approvalsCount={0} onContinue={onCheckCardContinue} + trustedEntityIds={Object.keys(credentialsForRequest?.verifier.verifiedEntityIds ?? [])} /> ), }, diff --git a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx index 7bc8909b..15b071a9 100644 --- a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx +++ b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx @@ -25,8 +25,8 @@ interface VerifyPartySlideProps { logo?: DisplayImage backgroundColor?: string lastInteractionDate?: string - approvalsCount?: number onContinue?: () => Promise + trustedEntityIds?: string[] } export const VerifyPartySlide = ({ @@ -36,8 +36,8 @@ export const VerifyPartySlide = ({ logo, backgroundColor, lastInteractionDate, - approvalsCount, onContinue, + trustedEntityIds, }: VerifyPartySlideProps) => { const router = useRouter() const { onNext, onCancel } = useWizard() @@ -54,7 +54,9 @@ export const VerifyPartySlide = ({ } const onPressVerifiedIssuer = withHaptics(() => { - router.push(`/issuer?entityId=${entityId}`) + router.push( + `/issuer?name=${name}&logo=${logo?.url}&entityId=${entityId}&trustedEntityIds=${trustedEntityIds?.join(',') ?? ''}` + ) }) const onPressInteraction = withHaptics(() => { @@ -93,15 +95,20 @@ export const VerifyPartySlide = ({ - {approvalsCount ? ( + {trustedEntityIds && trustedEntityIds.length > 0 ? ( ) : ( - + )} credentialsForRequest && getOpenIdFedIssuerMetadata(credentialsForRequest.verifier.entityId), - [credentialsForRequest] - ) const lastInteractionDate = activities?.[0]?.date + const shouldUsePin = useShouldUsePinForSubmission(credentialsForRequest) useEffect(() => { if (credentialsForRequest) return @@ -154,8 +146,8 @@ export function FunkeOpenIdPresentationNotificationScreen() { entityId={credentialsForRequest?.verifier.entityId as string} verifierName={credentialsForRequest?.verifier.name} logo={credentialsForRequest?.verifier.logo} + trustedEntityIds={Object.keys(credentialsForRequest?.verifier.verifiedEntityIds ?? [])} lastInteractionDate={lastInteractionDate} - approvalsCount={fedDisplayData?.approvals.length} onComplete={() => pushToWallet('replace')} /> ) diff --git a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx index 0e6010e8..2b360462 100644 --- a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx @@ -13,8 +13,7 @@ interface FunkePresentationNotificationScreenProps { verifierName?: string logo?: DisplayImage lastInteractionDate?: string - approvalsCount?: number - + trustedEntityIds?: string[] submission?: FormattedSubmission usePin: boolean isAccepting: boolean @@ -28,13 +27,13 @@ export function FunkePresentationNotificationScreen({ verifierName, logo, lastInteractionDate, - approvalsCount, usePin, onAccept, onDecline, isAccepting, submission, onComplete, + trustedEntityIds, }: FunkePresentationNotificationScreenProps) { return ( ), }, diff --git a/apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx b/apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx index 95ed1a50..6381ff97 100644 --- a/apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx +++ b/apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx @@ -1,53 +1,36 @@ -import { getOpenIdFedIssuerMetadata } from '@easypid/utils/issuer' import { Circle, FlexPage, Heading, HeroIcons, + IconContainer, Image, MessageBox, Paragraph, ScrollView, type ScrollViewRefType, - Stack, XStack, YStack, - useToastController, } from '@package/ui' -import { useRouter } from 'expo-router' -import { TextBackButton, useHaptics, useScrollViewPosition } from 'packages/app/src' +import { useTrustedEntities } from 'packages/agent/src' +import { TextBackButton, useScrollViewPosition } from 'packages/app/src' import { useRef } from 'react' -import { Linking } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' interface FunkeIssuerDetailScreenProps { - host: string + name: string + logo?: string + entityId?: string + trustedEntityIds?: string[] } -export function FunkeIssuerDetailScreen({ host }: FunkeIssuerDetailScreenProps) { - const toast = useToastController() - const router = useRouter() - const { withHaptics, errorHaptic } = useHaptics() - const data = getOpenIdFedIssuerMetadata(host) - - if (!data) { - router.back() - errorHaptic() - return toast.show('Currently unavailable.', { - customData: { - preset: 'warning', - }, - }) - } +export function FunkeIssuerDetailScreen({ name, logo, entityId, trustedEntityIds = [] }: FunkeIssuerDetailScreenProps) { + const { trustedEntities } = useTrustedEntities() const { handleScroll, isScrolledByOffset, scrollEventThrottle } = useScrollViewPosition() const { bottom } = useSafeAreaInsets() const scrollViewRef = useRef(null) - const openDomain = withHaptics(() => { - Linking.openURL(`https://${host}`) - }) - return ( } /> - - - + {logo ? ( + + + + ) : ( + + + + )} - {data.display.name} - - {host} + {name} + + Website - Approvals - A list of entities that have approved {data.display.name}. - - - {data.approvals.map((approval) => ( - - - - - - {approval.name} - Owned by {approval.ownedBy.display.name} - - - ))} + Trusted by + + A list of organizations and whether they have approved{' '} + {name}. + - - - Trust marks - Certifications that verify {data.display.name}'s security and quality standards. + {trustedEntities.map((entity) => { + const isTrusted = trustedEntityIds.includes(entity.entity_id) + + return ( + + {entity.logo_uri && ( + + + + )} + + {entity.organization_name} + + ) : ( + + ) + } + /> + + + ) + })} - - {data.certifications.map((certification) => ( - - {certification} - - ))} - diff --git a/apps/easypid/src/utils/issuer.ts b/apps/easypid/src/utils/issuer.ts deleted file mode 100644 index 15d8ac69..00000000 --- a/apps/easypid/src/utils/issuer.ts +++ /dev/null @@ -1,52 +0,0 @@ -const DEFAULT_FUNKE_HOST = 'funke.animo.id' - -const FUNKE_ISSUER_DATA = { - host: DEFAULT_FUNKE_HOST, - display: { - name: 'Animo', - logo: { - url: 'https://i.imgur.com/5kxpKzA.png', - altText: 'Animo Solutions logo', - }, - }, - approvals: [ - { - id: '7c82e94d-d650-4230-9586-cc5e0bec1d88', - name: 'Dutch Gov eID list', - ownedBy: { - did: 'did:web:dutch.gov', - display: { - name: 'Dutch Gov', - logo: { - url: 'https://i.imgur.com/lqfQV5g.png', - altText: 'Dutch Gov logo', - }, - isGovernment: true, - }, - }, - }, - { - id: '1e5b0c77-891f-4db6-b5b0-b174e7b38d30', - name: 'Registered Businesses', - ownedBy: { - did: 'did:web:registered.businesses', - display: { - name: 'Registered Businesses', - logo: { - url: 'https://i.imgur.com/eoXTZS5.jpeg', - altText: 'Registered Businesses logo', - }, - }, - }, - }, - ], - certifications: ['eIDAS compliant', 'ISO/IEC 27001'], -} - -export const getOpenIdFedIssuerMetadata = (host: string) => { - if (host === FUNKE_ISSUER_DATA.host) { - return FUNKE_ISSUER_DATA - } - - return null -} diff --git a/packages/agent/src/invitation/handler.ts b/packages/agent/src/invitation/handler.ts index 98978eac..80de4671 100644 --- a/packages/agent/src/invitation/handler.ts +++ b/packages/agent/src/invitation/handler.ts @@ -54,6 +54,7 @@ import { import { setBatchCredentialMetadata } from '../openid4vc/batchMetadata' import { getCredentialBindingResolver } from '../openid4vc/credentialBindingResolver' import { extractOpenId4VcCredentialMetadata, setOpenId4VcCredentialMetadata } from '../openid4vc/displayMetadata' +import { TRUSTED_ENTITIES } from '../providers/TrustedEntitiesProvider' import { BiometricAuthenticationError } from './error' import { fetchInvitationDataUrl } from './fetchInvitation' @@ -449,20 +450,21 @@ export async function withTrustedCertificate( } export type CredentialsForProofRequest = Awaited> -export const getCredentialsForProofRequest = async ({ - agent, - data, - uri, - allowUntrustedFederation = true, // TODO: True for now -}: { + +export type GetCredentialsForProofRequestOptions = { agent: EitherAgent - // Either data or uri can be provided data?: string uri?: string allowUntrustedFederation?: boolean -}) => { - let requestUri: string +} +export const getCredentialsForProofRequest = async ({ + agent, + data, + uri, + allowUntrustedFederation = true, +}: GetCredentialsForProofRequestOptions) => { + let requestUri: string let requestData = data const { entityId = undefined, data: fromFederationData = null } = allowUntrustedFederation @@ -496,6 +498,22 @@ export const getCredentialsForProofRequest = async ({ resolved.authorizationRequest.authorizationRequestPayload.client_metadata } + let verifiedEntityIds: Record = {} + if (entityId) { + const resolvedChains = await agent.modules.openId4VcHolder.resolveOpenIdFederationChains({ + entityId: entityId ?? '', + trustAnchorEntityIds: TRUSTED_ENTITIES, + }) + + // Return which resolved chains are actually resolved + verifiedEntityIds = Object.fromEntries( + resolvedChains.map((chain) => [ + chain.trustAnchorEntityConfiguration.sub, + TRUSTED_ENTITIES.includes(chain.trustAnchorEntityConfiguration.sub), + ]) + ) + } + let formattedSubmission: FormattedSubmission if (resolved.presentationExchange) { formattedSubmission = formatDifPexCredentialsForRequest( @@ -531,6 +549,7 @@ export const getCredentialsForProofRequest = async ({ } : undefined, name: clientMetadata?.client_name, + verifiedEntityIds, }, formattedSubmission, } as const diff --git a/packages/agent/src/providers/AgentProvider.tsx b/packages/agent/src/providers/AgentProvider.tsx index c79c1ab7..778767c3 100644 --- a/packages/agent/src/providers/AgentProvider.tsx +++ b/packages/agent/src/providers/AgentProvider.tsx @@ -6,6 +6,7 @@ import NativeAgentProvider from '@credo-ts/react-hooks' import { ExchangeRecordDisplayMetadataProvider } from './ExchangeRecordDisplayMetadataProvider' import { MdocRecordProvider } from './MdocProvider' import { SdJwtVcRecordProvider } from './SdJwtVcsProvider' +import { TrustedEntitiesProvider } from './TrustedEntitiesProvider' import { W3cCredentialRecordProvider } from './W3cCredentialsProvider' export interface AgentProviderProps { @@ -17,7 +18,9 @@ export const AgentProvider = ({ agent, children }: PropsWithChildren - {children} + + {children} + diff --git a/packages/agent/src/providers/TrustedEntitiesProvider.tsx b/packages/agent/src/providers/TrustedEntitiesProvider.tsx new file mode 100644 index 00000000..abd20c94 --- /dev/null +++ b/packages/agent/src/providers/TrustedEntitiesProvider.tsx @@ -0,0 +1,69 @@ +import { OpenId4VcSiopHolderService } from '@credo-ts/openid4vc' +import type { FullAppAgent } from 'packages/agent/src' +import { type ReactNode, createContext, useContext, useEffect, useState } from 'react' + +export const TRUSTED_ENTITIES = [ + 'https://funke.animo.id/siop/0193687b-0c27-7b82-a686-ff857dc6bbb3', + 'https://funke.animo.id/siop/0193687f-20d8-720a-9139-ed939ba510fa', +] satisfies [string, ...string[]] + +type TrustedEntity = { + entity_id: string + organization_name: string + logo_uri?: string +} + +type TrustedEntitiesContextType = { + trustedEntities: TrustedEntity[] + isLoading: boolean +} + +const TrustedEntitiesContext = createContext(undefined) + +export function TrustedEntitiesProvider({ agent, children }: { agent: FullAppAgent; children: ReactNode }) { + const [isLoading, setIsLoading] = useState(true) + const [trustedEntities, setTrustedEntities] = useState([]) + + useEffect(() => { + async function fetchTrustedEntities() { + try { + const openId4VcSiopHolderService = agent.dependencyManager.resolve(OpenId4VcSiopHolderService) + + // Fetch configurations for all trusted entities + const entityPromises = TRUSTED_ENTITIES.map((entityId) => + openId4VcSiopHolderService.fetchOpenIdFederationEntityConfiguration(agent.context, { + entityId, + }) + ) + const entitiesResults = await Promise.all(entityPromises) + const entities = entitiesResults.map((result) => { + return { + entity_id: result.iss, + organization_name: result.metadata?.federation_entity?.organization_name ?? 'Unknown entity', + logo_uri: result.metadata?.federation_entity?.logo_uri, + } + }) + + setTrustedEntities(entities) + } catch (error) { + console.error('Failed to fetch trusted entities:', error) + } finally { + setIsLoading(false) + } + } + + fetchTrustedEntities() + }, [agent]) + + return ( + {children} + ) +} + +export function useTrustedEntities() { + const context = useContext(TrustedEntitiesContext) + if (context === undefined) { + throw new Error('useTrustedEntities must be used within a TrustedEntitiesProvider') + } + return context +} diff --git a/packages/agent/src/providers/index.ts b/packages/agent/src/providers/index.ts index 28c3804e..fcfa0e24 100644 --- a/packages/agent/src/providers/index.ts +++ b/packages/agent/src/providers/index.ts @@ -7,3 +7,4 @@ export { } from './W3cCredentialsProvider' export { useSdJwtVcRecordById, useSdJwtVcRecords, SdJwtVcRecord, SdJwtVc } from './SdJwtVcsProvider' export { useMdocRecordById, useMdocRecords, Mdoc, MdocRecord } from './MdocProvider' +export { useTrustedEntities } from './TrustedEntitiesProvider' From 7c19153c7a132c277c21b98d6395465168d82beb Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 16:11:22 +0100 Subject: [PATCH 02/10] chore: cleanup --- apps/easypid/src/app/(app)/_layout.tsx | 4 ++-- .../easypid/src/app/(app)/{issuer.tsx => federation.tsx} | 4 ++-- .../receive/FunkeCredentialNotificationScreen.tsx | 1 - .../src/features/receive/slides/VerifyPartySlide.tsx | 8 ++++++-- .../share/FunkeOpenIdPresentationNotificationScreen.tsx | 2 +- .../share/FunkePresentationNotificationScreen.tsx | 6 +++--- ...rDetailScreen.tsx => FunkeFederationDetailScreen.tsx} | 9 +++++++-- 7 files changed, 21 insertions(+), 13 deletions(-) rename apps/easypid/src/app/(app)/{issuer.tsx => federation.tsx} (77%) rename apps/easypid/src/features/wallet/{FunkeIssuerDetailScreen.tsx => FunkeFederationDetailScreen.tsx} (95%) diff --git a/apps/easypid/src/app/(app)/_layout.tsx b/apps/easypid/src/app/(app)/_layout.tsx index d5084138..6d770153 100644 --- a/apps/easypid/src/app/(app)/_layout.tsx +++ b/apps/easypid/src/app/(app)/_layout.tsx @@ -1,4 +1,4 @@ -import { Redirect, Stack, useGlobalSearchParams, useLocalSearchParams, usePathname, useRouter } from 'expo-router' +import { Redirect, Stack, useGlobalSearchParams, usePathname, useRouter } from 'expo-router' import { TypedArrayEncoder } from '@credo-ts/core' import { useSecureUnlock } from '@easypid/agent' @@ -137,7 +137,7 @@ export default function AppLayout() { - + diff --git a/apps/easypid/src/app/(app)/issuer.tsx b/apps/easypid/src/app/(app)/federation.tsx similarity index 77% rename from apps/easypid/src/app/(app)/issuer.tsx rename to apps/easypid/src/app/(app)/federation.tsx index 0d3916db..662c4b68 100644 --- a/apps/easypid/src/app/(app)/issuer.tsx +++ b/apps/easypid/src/app/(app)/federation.tsx @@ -1,4 +1,4 @@ -import { FunkeIssuerDetailScreen } from '@easypid/features/wallet/FunkeIssuerDetailScreen' +import { FunkeFederationDetailScreen } from '@easypid/features/wallet/FunkeFederationDetailScreen' import { useLocalSearchParams } from 'expo-router' export default function Screen() { @@ -7,7 +7,7 @@ export default function Screen() { const trustedEntityIdsArray = Array.isArray(trustedEntityIds) ? trustedEntityIds : trustedEntityIds?.split(',') ?? [] return ( - ), }, diff --git a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx index 15b071a9..db93ffc3 100644 --- a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx +++ b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx @@ -26,7 +26,7 @@ interface VerifyPartySlideProps { backgroundColor?: string lastInteractionDate?: string onContinue?: () => Promise - trustedEntityIds?: string[] + verifiedEntityIds?: Record } export const VerifyPartySlide = ({ @@ -37,13 +37,17 @@ export const VerifyPartySlide = ({ backgroundColor, lastInteractionDate, onContinue, - trustedEntityIds, + verifiedEntityIds, }: VerifyPartySlideProps) => { const router = useRouter() const { onNext, onCancel } = useWizard() const { withHaptics } = useHaptics() const [isLoading, setIsLoading] = useState(false) + const trustedEntityIds = Object.entries(verifiedEntityIds ?? {}) + .filter(([_, isVerified]) => isVerified) + .map(([entityId]) => entityId) + const handleContinue = async () => { setIsLoading(true) if (onContinue) { diff --git a/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx index 615a6a33..cb8a79a2 100644 --- a/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx @@ -146,7 +146,7 @@ export function FunkeOpenIdPresentationNotificationScreen() { entityId={credentialsForRequest?.verifier.entityId as string} verifierName={credentialsForRequest?.verifier.name} logo={credentialsForRequest?.verifier.logo} - trustedEntityIds={Object.keys(credentialsForRequest?.verifier.verifiedEntityIds ?? [])} + verifiedEntityIds={credentialsForRequest?.verifier.verifiedEntityIds} lastInteractionDate={lastInteractionDate} onComplete={() => pushToWallet('replace')} /> diff --git a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx index 2b360462..f2bd583d 100644 --- a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx @@ -13,7 +13,7 @@ interface FunkePresentationNotificationScreenProps { verifierName?: string logo?: DisplayImage lastInteractionDate?: string - trustedEntityIds?: string[] + verifiedEntityIds?: Record submission?: FormattedSubmission usePin: boolean isAccepting: boolean @@ -33,7 +33,7 @@ export function FunkePresentationNotificationScreen({ isAccepting, submission, onComplete, - trustedEntityIds, + verifiedEntityIds, }: FunkePresentationNotificationScreenProps) { return ( ), }, diff --git a/apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx similarity index 95% rename from apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx rename to apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx index 6381ff97..7b6ba629 100644 --- a/apps/easypid/src/features/wallet/FunkeIssuerDetailScreen.tsx +++ b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx @@ -17,14 +17,19 @@ import { TextBackButton, useScrollViewPosition } from 'packages/app/src' import { useRef } from 'react' import { useSafeAreaInsets } from 'react-native-safe-area-context' -interface FunkeIssuerDetailScreenProps { +interface FunkeFederationDetailScreenProps { name: string logo?: string entityId?: string trustedEntityIds?: string[] } -export function FunkeIssuerDetailScreen({ name, logo, entityId, trustedEntityIds = [] }: FunkeIssuerDetailScreenProps) { +export function FunkeFederationDetailScreen({ + name, + logo, + entityId, + trustedEntityIds = [], +}: FunkeFederationDetailScreenProps) { const { trustedEntities } = useTrustedEntities() const { handleScroll, isScrolledByOffset, scrollEventThrottle } = useScrollViewPosition() From 1111d922db534daeb24ce695db0fc220040b94b9 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 16:13:44 +0100 Subject: [PATCH 03/10] chore: type --- .../src/features/share/FunkeMdocOfflineSharingScreen.tsx | 1 + packages/agent/src/invitation/handler.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx b/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx index 002b52ff..0c7a75d7 100644 --- a/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx +++ b/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx @@ -122,6 +122,7 @@ export function FunkeMdocOfflineSharingScreen({ hostName: undefined, logo: undefined, name: 'Unknown party', + verifiedEntityIds: undefined, }, }, status diff --git a/packages/agent/src/invitation/handler.ts b/packages/agent/src/invitation/handler.ts index 80de4671..c8c25861 100644 --- a/packages/agent/src/invitation/handler.ts +++ b/packages/agent/src/invitation/handler.ts @@ -498,7 +498,7 @@ export const getCredentialsForProofRequest = async ({ resolved.authorizationRequest.authorizationRequestPayload.client_metadata } - let verifiedEntityIds: Record = {} + let verifiedEntityIds: Record | undefined = undefined if (entityId) { const resolvedChains = await agent.modules.openId4VcHolder.resolveOpenIdFederationChains({ entityId: entityId ?? '', From 41cd2c3cee8f12f4f1d7037953e273284e240791 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 16:49:39 +0100 Subject: [PATCH 04/10] feat: federation details --- .../receive/slides/VerifyPartySlide.tsx | 10 ++--- .../wallet/FunkeFederationDetailScreen.tsx | 44 ++++++------------- packages/ui/src/components/InfoButton.tsx | 6 ++- 3 files changed, 23 insertions(+), 37 deletions(-) diff --git a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx index db93ffc3..aa4033e9 100644 --- a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx +++ b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx @@ -59,7 +59,7 @@ export const VerifyPartySlide = ({ const onPressVerifiedIssuer = withHaptics(() => { router.push( - `/issuer?name=${name}&logo=${logo?.url}&entityId=${entityId}&trustedEntityIds=${trustedEntityIds?.join(',') ?? ''}` + `/federation?name=${name}&logo=${logo?.url}&entityId=${entityId}&trustedEntityIds=${trustedEntityIds?.join(',') ?? ''}` ) }) @@ -101,15 +101,15 @@ export const VerifyPartySlide = ({ {trustedEntityIds && trustedEntityIds.length > 0 ? ( ) : ( diff --git a/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx index 7b6ba629..c81e39cf 100644 --- a/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx +++ b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx @@ -14,6 +14,7 @@ import { } from '@package/ui' import { useTrustedEntities } from 'packages/agent/src' import { TextBackButton, useScrollViewPosition } from 'packages/app/src' +import React from 'react' import { useRef } from 'react' import { useSafeAreaInsets } from 'react-native-safe-area-context' @@ -36,6 +37,8 @@ export function FunkeFederationDetailScreen({ const { bottom } = useSafeAreaInsets() const scrollViewRef = useRef(null) + const filteredTrustedEntities = trustedEntities.filter((entity) => trustedEntityIds.includes(entity.entity_id)) + return ( } /> - + {logo ? ( @@ -63,36 +66,23 @@ export function FunkeFederationDetailScreen({ )} - - {name} - - Website - - + {name} Trusted by - A list of organizations and whether they have approved{' '} - {name}. + {filteredTrustedEntities.length > 0 ? ( + <>A list of organizations and whether they have approved {name}. + ) : ( + <>There are no organizations that have approved {name}. + )} - {trustedEntities.map((entity) => { - const isTrusted = trustedEntityIds.includes(entity.entity_id) - + {filteredTrustedEntities.map((entity) => { return ( - + {entity.logo_uri && ( @@ -100,15 +90,7 @@ export function FunkeFederationDetailScreen({ )} {entity.organization_name} - - ) : ( - - ) - } - /> + } /> ) diff --git a/packages/ui/src/components/InfoButton.tsx b/packages/ui/src/components/InfoButton.tsx index 08a6c8da..8c4ed4fc 100644 --- a/packages/ui/src/components/InfoButton.tsx +++ b/packages/ui/src/components/InfoButton.tsx @@ -21,6 +21,10 @@ const infoButtonVariants = { icon: , accent: '$danger-500', }, + info: { + icon: , + accent: '$grey-500', + }, // States expired: { @@ -95,7 +99,7 @@ export function InfoButton({ )} - + {title} From 9579682acdd7ead2f30e2c2e68955a52074ef8cf Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 17:19:42 +0100 Subject: [PATCH 05/10] feat: done --- apps/easypid/src/app/(app)/federation.tsx | 7 +- .../receive/slides/VerifyPartySlide.tsx | 16 ++--- ...keOpenIdPresentationNotificationScreen.tsx | 2 +- .../FunkePresentationNotificationScreen.tsx | 7 +- .../wallet/FunkeFederationDetailScreen.tsx | 17 ++--- packages/agent/src/invitation/handler.ts | 24 ++++--- packages/agent/src/invitation/index.ts | 2 + .../agent/src/invitation/trustedEntities.ts | 16 +++++ .../agent/src/providers/AgentProvider.tsx | 5 +- .../src/providers/TrustedEntitiesProvider.tsx | 69 ------------------- 10 files changed, 53 insertions(+), 112 deletions(-) create mode 100644 packages/agent/src/invitation/trustedEntities.ts delete mode 100644 packages/agent/src/providers/TrustedEntitiesProvider.tsx diff --git a/apps/easypid/src/app/(app)/federation.tsx b/apps/easypid/src/app/(app)/federation.tsx index 662c4b68..0f59457d 100644 --- a/apps/easypid/src/app/(app)/federation.tsx +++ b/apps/easypid/src/app/(app)/federation.tsx @@ -1,15 +1,16 @@ import { FunkeFederationDetailScreen } from '@easypid/features/wallet/FunkeFederationDetailScreen' import { useLocalSearchParams } from 'expo-router' +import type { TrustedEntity } from 'packages/agent/src/invitation/handler' export default function Screen() { - const { entityId, trustedEntityIds, name, logo } = useLocalSearchParams() + const { entityId, trustedEntities, name, logo } = useLocalSearchParams() - const trustedEntityIdsArray = Array.isArray(trustedEntityIds) ? trustedEntityIds : trustedEntityIds?.split(',') ?? [] + const trustedEntitiesArray = JSON.parse(decodeURIComponent(trustedEntities as string)) as Array return ( diff --git a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx index aa4033e9..94ac401b 100644 --- a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx +++ b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx @@ -1,4 +1,4 @@ -import type { DisplayImage } from '@package/agent' +import type { DisplayImage, TrustedEntity } from '@package/agent' import { Circle, @@ -26,7 +26,7 @@ interface VerifyPartySlideProps { backgroundColor?: string lastInteractionDate?: string onContinue?: () => Promise - verifiedEntityIds?: Record + verifiedEntities?: Array } export const VerifyPartySlide = ({ @@ -37,17 +37,13 @@ export const VerifyPartySlide = ({ backgroundColor, lastInteractionDate, onContinue, - verifiedEntityIds, + verifiedEntities, }: VerifyPartySlideProps) => { const router = useRouter() const { onNext, onCancel } = useWizard() const { withHaptics } = useHaptics() const [isLoading, setIsLoading] = useState(false) - const trustedEntityIds = Object.entries(verifiedEntityIds ?? {}) - .filter(([_, isVerified]) => isVerified) - .map(([entityId]) => entityId) - const handleContinue = async () => { setIsLoading(true) if (onContinue) { @@ -59,7 +55,7 @@ export const VerifyPartySlide = ({ const onPressVerifiedIssuer = withHaptics(() => { router.push( - `/federation?name=${name}&logo=${logo?.url}&entityId=${entityId}&trustedEntityIds=${trustedEntityIds?.join(',') ?? ''}` + `/federation?name=${encodeURIComponent(name ?? '')}&logo=${encodeURIComponent(logo?.url ?? '')}&entityId=${encodeURIComponent(entityId)}&trustedEntities=${encodeURIComponent(JSON.stringify(verifiedEntities ?? []))}` ) }) @@ -99,11 +95,11 @@ export const VerifyPartySlide = ({ - {trustedEntityIds && trustedEntityIds.length > 0 ? ( + {verifiedEntities && verifiedEntities.length > 0 ? ( ) : ( diff --git a/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx index cb8a79a2..dff76435 100644 --- a/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx @@ -146,7 +146,7 @@ export function FunkeOpenIdPresentationNotificationScreen() { entityId={credentialsForRequest?.verifier.entityId as string} verifierName={credentialsForRequest?.verifier.name} logo={credentialsForRequest?.verifier.logo} - verifiedEntityIds={credentialsForRequest?.verifier.verifiedEntityIds} + verifiedEntities={credentialsForRequest?.verifier.verifiedEntities} lastInteractionDate={lastInteractionDate} onComplete={() => pushToWallet('replace')} /> diff --git a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx index f2bd583d..335e8b3c 100644 --- a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx @@ -1,6 +1,7 @@ import type { DisplayImage, FormattedSubmission } from '@package/agent' import { type SlideStep, SlideWizard } from '@package/app' +import type { TrustedEntity } from 'packages/agent/src/invitation/handler' import { LoadingRequestSlide } from '../receive/slides/LoadingRequestSlide' import { VerifyPartySlide } from '../receive/slides/VerifyPartySlide' import type { PresentationRequestResult } from './components/utils' @@ -13,7 +14,7 @@ interface FunkePresentationNotificationScreenProps { verifierName?: string logo?: DisplayImage lastInteractionDate?: string - verifiedEntityIds?: Record + verifiedEntities?: Array submission?: FormattedSubmission usePin: boolean isAccepting: boolean @@ -33,7 +34,7 @@ export function FunkePresentationNotificationScreen({ isAccepting, submission, onComplete, - verifiedEntityIds, + verifiedEntities, }: FunkePresentationNotificationScreenProps) { return ( ), }, diff --git a/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx index c81e39cf..20d8c7db 100644 --- a/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx +++ b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx @@ -1,3 +1,4 @@ +import type { TrustedEntity } from '@package/agent' import { Circle, FlexPage, @@ -12,33 +13,27 @@ import { XStack, YStack, } from '@package/ui' -import { useTrustedEntities } from 'packages/agent/src' import { TextBackButton, useScrollViewPosition } from 'packages/app/src' -import React from 'react' -import { useRef } from 'react' +import React, { useRef } from 'react' import { useSafeAreaInsets } from 'react-native-safe-area-context' interface FunkeFederationDetailScreenProps { name: string logo?: string entityId?: string - trustedEntityIds?: string[] + trustedEntities?: Array } export function FunkeFederationDetailScreen({ name, logo, entityId, - trustedEntityIds = [], + trustedEntities = [], }: FunkeFederationDetailScreenProps) { - const { trustedEntities } = useTrustedEntities() - const { handleScroll, isScrolledByOffset, scrollEventThrottle } = useScrollViewPosition() const { bottom } = useSafeAreaInsets() const scrollViewRef = useRef(null) - const filteredTrustedEntities = trustedEntities.filter((entity) => trustedEntityIds.includes(entity.entity_id)) - return ( Trusted by - {filteredTrustedEntities.length > 0 ? ( + {trustedEntities.length > 0 ? ( <>A list of organizations and whether they have approved {name}. ) : ( <>There are no organizations that have approved {name}. @@ -80,7 +75,7 @@ export function FunkeFederationDetailScreen({ - {filteredTrustedEntities.map((entity) => { + {trustedEntities.map((entity) => { return ( {entity.logo_uri && ( diff --git a/packages/agent/src/invitation/handler.ts b/packages/agent/src/invitation/handler.ts index c8c25861..035c0f55 100644 --- a/packages/agent/src/invitation/handler.ts +++ b/packages/agent/src/invitation/handler.ts @@ -54,9 +54,10 @@ import { import { setBatchCredentialMetadata } from '../openid4vc/batchMetadata' import { getCredentialBindingResolver } from '../openid4vc/credentialBindingResolver' import { extractOpenId4VcCredentialMetadata, setOpenId4VcCredentialMetadata } from '../openid4vc/displayMetadata' -import { TRUSTED_ENTITIES } from '../providers/TrustedEntitiesProvider' import { BiometricAuthenticationError } from './error' import { fetchInvitationDataUrl } from './fetchInvitation' +import { TRUSTED_ENTITIES } from './trustedEntities' +import type { TrustedEntity } from './trustedEntities' export async function resolveOpenId4VciOffer({ agent, @@ -498,20 +499,21 @@ export const getCredentialsForProofRequest = async ({ resolved.authorizationRequest.authorizationRequestPayload.client_metadata } - let verifiedEntityIds: Record | undefined = undefined + let verifiedEntities: Array = [] if (entityId) { const resolvedChains = await agent.modules.openId4VcHolder.resolveOpenIdFederationChains({ - entityId: entityId ?? '', + entityId: entityId, trustAnchorEntityIds: TRUSTED_ENTITIES, }) - // Return which resolved chains are actually resolved - verifiedEntityIds = Object.fromEntries( - resolvedChains.map((chain) => [ - chain.trustAnchorEntityConfiguration.sub, - TRUSTED_ENTITIES.includes(chain.trustAnchorEntityConfiguration.sub), - ]) - ) + verifiedEntities = resolvedChains + .map((chain) => ({ + entity_id: chain.trustAnchorEntityConfiguration.sub, + organization_name: + chain.trustAnchorEntityConfiguration.metadata?.federation_entity?.organization_name ?? 'Unknown entity', + logo_uri: chain.trustAnchorEntityConfiguration.metadata?.federation_entity?.logo_uri, + })) + .filter((entity, index, self) => self.findIndex((e) => e.entity_id === entity.entity_id) === index) } let formattedSubmission: FormattedSubmission @@ -549,7 +551,7 @@ export const getCredentialsForProofRequest = async ({ } : undefined, name: clientMetadata?.client_name, - verifiedEntityIds, + verifiedEntities, }, formattedSubmission, } as const diff --git a/packages/agent/src/invitation/index.ts b/packages/agent/src/invitation/index.ts index 4908fe99..c7b9f8f9 100644 --- a/packages/agent/src/invitation/index.ts +++ b/packages/agent/src/invitation/index.ts @@ -40,3 +40,5 @@ export { acquireAuthorizationCodeUsingPresentation, } from './handler' export * from './error' + +export type { TrustedEntity } from './trustedEntities' diff --git a/packages/agent/src/invitation/trustedEntities.ts b/packages/agent/src/invitation/trustedEntities.ts new file mode 100644 index 00000000..0a8e3840 --- /dev/null +++ b/packages/agent/src/invitation/trustedEntities.ts @@ -0,0 +1,16 @@ +const BASE_URL = 'https://macbook-pro-van-tom.curl-perch.ts.net/siop' + +export const TRUSTED_ENTITIES = [ + `${BASE_URL}/0193687b-0c27-7b82-a686-ff857dc6bbb3`, + `${BASE_URL}/0193687f-20d8-720a-9139-ed939ba510fa`, + // To be added + `${BASE_URL}/019368ed-3787-7669-b7f4-8c012238e90d`, + `${BASE_URL}/01936907-56a3-7007-a61f-44bff8b5d175`, + `${BASE_URL}/01936903-8879-733f-8eaf-6f2fa862099c`, +] satisfies [string, ...string[]] + +export type TrustedEntity = { + entity_id: string + organization_name: string + logo_uri?: string +} diff --git a/packages/agent/src/providers/AgentProvider.tsx b/packages/agent/src/providers/AgentProvider.tsx index 778767c3..c79c1ab7 100644 --- a/packages/agent/src/providers/AgentProvider.tsx +++ b/packages/agent/src/providers/AgentProvider.tsx @@ -6,7 +6,6 @@ import NativeAgentProvider from '@credo-ts/react-hooks' import { ExchangeRecordDisplayMetadataProvider } from './ExchangeRecordDisplayMetadataProvider' import { MdocRecordProvider } from './MdocProvider' import { SdJwtVcRecordProvider } from './SdJwtVcsProvider' -import { TrustedEntitiesProvider } from './TrustedEntitiesProvider' import { W3cCredentialRecordProvider } from './W3cCredentialsProvider' export interface AgentProviderProps { @@ -18,9 +17,7 @@ export const AgentProvider = ({ agent, children }: PropsWithChildren - - {children} - + {children} diff --git a/packages/agent/src/providers/TrustedEntitiesProvider.tsx b/packages/agent/src/providers/TrustedEntitiesProvider.tsx deleted file mode 100644 index abd20c94..00000000 --- a/packages/agent/src/providers/TrustedEntitiesProvider.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { OpenId4VcSiopHolderService } from '@credo-ts/openid4vc' -import type { FullAppAgent } from 'packages/agent/src' -import { type ReactNode, createContext, useContext, useEffect, useState } from 'react' - -export const TRUSTED_ENTITIES = [ - 'https://funke.animo.id/siop/0193687b-0c27-7b82-a686-ff857dc6bbb3', - 'https://funke.animo.id/siop/0193687f-20d8-720a-9139-ed939ba510fa', -] satisfies [string, ...string[]] - -type TrustedEntity = { - entity_id: string - organization_name: string - logo_uri?: string -} - -type TrustedEntitiesContextType = { - trustedEntities: TrustedEntity[] - isLoading: boolean -} - -const TrustedEntitiesContext = createContext(undefined) - -export function TrustedEntitiesProvider({ agent, children }: { agent: FullAppAgent; children: ReactNode }) { - const [isLoading, setIsLoading] = useState(true) - const [trustedEntities, setTrustedEntities] = useState([]) - - useEffect(() => { - async function fetchTrustedEntities() { - try { - const openId4VcSiopHolderService = agent.dependencyManager.resolve(OpenId4VcSiopHolderService) - - // Fetch configurations for all trusted entities - const entityPromises = TRUSTED_ENTITIES.map((entityId) => - openId4VcSiopHolderService.fetchOpenIdFederationEntityConfiguration(agent.context, { - entityId, - }) - ) - const entitiesResults = await Promise.all(entityPromises) - const entities = entitiesResults.map((result) => { - return { - entity_id: result.iss, - organization_name: result.metadata?.federation_entity?.organization_name ?? 'Unknown entity', - logo_uri: result.metadata?.federation_entity?.logo_uri, - } - }) - - setTrustedEntities(entities) - } catch (error) { - console.error('Failed to fetch trusted entities:', error) - } finally { - setIsLoading(false) - } - } - - fetchTrustedEntities() - }, [agent]) - - return ( - {children} - ) -} - -export function useTrustedEntities() { - const context = useContext(TrustedEntitiesContext) - if (context === undefined) { - throw new Error('useTrustedEntities must be used within a TrustedEntitiesProvider') - } - return context -} From f197a17e468291d7a4be13370d22a554c903ebce Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 17:22:07 +0100 Subject: [PATCH 06/10] chore: rename --- .../src/features/receive/slides/VerifyPartySlide.tsx | 10 +++++----- .../FunkeOpenIdPresentationNotificationScreen.tsx | 2 +- .../share/FunkePresentationNotificationScreen.tsx | 9 ++++----- packages/agent/src/invitation/handler.ts | 6 +++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx index 94ac401b..538d8096 100644 --- a/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx +++ b/apps/easypid/src/features/receive/slides/VerifyPartySlide.tsx @@ -26,7 +26,7 @@ interface VerifyPartySlideProps { backgroundColor?: string lastInteractionDate?: string onContinue?: () => Promise - verifiedEntities?: Array + trustedEntities?: Array } export const VerifyPartySlide = ({ @@ -37,7 +37,7 @@ export const VerifyPartySlide = ({ backgroundColor, lastInteractionDate, onContinue, - verifiedEntities, + trustedEntities, }: VerifyPartySlideProps) => { const router = useRouter() const { onNext, onCancel } = useWizard() @@ -55,7 +55,7 @@ export const VerifyPartySlide = ({ const onPressVerifiedIssuer = withHaptics(() => { router.push( - `/federation?name=${encodeURIComponent(name ?? '')}&logo=${encodeURIComponent(logo?.url ?? '')}&entityId=${encodeURIComponent(entityId)}&trustedEntities=${encodeURIComponent(JSON.stringify(verifiedEntities ?? []))}` + `/federation?name=${encodeURIComponent(name ?? '')}&logo=${encodeURIComponent(logo?.url ?? '')}&entityId=${encodeURIComponent(entityId)}&trustedEntities=${encodeURIComponent(JSON.stringify(trustedEntities ?? []))}` ) }) @@ -95,11 +95,11 @@ export const VerifyPartySlide = ({ - {verifiedEntities && verifiedEntities.length > 0 ? ( + {trustedEntities && trustedEntities.length > 0 ? ( ) : ( diff --git a/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx index dff76435..fe7f26bc 100644 --- a/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkeOpenIdPresentationNotificationScreen.tsx @@ -146,7 +146,7 @@ export function FunkeOpenIdPresentationNotificationScreen() { entityId={credentialsForRequest?.verifier.entityId as string} verifierName={credentialsForRequest?.verifier.name} logo={credentialsForRequest?.verifier.logo} - verifiedEntities={credentialsForRequest?.verifier.verifiedEntities} + trustedEntities={credentialsForRequest?.verifier.trustedEntities} lastInteractionDate={lastInteractionDate} onComplete={() => pushToWallet('replace')} /> diff --git a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx index 335e8b3c..eeea2449 100644 --- a/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx +++ b/apps/easypid/src/features/share/FunkePresentationNotificationScreen.tsx @@ -1,7 +1,6 @@ -import type { DisplayImage, FormattedSubmission } from '@package/agent' +import type { DisplayImage, FormattedSubmission, TrustedEntity } from '@package/agent' import { type SlideStep, SlideWizard } from '@package/app' -import type { TrustedEntity } from 'packages/agent/src/invitation/handler' import { LoadingRequestSlide } from '../receive/slides/LoadingRequestSlide' import { VerifyPartySlide } from '../receive/slides/VerifyPartySlide' import type { PresentationRequestResult } from './components/utils' @@ -14,7 +13,7 @@ interface FunkePresentationNotificationScreenProps { verifierName?: string logo?: DisplayImage lastInteractionDate?: string - verifiedEntities?: Array + trustedEntities?: Array submission?: FormattedSubmission usePin: boolean isAccepting: boolean @@ -34,7 +33,7 @@ export function FunkePresentationNotificationScreen({ isAccepting, submission, onComplete, - verifiedEntities, + trustedEntities, }: FunkePresentationNotificationScreenProps) { return ( ), }, diff --git a/packages/agent/src/invitation/handler.ts b/packages/agent/src/invitation/handler.ts index 035c0f55..c74c7755 100644 --- a/packages/agent/src/invitation/handler.ts +++ b/packages/agent/src/invitation/handler.ts @@ -499,14 +499,14 @@ export const getCredentialsForProofRequest = async ({ resolved.authorizationRequest.authorizationRequestPayload.client_metadata } - let verifiedEntities: Array = [] + let trustedEntities: Array = [] if (entityId) { const resolvedChains = await agent.modules.openId4VcHolder.resolveOpenIdFederationChains({ entityId: entityId, trustAnchorEntityIds: TRUSTED_ENTITIES, }) - verifiedEntities = resolvedChains + trustedEntities = resolvedChains .map((chain) => ({ entity_id: chain.trustAnchorEntityConfiguration.sub, organization_name: @@ -551,7 +551,7 @@ export const getCredentialsForProofRequest = async ({ } : undefined, name: clientMetadata?.client_name, - verifiedEntities, + trustedEntities, }, formattedSubmission, } as const From f0ffc50fe93580351a859ff974723c07cf02b7fa Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 17:23:36 +0100 Subject: [PATCH 07/10] feat: working --- packages/agent/src/invitation/trustedEntities.ts | 3 +-- packages/agent/src/providers/index.ts | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/agent/src/invitation/trustedEntities.ts b/packages/agent/src/invitation/trustedEntities.ts index 0a8e3840..0cd3b226 100644 --- a/packages/agent/src/invitation/trustedEntities.ts +++ b/packages/agent/src/invitation/trustedEntities.ts @@ -1,9 +1,8 @@ -const BASE_URL = 'https://macbook-pro-van-tom.curl-perch.ts.net/siop' +const BASE_URL = 'https://funke.animo.id/siop' export const TRUSTED_ENTITIES = [ `${BASE_URL}/0193687b-0c27-7b82-a686-ff857dc6bbb3`, `${BASE_URL}/0193687f-20d8-720a-9139-ed939ba510fa`, - // To be added `${BASE_URL}/019368ed-3787-7669-b7f4-8c012238e90d`, `${BASE_URL}/01936907-56a3-7007-a61f-44bff8b5d175`, `${BASE_URL}/01936903-8879-733f-8eaf-6f2fa862099c`, diff --git a/packages/agent/src/providers/index.ts b/packages/agent/src/providers/index.ts index fcfa0e24..28c3804e 100644 --- a/packages/agent/src/providers/index.ts +++ b/packages/agent/src/providers/index.ts @@ -7,4 +7,3 @@ export { } from './W3cCredentialsProvider' export { useSdJwtVcRecordById, useSdJwtVcRecords, SdJwtVcRecord, SdJwtVc } from './SdJwtVcsProvider' export { useMdocRecordById, useMdocRecords, Mdoc, MdocRecord } from './MdocProvider' -export { useTrustedEntities } from './TrustedEntitiesProvider' From bc0c341522c8a92ce69c20cc4ea317adb34a8fb4 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 17:28:51 +0100 Subject: [PATCH 08/10] feat: final fixes --- apps/easypid/src/app/(app)/federation.tsx | 2 +- .../src/features/wallet/FunkeFederationDetailScreen.tsx | 6 ++++-- packages/agent/src/invitation/trustedEntities.ts | 3 ++- packages/ui/src/components/InfoButton.tsx | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/easypid/src/app/(app)/federation.tsx b/apps/easypid/src/app/(app)/federation.tsx index 0f59457d..70a8a0db 100644 --- a/apps/easypid/src/app/(app)/federation.tsx +++ b/apps/easypid/src/app/(app)/federation.tsx @@ -1,6 +1,6 @@ import { FunkeFederationDetailScreen } from '@easypid/features/wallet/FunkeFederationDetailScreen' +import type { TrustedEntity } from '@package/agent' import { useLocalSearchParams } from 'expo-router' -import type { TrustedEntity } from 'packages/agent/src/invitation/handler' export default function Screen() { const { entityId, trustedEntities, name, logo } = useLocalSearchParams() diff --git a/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx index 20d8c7db..60396b4d 100644 --- a/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx +++ b/apps/easypid/src/features/wallet/FunkeFederationDetailScreen.tsx @@ -83,8 +83,10 @@ export function FunkeFederationDetailScreen({ )} - - {entity.organization_name} + + + {entity.organization_name} + } /> diff --git a/packages/agent/src/invitation/trustedEntities.ts b/packages/agent/src/invitation/trustedEntities.ts index 0cd3b226..0a8e3840 100644 --- a/packages/agent/src/invitation/trustedEntities.ts +++ b/packages/agent/src/invitation/trustedEntities.ts @@ -1,8 +1,9 @@ -const BASE_URL = 'https://funke.animo.id/siop' +const BASE_URL = 'https://macbook-pro-van-tom.curl-perch.ts.net/siop' export const TRUSTED_ENTITIES = [ `${BASE_URL}/0193687b-0c27-7b82-a686-ff857dc6bbb3`, `${BASE_URL}/0193687f-20d8-720a-9139-ed939ba510fa`, + // To be added `${BASE_URL}/019368ed-3787-7669-b7f4-8c012238e90d`, `${BASE_URL}/01936907-56a3-7007-a61f-44bff8b5d175`, `${BASE_URL}/01936903-8879-733f-8eaf-6f2fa862099c`, diff --git a/packages/ui/src/components/InfoButton.tsx b/packages/ui/src/components/InfoButton.tsx index 8c4ed4fc..caa9932d 100644 --- a/packages/ui/src/components/InfoButton.tsx +++ b/packages/ui/src/components/InfoButton.tsx @@ -99,7 +99,7 @@ export function InfoButton({ )} - + {title} From abe86d11f92ad718feb39074db84577054f3d87d Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 17:30:10 +0100 Subject: [PATCH 09/10] chore: back to funke --- packages/agent/src/invitation/trustedEntities.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/agent/src/invitation/trustedEntities.ts b/packages/agent/src/invitation/trustedEntities.ts index 0a8e3840..0cd3b226 100644 --- a/packages/agent/src/invitation/trustedEntities.ts +++ b/packages/agent/src/invitation/trustedEntities.ts @@ -1,9 +1,8 @@ -const BASE_URL = 'https://macbook-pro-van-tom.curl-perch.ts.net/siop' +const BASE_URL = 'https://funke.animo.id/siop' export const TRUSTED_ENTITIES = [ `${BASE_URL}/0193687b-0c27-7b82-a686-ff857dc6bbb3`, `${BASE_URL}/0193687f-20d8-720a-9139-ed939ba510fa`, - // To be added `${BASE_URL}/019368ed-3787-7669-b7f4-8c012238e90d`, `${BASE_URL}/01936907-56a3-7007-a61f-44bff8b5d175`, `${BASE_URL}/01936903-8879-733f-8eaf-6f2fa862099c`, From 8e4d3bb3614d05fe026fe3b00b476afdda0fc733 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 26 Nov 2024 17:56:39 +0100 Subject: [PATCH 10/10] fix: ci --- .../src/features/share/FunkeMdocOfflineSharingScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx b/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx index 0c7a75d7..beef9e42 100644 --- a/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx +++ b/apps/easypid/src/features/share/FunkeMdocOfflineSharingScreen.tsx @@ -122,7 +122,7 @@ export function FunkeMdocOfflineSharingScreen({ hostName: undefined, logo: undefined, name: 'Unknown party', - verifiedEntityIds: undefined, + trustedEntities: [], }, }, status