-
Notifications
You must be signed in to change notification settings - Fork 293
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(liveness): Liveness cred provider (#4260)
* feat(liveness): add credentialProvider prop (#3790) * feat(liveness): add credentialProvier prop * chore: update sdk types * chore: remove extra api definition * update yarn.lock * chore: update credential provider API based on internal review * chore: add unit tests to fix coverage * chore: address feedback * chore: add comment on why credentials are copied, fix unit tests * chore: add size limit check for react-liveness * fix: reusable unit test size check * chore: update types to better match AWS SDK types, export them as well * Update packages/react-liveness/src/components/FaceLivenessDetector/service/types/liveness.ts Co-authored-by: Caleb Pollman <cpollman@amazon.com> * Update packages/react-liveness/src/components/FaceLivenessDetector/service/types/liveness.ts Co-authored-by: Caleb Pollman <cpollman@amazon.com> * chore: switch to using credential-provider@3.310.0 * address feedback * Update packages/e2e/features/ui/components/liveness/with-credential-provider.feature * update to use more recent aws-sdk deps * try fixing deps * update aws-sdk dep to 3.350.0 * maybe this fixes it * another try * fix yarn.lock * fix e2e test --------- Co-authored-by: Caleb Pollman <cpollman@amazon.com> Co-authored-by: William Lee <43682783+wlee221@users.noreply.github.com> * update yarn.lock * Create pretty-laws-obey.md * update ignored links * fix yarn.lock --------- Co-authored-by: Caleb Pollman <cpollman@amazon.com> Co-authored-by: William Lee <43682783+wlee221@users.noreply.github.com>
- Loading branch information
1 parent
d165ddf
commit e4bf312
Showing
23 changed files
with
1,155 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@aws-amplify/ui-react-liveness": minor | ||
--- | ||
|
||
feat(liveness): Liveness cred provider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
examples/next/pages/ui/components/liveness/with-credential-provider/aws-exports.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import awsExports from '@environments/liveness/liveness-environment/src/aws-exports'; | ||
export default awsExports; |
33 changes: 33 additions & 0 deletions
33
examples/next/pages/ui/components/liveness/with-credential-provider/index.page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import dynamic from 'next/dynamic'; | ||
import React from 'react'; | ||
import { Amplify } from 'aws-amplify'; | ||
import { fromCognitoIdentityPool } from '@aws-sdk/credential-providers'; | ||
import { AwsCredentialProvider } from '@aws-amplify/ui-react-liveness'; | ||
|
||
import LivenessDefault from '../components/LivenessDefault'; | ||
import Layout from '../components/Layout'; | ||
import awsExports from './aws-exports'; | ||
|
||
Amplify.configure({ | ||
...awsExports, | ||
Analytics: { | ||
autoSessionRecord: false, | ||
}, | ||
}); | ||
|
||
const App = () => { | ||
const credentialProvider: AwsCredentialProvider = fromCognitoIdentityPool({ | ||
clientConfig: { region: 'us-east-2' }, | ||
identityPoolId: 'us-east-2:89d27d83-5313-46b2-a7cb-328604399400', | ||
}); | ||
|
||
return ( | ||
<Layout> | ||
<LivenessDefault credentialProvider={credentialProvider} /> | ||
</Layout> | ||
); | ||
}; | ||
|
||
export default dynamic(() => Promise.resolve(App), { | ||
ssr: false, | ||
}); |
22 changes: 22 additions & 0 deletions
22
packages/e2e/features/ui/components/liveness/with-credential-provider.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Feature: Liveness with Custom Components | ||
|
||
Liveness component supports using a custom credential provider. | ||
|
||
Background: | ||
Given I'm running the example "ui/components/liveness/with-credential-provider/" | ||
|
||
@react | ||
Scenario: See camera module and close with the close icon | ||
Then I click the "Begin check" button | ||
And I click the "close-icon" | ||
Then I see the "Begin check" button | ||
|
||
@react | ||
Scenario: See camera module and instructions | ||
Then I click the "Begin check" button | ||
And I see "liveness-detector" element | ||
And I see "connecting" | ||
And I see "Move closer" | ||
And I see "Face didn't fill oval within time limit." | ||
And I click the "Try again" button | ||
Then I see the "Begin check" button |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 16 additions & 80 deletions
96
packages/react-liveness/src/components/FaceLivenessDetector/FaceLivenessDetector.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,34 @@ | ||
import * as React from 'react'; | ||
import { useActor, useInterpret } from '@xstate/react'; | ||
import { Credentials as AmplifyCredentials } from '@aws-amplify/core'; | ||
import { | ||
livenessMachine, | ||
AwsTemporaryCredentials, | ||
FaceLivenessDetectorProps as FaceLivenessDetectorPropsFromUi, | ||
} from './service'; | ||
import { View, Flex } from '@aws-amplify/ui-react'; | ||
|
||
import { FaceLivenessDetectorProvider } from './providers'; | ||
import { StartLiveness } from './StartLiveness'; | ||
import { LivenessCheck } from './LivenessCheck'; | ||
import { getVideoConstraints } from './StartLiveness/helpers'; | ||
import { StartScreenComponents } from './shared/DefaultStartScreenComponents'; | ||
import FaceLivenessDetectorCore, { | ||
FaceLivenessDetectorComponents, | ||
} from './FaceLivenessDetectorCore'; | ||
import { LivenessDisplayText } from './displayText'; | ||
import { getDisplayText } from './utils/getDisplayText'; | ||
import { CheckScreenComponents } from './shared/FaceLivenessErrorModal'; | ||
|
||
const DETECTOR_CLASS_NAME = 'liveness-detector'; | ||
|
||
type FaceLivenessDetectorComponents = StartScreenComponents & | ||
CheckScreenComponents; | ||
|
||
export interface FaceLivenessDetectorProps | ||
extends FaceLivenessDetectorPropsFromUi { | ||
components?: FaceLivenessDetectorComponents; | ||
displayText?: LivenessDisplayText; | ||
} | ||
|
||
const credentialProvider = async () => { | ||
const credentials = | ||
(await AmplifyCredentials.get()) as AwsTemporaryCredentials; | ||
return credentials; | ||
}; | ||
|
||
export default function FaceLivenessDetector( | ||
props: FaceLivenessDetectorProps | ||
): JSX.Element { | ||
const { | ||
disableInstructionScreen = false, | ||
components, | ||
config, | ||
displayText, | ||
} = props; | ||
const currElementRef = React.useRef<HTMLDivElement>(null); | ||
const { | ||
hintDisplayText, | ||
cameraDisplayText, | ||
instructionDisplayText, | ||
streamDisplayText, | ||
errorDisplayText, | ||
} = getDisplayText(displayText); | ||
|
||
const service = useInterpret(livenessMachine, { | ||
devTools: process.env.NODE_ENV === 'development', | ||
context: { | ||
componentProps: { | ||
...props, | ||
config: config ?? {}, | ||
}, | ||
}, | ||
}); | ||
|
||
const [state, send] = useActor(service); | ||
const isStartView = state.matches('start') || state.matches('userCancel'); | ||
|
||
const beginLivenessCheck = React.useCallback(() => { | ||
const videoConstraints = getVideoConstraints(); | ||
|
||
send({ | ||
type: 'BEGIN', | ||
data: { videoConstraints }, | ||
}); | ||
}, [send]); | ||
|
||
React.useLayoutEffect(() => { | ||
if (disableInstructionScreen && isStartView) { | ||
beginLivenessCheck(); | ||
} | ||
}, [beginLivenessCheck, disableInstructionScreen, isStartView]); | ||
|
||
const { config, ...rest } = props; | ||
return ( | ||
<View className={DETECTOR_CLASS_NAME} testId={DETECTOR_CLASS_NAME}> | ||
<FaceLivenessDetectorProvider componentProps={props} service={service}> | ||
<Flex direction="column" ref={currElementRef}> | ||
{isStartView ? ( | ||
<StartLiveness | ||
beginLivenessCheck={beginLivenessCheck} | ||
components={components} | ||
instructionDisplayText={instructionDisplayText} | ||
/> | ||
) : ( | ||
<LivenessCheck | ||
hintDisplayText={hintDisplayText} | ||
cameraDisplayText={cameraDisplayText} | ||
streamDisplayText={streamDisplayText} | ||
errorDisplayText={errorDisplayText} | ||
components={components} | ||
/> | ||
)} | ||
</Flex> | ||
</FaceLivenessDetectorProvider> | ||
</View> | ||
<FaceLivenessDetectorCore | ||
{...rest} | ||
config={{ credentialProvider, ...config }} | ||
/> | ||
); | ||
} |
98 changes: 98 additions & 0 deletions
98
packages/react-liveness/src/components/FaceLivenessDetector/FaceLivenessDetectorCore.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import * as React from 'react'; | ||
import { useActor, useInterpret } from '@xstate/react'; | ||
import { | ||
livenessMachine, | ||
FaceLivenessDetectorCoreProps as FaceLivenessDetectorPropsFromUi, | ||
} from './service'; | ||
import { View, Flex } from '@aws-amplify/ui-react'; | ||
|
||
import { FaceLivenessDetectorProvider } from './providers'; | ||
import { StartLiveness } from './StartLiveness'; | ||
import { LivenessCheck } from './LivenessCheck'; | ||
import { getVideoConstraints } from './StartLiveness/helpers'; | ||
import { StartScreenComponents } from './shared/DefaultStartScreenComponents'; | ||
import { LivenessDisplayText } from './displayText'; | ||
import { getDisplayText } from './utils/getDisplayText'; | ||
import { CheckScreenComponents } from './shared/FaceLivenessErrorModal'; | ||
|
||
const DETECTOR_CLASS_NAME = 'liveness-detector'; | ||
|
||
export type FaceLivenessDetectorComponents = StartScreenComponents & | ||
CheckScreenComponents; | ||
|
||
export interface FaceLivenessDetectorCoreProps | ||
extends FaceLivenessDetectorPropsFromUi { | ||
components?: FaceLivenessDetectorComponents; | ||
displayText?: LivenessDisplayText; | ||
} | ||
|
||
export default function FaceLivenessDetectorCore( | ||
props: FaceLivenessDetectorCoreProps | ||
): JSX.Element { | ||
const { | ||
disableInstructionScreen = false, | ||
components, | ||
config, | ||
displayText, | ||
} = props; | ||
const currElementRef = React.useRef<HTMLDivElement>(null); | ||
const { | ||
hintDisplayText, | ||
cameraDisplayText, | ||
instructionDisplayText, | ||
streamDisplayText, | ||
errorDisplayText, | ||
} = getDisplayText(displayText); | ||
|
||
const service = useInterpret(livenessMachine, { | ||
devTools: process.env.NODE_ENV === 'development', | ||
context: { | ||
componentProps: { | ||
...props, | ||
config: config ?? {}, | ||
}, | ||
}, | ||
}); | ||
|
||
const [state, send] = useActor(service); | ||
const isStartView = state.matches('start') || state.matches('userCancel'); | ||
|
||
const beginLivenessCheck = React.useCallback(() => { | ||
const videoConstraints = getVideoConstraints(); | ||
|
||
send({ | ||
type: 'BEGIN', | ||
data: { videoConstraints }, | ||
}); | ||
}, [send]); | ||
|
||
React.useLayoutEffect(() => { | ||
if (disableInstructionScreen && isStartView) { | ||
beginLivenessCheck(); | ||
} | ||
}, [beginLivenessCheck, disableInstructionScreen, isStartView]); | ||
|
||
return ( | ||
<View className={DETECTOR_CLASS_NAME} testId={DETECTOR_CLASS_NAME}> | ||
<FaceLivenessDetectorProvider componentProps={props} service={service}> | ||
<Flex direction="column" ref={currElementRef}> | ||
{isStartView ? ( | ||
<StartLiveness | ||
beginLivenessCheck={beginLivenessCheck} | ||
components={components} | ||
instructionDisplayText={instructionDisplayText} | ||
/> | ||
) : ( | ||
<LivenessCheck | ||
hintDisplayText={hintDisplayText} | ||
cameraDisplayText={cameraDisplayText} | ||
streamDisplayText={streamDisplayText} | ||
errorDisplayText={errorDisplayText} | ||
components={components} | ||
/> | ||
)} | ||
</Flex> | ||
</FaceLivenessDetectorProvider> | ||
</View> | ||
); | ||
} |
Oops, something went wrong.