Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConnectID Initial Implementation #2660

Merged
merged 79 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
6153242
Initial work on ConnectId UI and some intro logic. Working toward POC.
OrangeAndGreen Mar 2, 2023
466026c
Got rid of locked state for Connect ID (only logged out or logged in).
OrangeAndGreen Mar 10, 2023
06f9936
Renamed some files for consistency.
OrangeAndGreen Mar 30, 2023
6d7b527
Changes to initial ConnectID create/recovery workflow.
OrangeAndGreen Apr 6, 2023
87c6d0f
A few look-and-feel changes
OrangeAndGreen Apr 12, 2023
1bfa868
Merge remote-tracking branch 'origin/master' into dv/connect_id
OrangeAndGreen Apr 12, 2023
d16af33
Disabling ConnectID functionality by default.
OrangeAndGreen Apr 12, 2023
a60a863
Changed min SDK to 23.
OrangeAndGreen Apr 24, 2023
e2cb6cb
Added activity for getting Connect recovery vs. new account decision.
OrangeAndGreen Apr 27, 2023
f07b4ed
Fixed recently introduced crash after server error on Connect registr…
OrangeAndGreen Apr 28, 2023
5bd6747
Remembering registration phase to resume after app interruption.
OrangeAndGreen May 2, 2023
0cf3b66
Icons instead of highlighted text on two pages.
OrangeAndGreen May 3, 2023
52b1bb7
ConnectID V1 development, including several new activities.
OrangeAndGreen Jun 8, 2023
e5590c6
Added ConnectID unlock functionality as a developer option.
OrangeAndGreen Jun 9, 2023
db457b4
Improved ConnectID DB encryption using Android KeyStore.
OrangeAndGreen Jun 9, 2023
23881d8
Quick fix: Changed a key received from the server.
OrangeAndGreen Jun 9, 2023
303cac5
Fixed bug where password sometimes wouldn't auto-fill when it should.
OrangeAndGreen Jun 14, 2023
74a21d6
Merge remote-tracking branch 'origin/master' into dv/connect_id
OrangeAndGreen Jun 14, 2023
ab4e140
Added two new externalizable classes to list for FormStorageTest (fix…
OrangeAndGreen Jun 15, 2023
64ca2d2
Added one more externalizable class to FormStorageTest list.
OrangeAndGreen Jun 15, 2023
4db49b5
Added phone number checking to recovery decision page before allowing…
OrangeAndGreen Jun 19, 2023
a0ce2ea
Moved a bunch of ConnectID-related strings from android_translatable_…
OrangeAndGreen Jun 19, 2023
2c35dfb
Added some (temporary) error reporting to API call that checks if pho…
OrangeAndGreen Jun 20, 2023
78bcb6a
Styling improvements.
OrangeAndGreen Jun 21, 2023
88e094a
Solved DB passphrase encryption for API 21 and lower.
OrangeAndGreen Jun 23, 2023
1cca84f
Showing ConnectID page titles in blue bar at top of screen.
OrangeAndGreen Jun 27, 2023
3fc9f5a
Added AppSelectActivity initial implementation (not using yet).
OrangeAndGreen Jul 11, 2023
46aa87f
Show sign in/up if user is logged out
shubham1g5 Jul 11, 2023
8069967
don't set parent activity null on forget user as it causes crash when…
shubham1g5 Jul 11, 2023
a1c37f4
Merge branch 'master' into dv/connect_id
shubham1g5 Jul 11, 2023
371d2d2
Showing ConnectID sign-in menu option when user resumes registration …
OrangeAndGreen Jul 11, 2023
6d7d1b8
Merge branch 'dv/connect_id' of https://github.com/dimagi/commcare-an…
OrangeAndGreen Jul 23, 2023
57a8178
2-minute countdown between OTP requests.
OrangeAndGreen Jul 24, 2023
7a436c2
Disabling biometric config buttons when already configured.
OrangeAndGreen Jul 25, 2023
16521f2
BROKEN: Attempting to use getRecordsForValues to query app_data records.
OrangeAndGreen Jul 26, 2023
e0c18e8
Fixed bug using getRecordsForValues
OrangeAndGreen Jul 26, 2023
44ec36a
fix null check for buildProfileID
shubham1g5 Jul 26, 2023
a3c66aa
In progress: SSO functionality
OrangeAndGreen Jul 31, 2023
457ef9e
Changed UI and some workflow for biometrics configuration.
OrangeAndGreen Aug 1, 2023
ced400a
Logs connect signins
shubham1g5 Aug 2, 2023
993b8e9
set ccc_enabled as a user property
shubham1g5 Aug 2, 2023
68747e0
logs connect id account recovery attempts
shubham1g5 Aug 2, 2023
7774ea7
Logs ccc sign out and normal login clicks
shubham1g5 Aug 3, 2023
8803140
Merge pull request #2687 from dimagi/connectAnalytics
OrangeAndGreen Aug 3, 2023
ad3aa57
Changed SSO token retrieval to a sync process, and calling it asynchr…
OrangeAndGreen Aug 3, 2023
154a5be
Merge branch 'dv/connect_id' of https://github.com/dimagi/commcare-an…
OrangeAndGreen Aug 3, 2023
682f3ee
Completed initial SSO workflow.
OrangeAndGreen Aug 3, 2023
138f746
make event params unique
shubham1g5 Aug 8, 2023
dfd8fdc
More attempted fixes for earlier Android versions using PIN for biome…
OrangeAndGreen Aug 8, 2023
9a46ac9
Addressed several comments from PR 2660.
OrangeAndGreen Aug 9, 2023
6345b66
Merge pull request #2688 from dimagi/analyticsUniqueParams
shubham1g5 Aug 10, 2023
566078e
Showing a toast when user presses Continue button twice while network…
OrangeAndGreen Aug 11, 2023
f80e233
Merge branch 'dv/connect_id' of https://github.com/dimagi/commcare-an…
OrangeAndGreen Aug 11, 2023
f57970a
Changes to address PR comments.
OrangeAndGreen Aug 14, 2023
6ffa2f6
Refactored encryption methods slightly for easier testing.
OrangeAndGreen Aug 15, 2023
63f234d
Added unit test for encryption/decryption using RSA key pair.
OrangeAndGreen Aug 15, 2023
c718bf7
Applied CommCare coding style to all new ConnectID code.
OrangeAndGreen Aug 15, 2023
d4bf1b7
Better singleton loading for ConnectIDNetworkHelper.
OrangeAndGreen Aug 16, 2023
525b332
Addressing comments for PR.
OrangeAndGreen Aug 21, 2023
d88d97d
Tying transformation string to existing key in Keystore (so app can s…
OrangeAndGreen Aug 21, 2023
de32648
Showing progress dialogs for ConnectID network calls.
OrangeAndGreen Aug 21, 2023
3ca59c3
Added some missing strings (from conflict).
OrangeAndGreen Aug 22, 2023
0661af5
Merge branch 'master' into dv/connect_id
OrangeAndGreen Aug 22, 2023
bf11aa2
Removed extra API check and suppressed code warning.
OrangeAndGreen Aug 23, 2023
c4eb7bf
Merge branch 'dv/connect_id' of https://github.com/dimagi/commcare-an…
OrangeAndGreen Aug 23, 2023
f8724f0
Reverted KeyAndTransform from record back to simple helper class (cau…
OrangeAndGreen Aug 23, 2023
be096bb
Merge branch 'master' of https://github.com/dimagi/commcare-android i…
OrangeAndGreen Aug 23, 2023
28c4610
Refactored encryption key code into EncryptionKeyProvider class and e…
OrangeAndGreen Aug 23, 2023
b3aa48e
Assigning default encryptionKeyProvider immediately (child can overri…
OrangeAndGreen Aug 23, 2023
5f53442
Creating MockEncryptionKeyProvider after super.onCreate for CommCareT…
OrangeAndGreen Aug 23, 2023
4bb727e
Addressing lint warnings.
OrangeAndGreen Aug 23, 2023
ee16434
Addressing more lint warnings, mostly code formatting and adding Java…
OrangeAndGreen Aug 23, 2023
f548a4a
Added javadoc descriptions
OrangeAndGreen Aug 23, 2023
b5b60e7
Broke some long lines into multiple
OrangeAndGreen Aug 23, 2023
d6719e3
Addressing remaining lint warnings in ConnectIDManager.
OrangeAndGreen Aug 24, 2023
8855e6b
Cleaning up more lint warnings.
OrangeAndGreen Aug 24, 2023
6409159
Addressing more lint warnings.
OrangeAndGreen Aug 24, 2023
b8d8997
Renamed all ConnectID* classes to ConnectId*
OrangeAndGreen Aug 24, 2023
98c0a6f
Fixed more lint warnings.
OrangeAndGreen Aug 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,18 @@
<activity android:name="org.commcare.activities.RootMenuHomeActivity"/>
<activity android:name="org.commcare.activities.MenuActivity"/>

<activity android:name="org.commcare.activities.connect.ConnectIDRecoveryDecisionActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDLoginActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDConsentActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDPhoneActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDRegistrationActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDPasswordActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDPasswordVerificationActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDVerificationActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDPicturesActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDPhoneVerificationActivity"/>
<activity android:name="org.commcare.activities.connect.ConnectIDMessageActivity"/>

<provider
android:name="org.commcare.provider.FormsProvider"
android:exported="false"
Expand Down
106 changes: 105 additions & 1 deletion app/assets/locales/android_translatable_strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ menu.privilege.claim.disable=Disable Privileges
menu.data.change.logs=Data Change Logs
menu.enable.rate.limit.popup=Enable Rate Limit Error Popup
menu.enable.manual.form.quarantine=Enable Manual Form Quarantine
menu.enable.connect.id=Enable ConnectID
connect.id.enabled=ConnectID Enabled

install.fail.error=We encountered an ${0} error processing your request. Please try again later. If the problem persists, contact CommCare Support.

Expand Down Expand Up @@ -175,16 +177,115 @@ login.password=Password
login.pin.password=PIN
login.primed.prompt=Your password has been saved for you! Just press 'Log In'.
login.button=Log In
login.button.connect=Sign in with ConnectID
OrangeAndGreen marked this conversation as resolved.
Show resolved Hide resolved
login.app.direct=Login to your app directly.
login.sync=Synchronize with server
login.bad.password=We couldn't find a user with this password. Please try another!
login.welcome.single=Welcome back! Please log in.
login.welcome.multiple=Welcome back! Please select an app and log in.
login.welcome.connect.signedout=Log into ConnectID first and then enter your app.
login.welcome.connect.signedin=Welcome ${0}!
login.show.password=SHOW
login.hide.password=HIDE

login.update.install.success=App update successfully applied!
login.update.install.failure=App update failed to apply!

choice.or=OR

connect.button.logged.in=Go to Connect menu
connect.button.logged.out=Login to Connect ID

connect.consent.title=Consent
connect.consent.message=Do you give your consent for ConnectID?
connect.consent.button=OK

connect.phone.title=Primary Phone
connect.phone.message=Please enter your primary phone number
connect.phone.button=OK
connect.phone.checking=Checking...
connect.phone.available=Phone number is available!
connect.phone.unavailable=Phone number is already in use
connect.phone.invalid=Enter a valid phone number

connect.password.title=Recovery Password
connect.password.message=Please choose a recovery password
connect.password.button=OK
connect.password=Enter Password
connect.password.repeat=Confirm Password
connect.password.mismatch=Passwords must match
connect.password.weak=Please choose a stronger password

connect.password.verify.title=Recovery Password
connect.password.verify.message=Please enter your recovery password to continue.
connect.password.verify=Enter Password
connect.password.verify.forgot=I forgot my password
connect.password.verify.button=Submit

connect.password.fail.title=Wrong Password
connect.password.fail.message=You entered the wrong password, please try again.
connect.password.fail.button=OK

connect.recovery.title=ConnectID Account
connect.recovery.decision.new=This is the first time logging into Connect on this device. Do you need to create a new account or recover an existing account?
connect.recovery.button.new=Create New Account
connect.recovery.button.recover=Recover Existing Account
connect.recovery.decision.phone=Please enter the primary phone number you registered with your account.
connect.recovery.button.phone=Continue
connect.recovery.button.extended=More Options

connect.recovery.alt.title=Alternate Phone
connect.recovery.alt.message=On the next screen, we'll send a code via SMS to the alternate phone number associated with your account. Once verified, you can set a new password.
connect.recovery.alt.button=Continue

connect.recovery.success.title=Account Recovered
connect.recovery.success.message=You have successfully recovered your account and can now resume using your ConnectID.
connect.recovery.success.button=OK

connect.unlock.title=ConnectID Sign In
connect.unlock.message=Please sign in to continue
connect.unlock.button.pin=Sign in with PIN
connect.unlock.button.password=Sign in with Password
connect.unlock.trouble.message=Trouble signing in?
connect.unlock.fingerprint.title=Sign in via fingerprint
connect.unlock.fingerprint.message=Use your fingerprint to continue
connect.unlock.other.options=Other options
connect.unlock.pin.title=Sign in via PIN
connect.unlock.pin.message=Enter your PIN to continue

connect.register.title=Create Account
connect.register.id=User ID
connect.register.name=Name
connect.register.dob=Date of Birth (YYYY-MM-DD)
connect.register.phone=Phone Number (+18887776666)
connect.register.phone.alt=Alternate Phone Number
connect.register.create=Create Account

connect.register.success.title=Account Created
connect.register.success.message=Your ConnectID account has been successfully created and is now ready for you to use!
connect.register.success.button=OK

connect.verify.title=Login Options
connect.verify.message=Please configure at least one local verification method. Check means configured, eye means not configured, X means unavailable.
connect.verify.fingerprint=Fingerprint
connect.verify.pin=PIN
connect.verify.button.configured=Continue
connect.verify.button.password=Use Password Only

connect.verify.phone.title=Verify Phone
connect.verify.phone.label=Please enter the code sent via SMS to your primary phone${0}.
connect.verify.phone.label.alternate=Almost there! Please enter the code sent via SMS to your alternate phone${0}.
connect.verify.phone.resend=Resend code
connect.verify.phone.change=Change phone number
connect.verify.phone.verify=Verify code

connect.pictures.title=Account Recovery
connect.pictures.label=To help with account recovery, you can optionally take some photos to help identify you.
connect.pictures.face=Face
connect.pictures.id=Official ID
connect.pictures.skip=Skip
connect.pictures.continue=Continue

query.button=Query
query.dialog.title=Querying Server
query.dialog.body=Searching server for relevant data
Expand All @@ -195,7 +296,7 @@ post.generic.error=An error occurred while preparing the HTTP request
post.dialog.title=Claiming...
post.dialog.body=Claiming chosen data from server
post.io.error=Error reading server response: ${0}
post.unknown.response=Received unknown resonse code (${0}) from server
post.unknown.response=Received unknown response code (${0}) from server
post.client.error=Client-side error (code ${0}) received from network request.
post.server.error=Server-side error (code ${0}) received from network request.
post.gone.error=Case is not present on server.
Expand Down Expand Up @@ -335,6 +436,9 @@ bulk.form.dump.success=${1} forms dumped successfully
login.menu.demo=Enter Practice Mode
login.menu.password.mode=Forgot PIN?
login.menu.app.manager=Go To App Manager
login.menu.connect.signin=Sign up for ConnectID
login.menu.connect.signout=Sign out of ConnectID
login.menu.connect.forget=Forget ConnectID user

main.sync.demo=You cannot sync data down from the server when using practice mode
main.sync.demo.has.forms=Your forms have been submitted to the server; however, you cannot retrieve forms from the server in practice mode.
Expand Down
5 changes: 5 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ dependencies {

implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.guava:guava:31.1-jre'

implementation 'androidx.biometric:biometric:1.1.0'

implementation 'io.michaelrocks:libphonenumber-android:8.13.11'
implementation 'com.nulab-inc:zxcvbn:1.7.0'
}

ext {
Expand Down
32 changes: 32 additions & 0 deletions app/res/layout/screen_connect_consent.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@color/cc_core_bg"
android:orientation="vertical">

<TextView
android:id="@+id/connect_consent_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textColor="@color/cc_neutral_color"
android:textSize="@dimen/text_largest" />

<TextView
android:id="@+id/connect_consent_message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_min_margin"
android:gravity="start"
android:textSize="@dimen/text_medium"/>

<Button
android:id="@+id/connect_consent_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_start"
android:paddingTop="@dimen/content_start" />

</LinearLayout>
61 changes: 61 additions & 0 deletions app/res/layout/screen_connect_login.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@color/cc_core_bg"
android:orientation="vertical">

<TextView
android:id="@+id/connect_login_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textColor="@color/cc_neutral_color"
android:textSize="@dimen/text_largest" />

<TextView
android:id="@+id/connect_login_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textSize="@dimen/text_medium" />

<Button
android:id="@+id/connect_pin_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_start"
android:paddingTop="@dimen/content_start"
android:visibility="gone"/>

<TextView
android:id="@+id/connect_login_or"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textSize="@dimen/text_medium"
android:visibility="gone"/>

<Button
android:id="@+id/connect_password_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_start"
android:paddingTop="@dimen/content_start"
android:visibility="gone"/>

<TextView
android:id="@+id/connect_trouble_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textColor="@color/blue"
android:textSize="@dimen/text_medium"
android:visibility="gone"/>

</LinearLayout>
32 changes: 32 additions & 0 deletions app/res/layout/screen_connect_message.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@color/cc_core_bg"
android:orientation="vertical">

<TextView
android:id="@+id/connect_message_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textColor="@color/cc_neutral_color"
android:textSize="@dimen/text_largest" />

<TextView
android:id="@+id/connect_message_message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_min_margin"
android:gravity="start"
android:textSize="@dimen/text_medium"/>

<Button
android:id="@+id/connect_message_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_start"
android:paddingTop="@dimen/content_start" />

</LinearLayout>
52 changes: 52 additions & 0 deletions app/res/layout/screen_connect_password.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@color/cc_core_bg"
android:orientation="vertical">

<TextView
android:id="@+id/connect_password_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/content_min_margin"
android:textColor="@color/cc_neutral_color"
android:textSize="@dimen/text_largest" />

<TextView
android:id="@+id/connect_password_message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_min_margin"
android:gravity="start"
android:textSize="@dimen/text_medium"/>

<AutoCompleteTextView
android:id="@+id/connect_password_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />

<AutoCompleteTextView
android:id="@+id/connect_password_repeat_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />

<TextView
android:id="@+id/connect_password_error_message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_min_margin"
android:gravity="start"
android:textSize="@dimen/text_medium"/>

<Button
android:id="@+id/connect_password_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_start"
android:paddingTop="@dimen/content_start" />

</LinearLayout>
Loading