aws-amplify / amplify-ui-swift-liveness

This repository offers a UI component for Amazon Rekognition Face Liveness, enabling developers to ensure that only authentic users, and not bad actors using spoofs, can access their services.
https://ui.docs.amplify.aws/swift/connected-components/liveness
Apache License 2.0
9 stars 20 forks source link

FaceLivenessDetectorView is not showing up on screen #28

Closed Sandiverse closed 1 year ago

Sandiverse commented 1 year ago

I am developing a Flutter App and since Amplify UI Face Liveness component is not Flutter ready yet, I am showing a native screen via platform channels, but the Swift UI view is not showing once the screen is opened.

This is my Swift UI view

import FaceLiveness
import SwiftUI

struct FaceLivenessDetectionView: View {
    var sessionId: String?
    var awsCredentials: CustomAWSCredentials?

    var body: some View {
        if let livenessSessionId = sessionId,
           let accessKeyId = awsCredentials?.accessKeyId,
           let secretAccessKey = awsCredentials?.secretAccessKey,
           let sessionToken = awsCredentials?.sessionToken,
           let expiration = awsCredentials?.expiration
           {
            FaceLivenessDetectorView(
                sessionID: livenessSessionId,
                credentialsProvider: FlutterAWSCredentialsProvider {
                    FlutterAWSCredentials(sessionToken: sessionToken,
                                          expiration: expiration,
                                          accessKeyId: accessKeyId,
                                          secretAccessKey: secretAccessKey)
                },
                region: "us-east-1",
                isPresented: .constant(true),
                onCompletion: { result in
                    switch result {
                    case .success:
                        print("Success")
                    case .failure(let error):
                        print("Error: \(error)")
                    default:
                        print("Default")
                    }
                }
            )
        } else {
            Text("Empty View")
                .font(.largeTitle)
                .foregroundColor(.white)
                .background(Color.blue)
                .edgesIgnoringSafeArea(.all)
        }
    }

I am sending all the credentials needed for the component from the Flutter side and by using a custom credentials provider

This is my custom credentials provider

import Amplify
import AWSPluginsCore

struct FlutterAWSCredentialsProvider: AWSCredentialsProvider {
    let credentials: () -> AWSCredentials

    func fetchAWSCredentials() async throws -> AWSCredentials {
        credentials()
    }
}

struct FlutterAWSCredentials: AWSTemporaryCredentials {
    var sessionToken: String
    var expiration: Date
    var accessKeyId: String
    var secretAccessKey: String
}

This is how I am displaying the Swift UI view on the screen (commented lines are another way I was trying without success)

navigationChannel.setMethodCallHandler {
            (call: FlutterMethodCall, result: FlutterResult) in
            switch call.method {
            case "startLivenesDetection":
                guard let rootViewController = UIApplication.shared.keyWindow?.rootViewController else {
                    result(FlutterError(code: "NOT_FOUND", message: "Root view controller not found", details: nil))
                    return
                }
                guard let sessionId = self.faceLivenessSessionId else {
                    result(FlutterError(code: "NOT_FOUND", message: "Face Liveness session ID is null", details: nil))
                    return
                }
                guard let awsCredentials = self.customAWSCredentials else {
                    result(FlutterError(code: "NOT_FOUND", message: "AWS Credentials are null", details: nil))
                    return
                }
                let faceLivenessController = UIHostingController(rootView: FaceLivenessDetectionView(sessionId: sessionId,
                                                                                                     awsCredentials: awsCredentials))
//                rootViewController.present(faceLivenessController,
//                                           animated: true,
//                                           completion: nil)
                if let window = UIApplication.shared.windows.first {
                    window.rootViewController = faceLivenessController
                    window.makeKeyAndVisible()
                }
            default:
                result(FlutterMethodNotImplemented)
            }
        }

This implementation is working Fine on Android but not on iOS

All I see in the debug console is this

3 Error: Transpose unit is not supported.
2023-05-10T11:47:20-0600 info CognitoIdentityClient : [Logging] Request: POST https:443
 Path: /
 x-amz-user-agent: aws-sdk-swift/1.0,
X-Amz-Target: AWSCognitoIdentityService.GetId,
Content-Length: 79,
Content-Type: application/x-amz-json-1.1,
User-Agent: aws-sdk-swift/1.0 api/cognito-identity/1.0 os/iOS/16.4.1 lang/swift/5.8 lib/amplify-swift/2.10.0,
Host: cognito-identity.us-east-1.amazonaws.com
 Optional([])
2023-05-10T11:47:20-0600 info SerialExecutor : [Logging] Creating connection pool for Optional("https://cognito-identity.us-east-1.amazonaws.com/?")with max connections: 50
2023-05-10T11:47:20-0600 info CRTClientEngine : [Logging] Connection was acquired to: Optional("https://cognito-identity.us-east-1.amazonaws.com/?")

Let me know if there is something else I can try or provide in order to help this issue being solved.

devedup commented 1 year ago

Same issue here.

atierian commented 1 year ago

Thanks for opening this issue @Sandiverse. As you mentioned, we don't support Flutter currently. Have you tried using this in a pure SwiftUI context (without using a channel to bridge to Flutter) to rule out any issues in bridging to Flutter through the channel?

Are you using the Auth category in Amplify in your application? If so, you shouldn't have to provide a credentials provider to the component.

devedup commented 1 year ago

I'm using a pure SwiftUI context and experiencing the same white screen.

atierian commented 1 year ago

I'm using a pure SwiftUI context and experiencing the same white screen.

I saw that in the issue you opened. We need a bit more information to investigate this though. Can you please provide the info requested over in the issue you opened?

If these end up being related, we'll consolidate the issues. But until then it's best to keep them separate to make sure we can debug this properly. Thanks!

devedup commented 1 year ago

@Sandiverse

Despite providing my own Credentials Provider, like yourself, i needed to go through amplify auth update again to remove the default settings. Below are the options I chose.

Then running it again, the screen appeared. However, having a few socket disconnect issues now that I'm resolving.

dave@Davids-MacBook-Pro-M1-Max iOS % amplify update auth
Please note that certain attributes may not be overwritten if you choose to use defaults settings.
Using service: Cognito, provided by: awscloudformation
 What do you want to do? Walkthrough all the auth configurations
 Select the authentication/authorization services that you want to use: User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and m
ore)
 Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) Yes
 Do you want to enable 3rd party authentication providers in your identity pool? No
 Do you want to add User Pool Groups? No
 Do you want to add an admin queries API? No
 Multifactor authentication (MFA) user login options: OFF
 Email based user registration/forgot password: Disabled (Uses SMS/TOTP as an alternative)
 Please specify an SMS verification message: Your verification code is {####}
 Do you want to override the default password policy for this User Pool? No
 Specify the app's refresh token expiration period (in days): 30
 Do you want to specify the user attributes this app can read and write? No
 Do you want to enable any of the following capabilities? 
 Do you want to use an OAuth flow? No
? Do you want to configure Lambda Triggers for Cognito? No
✅ Successfully updated auth resource locally

dave@Davids-MacBook-Pro-M1-Max iOS % amplify push
atierian commented 1 year ago

If you're not using Amplify in your project already, or don't want to add it to handle auth, you don't need to use Amplify CLI to create (or update) any backend resources.

If you're injecting a credentials provider, Amplify Auth isn't used at all.

To be clear:

  1. Using Amplify Auth -> You shouldn't inject credentials provider. This is handled automatically.
  2. Not using Amplify Auth -> You're responsible for credentials management and have to inject a credentials provider.
devedup commented 1 year ago

This is good to know thanks. All clear

AWS support told me originally that I had to use Cognito. 🙄

atierian commented 1 year ago

If you're not using Amplify Auth, you'll still need to provide valid AWS credentials to the component through the credentials provider. However they don't need to be sourced from Amazon Cognito.

devedup commented 1 year ago

Thanks. Yes, currently I have an AWS IAM user with this inline policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "rekognition:StartFaceLivenessSession",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "rekognition:CreateFaceLivenessSession",
            "Resource": "*"
        }
    ]
}

… but it still would mean embedding the key/secret in my code - or returning them from a backend call after auth….. which still exposes them.

The use case is that I have users that are already authenticated on a dating app, and they can opt in to have their profile/account photos verified. I’m already using Recognition to detect faces match successfully, but need to add another layer to stop fake photos getting through. Hence using Face Liveness to detect real people.

On 17 May 2023, at 20:16, Ian Saultz @.***> wrote:

If you're not using Amplify Auth, you'll still need to provide valid AWS credentials to the component through the credentials provider. However they don't need to be sourced from Amazon Cognito.

— Reply to this email directly, view it on GitHub https://github.com/aws-amplify/amplify-ui-swift-liveness/issues/28#issuecomment-1551925922, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACPXSVGG5ISHBNO6OYA573XGUPYDANCNFSM6AAAAAAX5B4OKU. You are receiving this because you commented.

Sandiverse commented 1 year ago

Thank you for reply @atierian.

I have tested this component in a pure Swift UI context application as you suggested it and the component is working as expected. So maybe it is something related to Flutter Platform channels.

I was even trying with Flutter Platform Views and the screen opens black but now the green dot in the status bar appears like if the camera is doing something but nothing shows up.

In the end I can not tell if the problem is completely from Flutter or if it is a combination of some sort of implementation in the Amplify library for the Face Liveness Swift UI component and Flutter.

atierian commented 1 year ago

I'm glad to hear you got it working in SwiftUI directly. While we don't explicitly support using the component from Flutter, I would like to know if there are any small tweaks we can make to get it to work. I'll try to put together a simple working example in the coming days. In the meantime, if you manage to get it working, please let us know. Thanks!

Sandiverse commented 1 year ago

Hi, it's been a while, I hope you're doing well.

Unfortunalety, I'm still not able to make it work.

I made a github repo with a sample project for you to test, I hope it helps.

https://github.com/Sandiverse/flutter_swift_face_liveness

I added to the readme some guidance in order to configure the project.

atierian commented 1 year ago

Thanks for the sample project link. I'll follow up here with any updates.

Sandiverse commented 1 year ago

Hello, it's been a long time, sorry for the insistence but I would like to know if there is any update on this.

atierian commented 1 year ago

No updates yet. If you discover that there's a Flutter compatibility issue and have a root cause, please let us know and we'll see if we can address it.

Thanks for your patience.

Sandiverse commented 1 year ago

Hi there,

I'm glad to tell that after upgrading Amplify UI Swift package to version 1.1.0 the bug seems to have dissapeared.

Now I have a completely successful hybrid implementation of this component between Flutter and Native Swift iOS.

Thank you @atierian for all your help.

atierian commented 1 year ago

That's great to hear 🎉 Thanks for letting us know!