Skip to content

Commit

Permalink
Merge pull request #13 from animo/card-integration
Browse files Browse the repository at this point in the history
feat: auth flow
  • Loading branch information
TimoGlastra authored Jul 25, 2024
2 parents bc2a18b + c204cc3 commit 6b5ca2c
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 54 deletions.
65 changes: 64 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ You can see the available [commands](https://www.ausweisapp.bund.de/sdk/commands
import { useEffect, useState } from 'react'
import { initializeSdk, sendCommand, addMessageListener } from '@animo-id/expo-ausweis-sdk'


export function App() {
const [isSdkInitialized, setIsSdkInitialized] = useState(false)

Expand Down Expand Up @@ -135,6 +134,70 @@ export function App() {
}
```

### Auth Flow

The package also exports an `AusweisAuthFlow` class that wraps the required logic for a general auth flow. An example of how to use the class can be found below.

To use the `AusweisAuthFlow` you need to configure it with the correct callbacks, and then call the `start()` method with the `tcTokenUrl`.

To cancel the flow, you can call the `cancel()` flow on the `AusweisAuthFlow` instance.

The Ausweis SDK only allows one flow to be active concurrently. It is important that you do not create multiple instances of the `AusweisAuthFlow`, as they will both receive the same events and messages, and will cause conflicts.

Note that this class is optimized for a simple auth flow and thus it may not fit all use cases. For example, the `SET_CAN` and `SET_PUK` commands are not supported (in case of too many failed PIN attempts). Attached simulator cards are also not supported. For more advanced use cases you can use the lower level commands and message listeners methods.

```tsx
import { AusweisAuthFlow } from '@animo-id/expo-ausweis-sdk'
import { useState } from 'react'
import { Button } from 'react-native'
import { StyleSheet, Text, View } from 'react-native'

export default function App() {
const [message, setMessage] = useState<string>()
const [flow, setFlow] = useState<AusweisAuthFlow>()

const cancelFlow = () =>
flow
?.cancel()
.then(() => setFlow(undefined))
.catch((error) => setMessage(`Error canceling flow. ${error.message}`))

const runAuthFlow = async () => {
setMessage(undefined)
setFlow(
new AusweisAuthFlow({
onEnterPin: ({ attemptsRemaining }) => {
// Mock incorrect pin entry
return attemptsRemaining === 1 ? '123456' : '123123'
},
onError: ({ message, reason }) => {
setFlow(undefined)
setMessage(`${reason}: ${message}`)
},
onSuccess: () => {
setFlow(undefined)
setMessage('Successfully ran auth flow')
},
onInsertCard: () => {
// For iOS this will show the NFC scanner modal. on Android we need
// use this callback to show the NFC scanner modal.
console.log('please insert card')
},
}).start({
tcTokenUrl: 'https://test.governikus-eid.de/AusweisAuskunft/WebServiceRequesterServlet',
})
)
}

return (
<View style={[StyleSheet.absoluteFill, { flex: 1, alignContent: 'center', justifyContent: 'center' }]}>
<Button onPress={flow ? cancelFlow : runAuthFlow} title={flow ? 'Cancel' : 'Start Auth Flow'} />
{message && <Text>{message}</Text>}
</View>
)
}
```

## Contributing

Is there something you'd like to fix or add? Great, we love community contributions! To get involved, please follow our [contribution guidelines](./CONTRIBUTING.md).
Expand Down
4 changes: 0 additions & 4 deletions ausweis-example/.expo/prebuild/cached-packages.json

This file was deleted.

63 changes: 37 additions & 26 deletions ausweis-example/app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,49 @@
import { addMessageListener, initializeSdk, sendCommand } from '@animo-id/expo-ausweis-sdk'
import { useEffect, useState } from 'react'
import { AusweisAuthFlow } from '@animo-id/expo-ausweis-sdk'
import { useState } from 'react'
import { Button } from 'react-native'
import { StyleSheet, Text, View } from 'react-native'

export default function App() {
const [isSdkInitialized, setIsSdkInitialized] = useState(false)
const [message, setMessage] = useState<string>()
const [flow, setFlow] = useState<AusweisAuthFlow>()

// Setup listener
useEffect(
addMessageListener((message) => {
console.log('received message', JSON.stringify(message, null, 2))
}).remove,
[]
)
const cancelFlow = () =>
flow
?.cancel()
.then(() => setFlow(undefined))
.catch((error) => setMessage(`Error canceling flow. ${error.message}`))

// Initialize SDK
useEffect(() => {
initializeSdk()
.then(() => setIsSdkInitialized(true))
.catch((e) => {
setIsSdkInitialized(true)
console.log('error setting up', e)
const runAuthFlow = async () => {
setMessage(undefined)
setFlow(
new AusweisAuthFlow({
onEnterPin: ({ attemptsRemaining }) => {
// Mock incorrect pin entry
return attemptsRemaining === 1 ? '123456' : '123123'
},
onError: ({ message, reason }) => {
setFlow(undefined)
setMessage(`${reason}: ${message}`)
},
onSuccess: () => {
setFlow(undefined)
setMessage('Successfully ran auth flow')
},
onInsertCard: () => {
// For iOS this will show the NFC scanner modal. on Android we need
// use this callback to show the NFC scanner modal.
console.log('please insert card')
},
}).start({
tcTokenUrl: 'https://test.governikus-eid.de/AusweisAuskunft/WebServiceRequesterServlet',
})
}, [])

// Send command once SDK is initialized
useEffect(() => {
if (!isSdkInitialized) return

sendCommand({ cmd: 'GET_INFO' })
}, [isSdkInitialized])
)
}

return (
<View style={[StyleSheet.absoluteFill, { flex: 1, alignContent: 'center', justifyContent: 'center' }]}>
<Text>Hello</Text>
<Button onPress={flow ? cancelFlow : runAuthFlow} title={flow ? 'Cancel' : 'Start Auth Flow'} />
{message && <Text>{message}</Text>}
</View>
)
}
6 changes: 4 additions & 2 deletions ausweis-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
"main": "expo-router/entry",
"version": "1.0.0",
"scripts": {
"start": "expo start",
"start": "expo start -c --dev-client",
"android": "expo run:android",
"ios": "expo run:ios"
"ios": "expo run:ios",
"prebuild": "expo prebuild --no-install"
},
"dependencies": {
"@animo-id/expo-ausweis-sdk": "../",
"@react-navigation/native": "^6.0.2",
"expo": "~51.0.17",
"expo-build-properties": "~0.12.3",
"expo-dev-client": "~4.0.20",
"expo-router": "~3.5.17",
"react": "18.2.0",
"react-native": "0.74.2",
Expand Down
92 changes: 92 additions & 0 deletions ausweis-example/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6b5ca2c

Please sign in to comment.