Skip to content

Commit

Permalink
feat(mdoc): proximity flow for Android functionality (#202)
Browse files Browse the repository at this point in the history
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
  • Loading branch information
berendsliedrecht authored Nov 19, 2024
1 parent 6802572 commit 4b5f277
Show file tree
Hide file tree
Showing 15 changed files with 5,732 additions and 1,980 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ yarn-error.log*
.env.development.local
.env.test.local
.env.production.local
.env

# vercel
.vercel
Expand Down
22 changes: 12 additions & 10 deletions apps/easypid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"dependencies": {
"@animo-id/expo-ausweis-sdk": "*",
"@animo-id/expo-mdoc-data-transfer": "0.0.1-alpha.1",
"@animo-id/expo-mdoc-data-transfer": "*",
"@animo-id/expo-secure-environment": "*",
"@credo-ts/core": "*",
"@expo-google-fonts/open-sans": "^0.2.3",
Expand All @@ -24,41 +24,43 @@
"@package/secure-store": "workspace:*",
"@package/ui": "workspace:*",
"@package/utils": "workspace:*",
"@protokoll/mdoc-client": "*",
"@react-native-community/blur": "^4.3.2",
"@react-native-community/netinfo": "11.3.1",
"@react-native-masked-view/masked-view": "0.3.1",
"@react-navigation/native": "^6.1.6",
"babel-plugin-module-resolver": "^4.1.0",
"burnt": "^0.12.2",
"expo": "~51.0.12",
"expo": "~51.0.39",
"expo-barcode-scanner": "~13.0.1",
"expo-blur": "^13.0.2",
"expo-constants": "~16.0.2",
"expo-dev-client": "~4.0.16",
"expo-font": "~12.0.7",
"expo-haptics": "~13.0.1",
"expo-image": "~1.12.11",
"expo-image": "~1.13.0",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
"expo-navigation-bar": "~3.0.6",
"expo-router": "~3.5.16",
"expo-router": "~3.5.24",
"expo-secure-store": "~13.0.1",
"expo-splash-screen": "~0.27.5",
"expo-splash-screen": "~0.27.7",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.6",
"expo-updates": "~0.25.16",
"react": "*",
"react-native": "*",
"react": "18.2.0",
"react-native": "~0.74.5",
"react-native-argon2": "^2.0.1",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.16.2",
"react-native-get-random-values": "~1.11.0",
"react-native-keychain": "^8.2.0",
"react-native-mmkv": "^2.12.2",
"react-native-reanimated": "~3.15.0",
"react-native-safe-area-context": "4.10.1",
"react-native-qrcode-svg": "^6.3.12",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "~3.31.1",
"react-native-svg": "15.2.0"
"react-native-svg": "15.9.0"
},
"devDependencies": {
"@babel/core": "^7.24.4",
Expand Down
1 change: 1 addition & 0 deletions apps/easypid/src/features/proximity/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './mdocProximity'
95 changes: 95 additions & 0 deletions apps/easypid/src/features/proximity/mdocProximity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { mdocDataTransfer } from '@animo-id/expo-mdoc-data-transfer'
import { TypedArrayEncoder } from '@credo-ts/core'
import { getMdocContext } from '@credo-ts/core/build/modules/mdoc/MdocContext'
import type { EasyPIDAppAgent } from '@package/agent'
import {
COSEKey,
DeviceRequest,
DeviceResponse,
MDoc,
type MdocContext,
parseIssuerSigned,
} from '@protokoll/mdoc-client'
import { type Permission, PermissionsAndroid, Platform } from 'react-native'

type ShareDeviceResponseOptions = {
sessionTranscript: Uint8Array
deviceRequest: Uint8Array
agent: EasyPIDAppAgent
}

const PERMISSIONS = [
'android.permission.ACCESS_FINE_LOCATION',
'android.permission.BLUETOOTH_CONNECT',
'android.permission.BLUETOOTH_SCAN',
'android.permission.BLUETOOTH_ADVERTISE',
'android.permission.ACCESS_COARSE_LOCATION',
] as const as Permission[]

export const requestMdocPermissions = async () => {
if (Platform.OS !== 'android') return
await PermissionsAndroid.requestMultiple(PERMISSIONS)
}

export const getMdocQrCode = async () => {
const mdt = mdocDataTransfer.instance()
const qrData = await mdt.startQrEngagement()
return qrData
}

/**
*
* Wait for the device request
*
* Returns the device request and session transcript
*
*/
export const waitForDeviceRequest = async () => {
const mdt = mdocDataTransfer.instance()
return await mdt.waitForDeviceRequest()
}

/**
*
* Naive way to share the device response based on the device request
*
* Optimalisations:
*
* 1. pre-filter the `agent.mdoc.getAll()` based on the `deviceRequest`
* 2. Allow the user to pick which specific mdoc is being used
*
*/
export const shareDeviceResponse = async (options: ShareDeviceResponseOptions) => {
const mdocs = await options.agent.mdoc.getAll()
const issuerSignedDocuments = mdocs.map((mdoc) => {
const docType = mdoc.getTag('DocType') as string
return parseIssuerSigned(TypedArrayEncoder.fromBase64(mdoc.base64Url), docType)
})

const mdoc = new MDoc(issuerSignedDocuments)

const mdocContext = getMdocContext(options.agent.context) as unknown as {
cose: MdocContext['cose']
crypto: MdocContext['crypto']
}

const mdt = mdocDataTransfer.instance()

const mso = mdoc.documents[0].issuerSigned.issuerAuth.decodedPayload
const deviceKeyInfo = mso.deviceKeyInfo
if (!deviceKeyInfo?.deviceKey) {
throw new Error('Device key info is missing')
}

const publicDeviceJwk = COSEKey.import(deviceKeyInfo.deviceKey).toJWK()

const deviceRequest = DeviceRequest.parse(options.deviceRequest)

const deviceResponse = await DeviceResponse.from(mdoc)
.usingSessionTranscriptBytes(new Uint8Array(options.sessionTranscript))
.usingDeviceRequest(deviceRequest)
.authenticateWithSignature(publicDeviceJwk, 'ES256')
.sign(mdocContext)

await mdt.sendDeviceResponse(deviceResponse.encode())
}
1 change: 1 addition & 0 deletions apps/paradym/app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const config = {
},
plugins: [
[
'expo-router',
'expo-font',
{
fonts: [
Expand Down
18 changes: 9 additions & 9 deletions apps/paradym/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,31 @@
"@react-navigation/native": "^6.1.6",
"babel-plugin-module-resolver": "^4.1.0",
"burnt": "^0.12.2",
"expo": "~51.0.12",
"expo": "~51.0.39",
"expo-barcode-scanner": "~13.0.1",
"expo-constants": "~16.0.2",
"expo-dev-client": "~4.0.16",
"expo-font": "~12.0.7",
"expo-haptics": "~13.0.1",
"expo-image": "~1.12.11",
"expo-image": "~1.13.0",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
"expo-navigation-bar": "~3.0.6",
"expo-router": "~3.5.16",
"expo-router": "~3.5.24",
"expo-secure-store": "~13.0.1",
"expo-splash-screen": "~0.27.5",
"expo-splash-screen": "~0.27.7",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.6",
"expo-updates": "~0.25.16",
"react": "*",
"react-native": "*",
"react": "18.2.0",
"react-native": "~0.74.5",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.16.2",
"react-native-get-random-values": "~1.11.0",
"react-native-reanimated": "~3.15.0",
"react-native-safe-area-context": "4.10.1",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "~3.31.1",
"react-native-svg": "15.2.0"
"react-native-svg": "15.9.0"
},
"devDependencies": {
"@babel/core": "^7.24.4",
Expand Down
3 changes: 2 additions & 1 deletion apps/storybook/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"../../node_modules/@expo-google-fonts/open-sans/OpenSans_700Bold.ttf"
]
}
]
],
"expo-router"
]
}
25 changes: 12 additions & 13 deletions apps/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "storybook-app",
"version": "1.0.0",
"main": "App.tsx",
"license": "MIT",
"private": true,
"scripts": {
"start": "expo start -c --dev-client",
"android": "expo run:android",
Expand All @@ -20,34 +20,34 @@
"@react-navigation/native": "^6.1.6",
"@storybook/addons": "^7.6.17",
"burnt": "^0.12.2",
"expo": "~51.0.12",
"expo": "~51.0.39",
"expo-barcode-scanner": "~13.0.1",
"expo-constants": "~16.0.2",
"expo-dev-client": "~4.0.16",
"expo-font": "~12.0.7",
"expo-haptics": "~13.0.1",
"expo-image": "~1.12.11",
"expo-image": "~1.13.0",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
"expo-navigation-bar": "~3.0.6",
"expo-router": "~3.5.16",
"expo-router": "~3.5.24",
"expo-secure-store": "~13.0.1",
"expo-splash-screen": "~0.27.5",
"expo-splash-screen": "~0.27.7",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.6",
"react": "*",
"react": "18.2.0",
"react-device-frameset": "^1.3.4",
"react-native": "*",
"react-native": "~0.74.5",
"react-native-gesture-handler": "~2.16.2",
"react-native-get-random-values": "~1.11.0",
"react-native-reanimated": "~3.15.0",
"react-native-safe-area-context": "4.10.1",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "~3.31.1",
"react-native-svg": "15.2.0"
"react-native-svg": "15.9.0"
},
"devDependencies": {
"@babel/core": "^7.24.4",
"@expo/metro-runtime": "~3.1.3",
"@expo/metro-runtime": "~3.2.3",
"@storybook/addon-actions": "^7.6.18",
"@storybook/addon-controls": "^7.6.18",
"@storybook/addon-essentials": "^7.6.18",
Expand All @@ -69,6 +69,5 @@
"storybook": "^7.6.18",
"tamagui-loader": "1.109.5",
"typescript": "*"
},
"private": true
}
}
18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
},
"pnpm": {
"overrides": {
"@types/react": "~18.2.79",
"react": "18.2.0",
"react-docgen-typescript": "2.2.2",
"typescript": "~5.3.3",
"@unimodules/react-native-adapter": "./noop",
"@unimodules/core": "./noop",
Expand All @@ -40,18 +37,25 @@
"@credo-ts/question-answer": "https://gitpkg.vercel.app/animo/aries-framework-javascript/packages/question-answer?funke",
"@credo-ts/react-native": "https://gitpkg.vercel.app/animo/aries-framework-javascript/packages/react-native?funke",
"@credo-ts/react-hooks": "0.6.1",
"@animo-id/expo-secure-environment": "0.1.0-alpha.5",
"@animo-id/expo-ausweis-sdk": "0.0.1-alpha.14",
"react-native": "0.74.5",
"@animo-id/expo-secure-environment": "0.1.0-alpha.5",
"@animo-id/expo-mdoc-data-transfer": "0.0.3-alpha.6",
"@types/react": "~18.2.79",
"react": "18.3.1",
"react-docgen-typescript": "2.2.2",
"react-native": "~0.75.0",
"react-native-reanimated": "~3.15.5",
"@sphereon/did-auth-siop": "https://gitpkg.vercel.app/animo/OID4VC/packages/siop-oid4vp?funke",
"@sphereon/oid4vc-common": "https://gitpkg.vercel.app/animo/OID4VC/packages/common?funke",
"@sphereon/oid4vci-common": "https://gitpkg.vercel.app/animo/OID4VC/packages/oid4vci-common?funke",
"@sphereon/oid4vci-issuer": "https://gitpkg.vercel.app/animo/OID4VC/packages/issuer?funke",
"@sphereon/oid4vci-client": "https://gitpkg.vercel.app/animo/OID4VC/packages/client?funke",
"@sphereon/jarm": "https://gitpkg.vercel.app/animo/OID4VC/packages/jarm?funke"
"@sphereon/jarm": "https://gitpkg.vercel.app/animo/OID4VC/packages/jarm?funke",
"@protokoll/mdoc-client": "0.2.36"
},
"patchedDependencies": {
"@hyperledger/indy-vdr-react-native@0.2.2": "patches/@hyperledger__indy-vdr-react-native@0.2.2.patch"
"@hyperledger/indy-vdr-react-native@0.2.2": "patches/@hyperledger__indy-vdr-react-native@0.2.2.patch",
"@protokoll/mdoc-client": "patches/@protokoll__mdoc-client.patch"
}
}
}
8 changes: 4 additions & 4 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
"expo-linking": "~6.3.1",
"expo-modules-autolinking": "~1.11.0",
"expo-navigation-bar": "~3.0.6",
"expo-router": "~3.5.16",
"expo-router": "~3.5.24",
"fast-text-encoding": "^1.0.6",
"react": "*",
"react-native-safe-area-context": "4.10.1",
"react-native-reanimated": "~3.15.0",
"react": "18.2.0",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"solito": "^3.0.0"
},
"devDependencies": {
Expand Down
11 changes: 1 addition & 10 deletions packages/app/src/provider/Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,7 @@ export function Provider({ children, ...rest }: PropsWithChildren<TamaguiProvide
return (
<TamaguiProvider disableInjectCSS defaultTheme="light" {...rest}>
<PortalProvider shouldAddRootHost>
<ToastProvider
swipeDirection="up"
duration={6000}
native={
[
/* uncomment the next line to do native toasts on mobile. NOTE: it'll require you making a dev build and won't work with Expo Go */
// 'mobile'
]
}
>
<ToastProvider swipeDirection="up" duration={6000} native={['mobile']}>
<QueryClientProvider client={queryClient}>
<GestureHandlerRootView style={{ flex: 1 }}>{children}</GestureHandlerRootView>
</QueryClientProvider>
Expand Down
2 changes: 1 addition & 1 deletion packages/scanner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@react-native-masked-view/masked-view": "0.3.1",
"@types/react": "~18.2.79",
"expo-barcode-scanner": "~13.0.1",
"react-native": "*"
"react-native": "~0.74.5"
},
"peerDependencies": {
"@react-native-masked-view/masked-view": "0.3.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@tamagui/themes": "1.109.5",
"@tamagui/toast": "1.109.5",
"react-native-heroicons": "^4.0.0",
"react-native-reanimated": "~3.15.0",
"react-native-reanimated": "~3.10.1",
"tamagui": "1.109.5"
}
}
Loading

0 comments on commit 4b5f277

Please sign in to comment.