npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@animo-id/expo-ausweis-sdk

v0.0.1-alpha.14

Published

Expo Module Wrapper around the German eID Ausweis SDK

Downloads

373

Readme


An Expo Module and Expo Config Plugin to automatically set up and configure the Ausweis App SDK for iOS & Android in Expo apps.

Getting Started

Install the plugin and expo-build-properties using the following command. We need expo-build-properties to set the minSdkVersion for Android to at least 26, and enable useLegacyPackaging (see App Bundle in Ausweis SDK documentation).

# yarn
yarn add @animo-id/expo-ausweis-sdk expo-build-properties

# npm
npm install @animo-id/expo-ausweis-sdk expo-build-properties

# npm
pnpm install @animo-id/expo-ausweis-sdk expo-build-properties

Then add the plugin to your Expo app config (app.json, app.config.json or app.config.js) plugins array:

{
  "expo": {
    "plugins": [
      "@animo-id/expo-ausweis-sdk",
      [
        "expo-build-properties",
        {
          "android": {
            "minSdkVersion": 26,
            "useLegacyPackaging": true
          }
        }
      ]
    ]
  }
}

NOTE: the expo top level key is only needed in app.json. In app.config.json, app.config.js and app.config.ts the top level expo key is not present anymore.

And lastly, prebuild the application so the Ausweis SDK and Expo Module wrapper can be added as native dependency (If you aren't making any manual modification to the iOS and Android directories you can add them to the gitignore of your project and generate them on demand):

# yarn
yarn expo prebuild

# npm
npx expo prebuild

That's it, you now have Ausweis App SDK configured for your iOS and Android project.

Usage

You can now import @animo-id/expo-ausweis-sdk in your application and use the methods from the SDK.

You can see the available commands and messages, which are typed in the sendCommand and addMessageListener methods.

import { useEffect, useState } from 'react'
import { initializeSdk, sendCommand, addMessageListener } from '@animo-id/expo-ausweis-sdk'

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

  // Setup listener
  useEffect(
    addMessageListener((message) => {
      console.log('received message', JSON.stringify(message, null, 2))
    }).remove,
    []
  )

  // Initialize SDK
  useEffect(() => {
    initializeSdk()
      .then(() => setIsSdkInitialized(true))
      .catch((e) => {
        console.log('error setting up', e)
      })
  }, [])

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

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

  return null
}

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.

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

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

  const [cardAttachRequested, setCardAttachRequested] = useState(false)
  const [isCardAttached, setIsCardAttached] = useState(false)
  const [progress, setProgress] = useState(0)

  const [requestedAccessRights, setRequestedAccessRights] = useState<string[]>()
  const [onAcceptAccessRights, setOnAcceptAccessRights] = useState<(accept: boolean) => void>()

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

  const runAuthFlow = async () => {
    setMessage(undefined)
    setFlow(
      new AusweisAuthFlow({
        debug: true,
        // Can set to true to allow simulator cards. In this case `onEnterPin` and `onAttachCard` won't be called
        allowSimulatorCard: false,
        onEnterPin: ({ attemptsRemaining }) => {
          // Mock incorrect pin entry
          return attemptsRemaining === 1 ? '123456' : '123123'
        },
        onError: ({ message, reason }) => {
          setFlow(undefined)
          setCardAttachRequested(false)
          setProgress(0)
          setMessage(`${reason}: ${message}`)
        },
        onSuccess: () => {
          setFlow(undefined)
          setProgress(100)
          setCardAttachRequested(false)
          setMessage('Successfully ran auth flow')
        },
        onAttachCard: () => {
          // iOS will already show the NFC scanner modal, but on Android we need
          // use this callback to show the NFC scanner modal.
          setCardAttachRequested(true)
        },
        onCardAttachedChanged: ({ isCardAttached }) => setIsCardAttached(isCardAttached),
        onStatusProgress: ({ progress }) => setProgress(progress),
        onRequestAccessRights: ({ effective }) =>
          new Promise((resolve) => {
            setRequestedAccessRights(effective)
            setOnAcceptAccessRights(() => {
              return (accept: boolean) => {
                resolve({ acceptAccessRights: accept })
                setOnAcceptAccessRights(undefined)
                setRequestedAccessRights(undefined)
              }
            })
          }),
      }).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'} />
      {flow && <Text>Progress: {progress}%</Text>}
      {flow && <Text>Is card attached: {isCardAttached ? 'Yes' : 'No'}</Text>}
      {flow && cardAttachRequested && <Text>Please present your card to the NFC scanner</Text>}
      {flow && requestedAccessRights && (
        <>
          <Text>
            Requested Access Rights:
            {'\n -'}
            {requestedAccessRights.join('\n- ')}
          </Text>
          <Button title="Accept" onPress={() => onAcceptAccessRights?.(true)} />
        </>
      )}
      {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.

License

Expo Ausweis SDK is licensed under the EUPL Version 1.2. The AusweisApp SDK used by this Expo Module is also licensed under EUPL Version 1.2