@pass-culture/id-check
v2.11.1
Published
ID Check module can be used to implement identity check in an existing application.
Downloads
25
Keywords
Readme
@pass-culture/id-check
ID Check module can be used to implement identity check in an existing application.
It is build with React Native, and it supports iOS, Android and Web targets.
Table of Contents
Installation
yarn add @pass-culture/id-check
You must install the peer dependencies.
react-native
yarn add react-native-modal
If you have not done it yet, install all the peerDependencies
(see package.json
)
If you want to use the repo instead of the node_module in a project, run:
yarn link "@pass-culture/id-check"
react-native-web
yarn add modal-enhanced-react-native-web react-native-svg-web react-native-web-lottie
Edit your resolve.alias
webpack configuration with:
+ 'react-native-modal$': 'modal-enhanced-react-native-web',
+ 'react-native-svg': 'react-native-svg-web',
+ 'lottie-react-native': 'react-native-web-lottie',
Edit your moduleNameMapper
jest configuration with:
+ 'react-native-modal$': 'modal-enhanced-react-native-web',
+ 'react-native-svg': 'react-native-svg-web',
+ 'lottie-react-native': 'react-native-web-lottie',
API
Those are exports exposed:
| Export name | Type | Description |
| --------------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| IdCheckContextProvider
| React.Component
| The IdCheck context |
| useIdCheckContext
| React.Hook
| Read the whole IdCheck context (can be useful to know the id check state) |
| IdCheckAnalyticsInterface
| Interface
| Interface used to create a custom Id Check analytics client |
| IdCheckErrorMonitoringInterface
| Interface
| Interface used to create a custom error monitoring client |
| routes
| Array<Route>
| Array of all IDCheck routes |
| IdCheckRootStackParamList
| Interface
| Stack params for each screens required by the route. Only for TypeScript to know each Id Check route params |
| initialRouteName
| string
| The home screen name of Id Check |
| linkingConfig
| LinkingOptions
| Linking configuration for React Navigation |
| IdCheckHomePage
| React.Component
| The Id Check Home page including error boundary, auth persistence, auth and security checkpoint |
| cameraOptions
| CameraOptions
| Default options used in react-native-image-picker
when taking pictures |
| imageLibraryOptions
| ImageLibraryOptions
| Default options used in react-native-image-picker
when opening image gallery |
| CampaignTrackerInterface
| Interface
| Interface used for tracking campaign events: startIdCheckTrack
, uploadDocuments
, accountCreated
and email
|
| IdCheckRetentionClient
| Interface
| Interface used to create a retention client, used when retention mode is active |
Required for demonstration purpose by the Native application, we also added those to exports:
| Export name | Type | Description |
| ------------------------ | ------------------ | ----------------------------------------------------- |
| IdCheckErrors
| Enum
| Enum with all Id Check errors |
| IdCheckError
| IdCheckError
| Error object used to throw Id Check custom error |
| withAsyncErrorBoundary
| HoC
| Error boundary higher order component for Id Check |
| Educonnect
| React.Component
| Educonnect page that navigates to educonnect webview |
Usage
You must wrap your React application within an <IdCheckContextProvider />
.
The module can be configured by injecting props into the ID Check context:
| ID Check context props | Type | Required | Default | Description |
| -------------------------- | ----------------------------------------------------------------------------------- | -------- | ---------- | ---------------------------------------------------------------------------------------------- |
| Initialization | | | | |
| initialStep
| Step
| No | id-check
| Initial step (only useful in retention mode) |
| URLs | | | | |
| jouveApiBaseUrl
| string
| Yes | | Base URL used for Id Check API call |
| homePageUrl
| string
| Yes | | Base URL used for success redirection |
| supportEmail
| string
| Yes | | Email address used for support links |
| dsmUrl
| string
| Yes | | URL for DSM links |
| personalDataDocUrl
| string
| Yes | | URL for personal data documentation |
| cguDocUrl
| string
| Yes | | URL for usage right documentation |
| dmsFrenchCitizenshipUrl
| string
| Yes | | URL for DMS french citizen |
| dmsForeignCitizenshipUrl
| string
| Yes | | URL for DMS foreign citizen |
| Features flips | | | | |
| displayDmsRedirection
| boolean
| No | | Display a DMS redirections when active |
| retention
| boolean
| Yes | | Set and switch to retention mode |
| shouldUseEduConnect
| boolean
| Yes | | Enable eduConnect identification method |
| Services | | | | |
| analytics
| IdCheckAnalyticsInterface
| Yes | | Services used for tracking analytics events |
| errorMonitoring
| IdCheckErrorMonitoringInterface
| Yes | | Services used for error monitoring |
| campaignTracker
| CampaignTrackerInterface
| Yes | | Services used for campaign tracking |
| requestLicenceToken
| Promise<{ licence_token: string, expiration_timestamp: number }>
| No | | Fetch request client can be provided to allow user to get a new licence_token
when necessary |
| retentionClient
| IdCheckRetentionClient<RetentionIdDocumentResponse>
| No | | Services used when retention is active |
| eduConnectClient
| EduConnectClient
| No | | Services used when eduConnect identification method is active |
| Events | | | | |
| onAbandon
| ({ pageName, form }: { pageName: string, form: Record<string, unknown> }) => void
| Yes | | Callback used when user abandon the identity check |
| onSuccess
| () => void
| Yes | | Callback used when user successfully end the identity check |
| Camera | | | | |
| imagePickerOptions
| ImagePickerOptions
| No | (cf. API) | Reconfigure react-native-image-picker
options used when taking pictures or opening gallery |
| Utilities | | | | |
| debug
| boolean
| No | false
| Enable verbose
analytics mode, useful for troubleshooting session issues |
Navigation configuration
Since it can work on iOS, Android and Web, we highly recommend to use React Navigation 5 for your application routing.
initialRouteName
The initialRouteName is IdCheckV2
, it can be reconfigured by passing initialRouteName
to the Id Check Context.
React Navigation 5
It is the default navigation.
React Router 5
For demonstration purpose, we can use React Router in the Web Application of Id Check.
This is possible thanks to @pass-culture/react-navigation-to-react-router-adpater
.
The adapter only have support for React Navigation method used by Id Check. We may later extend it's support if we decide to use React Router for the Web version of App Native
Create an ID Check Analytics client
Using IdCheckAnalyticsInterface
, you can create your own analytics client and track ID Check events:
import React from 'react'
import { IdCheckAnalyticsInterface } from '@pass-culture/id-check'
export const idCheckAnalyticsClient: IdCheckAnalyticsInterface = {
cancelSignUp({ pageName }) {},
identityError() {},
idValid() {},
invalidAge() {},
invalidDate() {},
invalidDocument() {},
invalidTwice() {},
processCompleted() {},
wrongSideDocument() {},
externalLink({ href, canOpen }) {},
fileSizeExceeded() {},
permissionsBlocked() {},
// method below only active when `debug` is on
hasValidSession({ valid, accessToken, accessTokenExpiresAt }) {},
startCheckTokens() {},
endCheckTokens() {},
getJouveToken({
appIsAllowedToRenewLicenceToken,
isLocalLicenceToken,
licenceToken,
licenceTokenExpirationTimestamp,
success,
accessToken,
accessTokenExpiresAt,
}) {},
getLicenceToken({ isError, errorCode, licenceToken, licenceTokenExpirationTimestamp }) {},
startDmsTransmission() {},
takeIdCheckPicture() {},
confirmIdCheckPicture() {},
}
Create an ID Check Error Monitoring client
Using IdCheckErrorMonitoringInterface<Scope, MonitoringUser, CaptureContext>
, you can create your own error monitoring client and track ID Check errors:
As an example with @sentry/react-native
:
import * as SentryModule from '@sentry/react-native' // or @sentry/react
import { CaptureContext, User } from '@sentry/types'
import { IdCheckErrorMonitoringInterface } from '@pass-culture/id-check'
export const errorMonitoring: IdCheckErrorMonitoringInterface<
SentryModule.Scope,
User,
CaptureContext
> = {
captureException: SentryModule.captureException,
captureEvent: SentryModule.captureEvent,
captureMessage: SentryModule.captureMessage,
configureScope: SentryModule.configureScope,
init: SentryModule.init,
setUser: SentryModule.setUser,
}
captureException
: will be call within theAsyncErrorBoundary
, which is wrapping every Id Check screens.captureEvent
: when provided, can be used to capture event whendebug
isON
.captureMessage
: when provided, can be used to capture message whendebug
isON
.configureScope
: method can be used to reconfigure the error monitoring context.init
: initialize the error monitoring service.setUser
: add a user to the error monitoring scope.
You MUST call the error monitoring
init
from within your application at the very beginning.
Create an Id Check Retention Client
Retention mode was created to validate Identity Document asynchronously. In this mode, document will be upload to any backend, which will be in charge of the Identity Check processing.
After creating a retention service on your serveur, you'll have to create a retentionClient
, this is the signature:
export type IdCheckRetentionClient = {
confirmProfile: (values?: Partial<UserProfile>) => Promise<void | EmptyResponse>
uploadDocument: (file: IdCheckFile) => Promise<IdDocumentResponse | EmptyResponse>
}
Since it is asynchronous, you can use an empty object
{}
in your response as you may not have theIdDocumentResponse
.
To activate the retention
, you must set within the Id Check Context retention=true
.
Error handling
uploadDocument
is called to upload the identity document. If the success code is not200/204
, you must handle the error accordingly using theApiError
, see example below.confirmProfile
is called at the end. If the success code is not200/204
, it will displayservice-unavailable
error.
Retention Example
import {
ApiError as IdCheckApiError,
IdCheckErrors,
IdCheckRetentionClient,
UserProfile,
IdCheckFile,
LocalStorageService,
} from '@pass-culture/id-check'
import { api } from 'api/api'
import { ActivityEnum, BeneficiaryInformationUpdateRequest } from 'api/gen'
import { ApiError } from 'api/helpers'
export const idCheckRetentionClient: IdCheckRetentionClient = {
confirmProfile(values?: Partial<UserProfile>) {
return api.patchnativev1beneficiaryInformation({
...(values?.address ? { address: values?.address } : {}),
...(values?.city ? { city: values?.city } : {}),
...(values?.email ? { email: values?.email } : {}),
...(values?.phone ? { phone: values?.phone } : {}),
...(values?.postalCode ? { postalCode: values?.postalCode } : {}),
...(values?.status ? { activity: values?.status as ActivityEnum } : {}),
} as BeneficiaryInformationUpdateRequest)
},
uploadDocument: async (file: IdCheckFile) => {
let error, token
try {
token = await LocalStorageService.getLicenceToken()
if (!token) {
error = new IdCheckApiError('Auth required', 400, {
code: IdCheckErrors['auth-required'],
})
}
} catch (err) {
error = err
}
if (error) {
return Promise.reject(error)
}
try {
const data = new FormData()
data.append('token', token)
data.append('identityDocumentFile', file as Blob)
return await api.postnativev1identityDocument({
body: data,
})
} catch (err) {
error = err
if (err instanceof ApiError) {
if (err.content.code === 'EXPIRED_TOKEN') {
error = new IdCheckApiError(err.content.message, err.statusCode, {
code: IdCheckErrors['auth-token-expired'],
})
} else if (err.content.code === 'INVALID_TOKEN') {
error = new IdCheckApiError(err.content.message, err.statusCode, {
code: IdCheckErrors['auth-required'],
})
} else if (err.content.code === 'FILE_SIZE_EXCEEDED') {
error = new IdCheckApiError(err.content.message, err.statusCode, {
code: IdCheckErrors['file-size-exceeded'],
})
} else if (err.content.code === 'SERVICE_UNAVAILABLE') {
error = new IdCheckApiError(err.content.message, err.statusCode, {
code: IdCheckErrors['validation-unavailable'],
})
}
}
return Promise.reject(error)
}
},
}
Add ID Check routes to your existing application
You can use the export from the module to create routes in your application:
routes
: necessary to add ID Check routes to your applications.initialRouteName
: can be necessary if your application home page is ID Check home, or to remap the ID Check home route.
Navigate to ID Check
- When navigating to ID Check route, you can provide a
licence_token
and it'sexpiration_timestamp
(in ms), if:- the
licence_token
is expired:requestLicenceToken
exist in the context: we get a new licence token, if:- it fail with
400
http status code, user seeTooManyAttempt
error page - it succeed, user continue to ID Check home
- it fail with
requestLicenceToken
does not exist in the context, we can't start id check:- it fail: user see
SessionExpired
error page (Usually for Webapp v1 which MUST passlicence_token
andexpiration_timestamp
query param to the base URL endpoint of the standalone Id Check V2 App)
- it fail: user see
- the
licence_token
is invalid:- it fail: user see
SessionExpired
error page
- it fail: user see
- the
requestLicenceToken
A fetch client that does a unique request can be provided to automatically get a new licence_token
when needed.
This is useful in the native application since the user and can call the secure API /native/v1/id_check_token
endpoint.
Example
Within your App.js
in a new project:
import React, { createRef } from 'react'
import { initialRouteName, routes, linkingConfig, RootStackParamList } from '@pass-culture/id-check'
import { NavigationContainer, NavigationContainerRef } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import { errorMonitoring, analytics } from './services'
const navigationRef = createRef<NavigationContainerRef>()
const Stack = createStackNavigator<RootStackParamList>()
function App() {
function onSuccess() {
console.log('success')
}
function onAbandon() {
console.log('abandon')
}
return (
<IdCheckContextProvider
retention={false}
errorMonitoring={errorMonitoring}
analytics={analytics}
onSuccess={onSuccess}
onAbandon={onAbandon}>
<NavigationContainer
linking={linkingConfig}
fallback={<div>Chargement...</div>}
ref={navigationRef}>
<Navigator
initialRouteName={initialRouteName}
screenOptions={{
headerShown: false,
cardShadowEnabled: false,
cardStyle: {
backgroundColor: 'transparent',
flex: 1,
},
}}>
{routes.map((route: Route) => (
<Screen
key={route.name}
name={route.name}
component={route.component}
options={route.options}
// Below is extra features used by @pass-culture/react-navigation-to-react-router-adapter
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
from={route.from}
path={route.path}
strict={route.strict}
exact={route.exact}
push={route.push}
to={route.to}
/>
))}
</Navigator>
</NavigationContainer>
</IdCheckContextProvider>
)
}
export default App