feat(webauthn): allow Android native origin #1196
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary of change
Modifications to Support Android Native WebAuthn Origins
Context
Currently, when attempting to define an Android Native origin (in the format
android:apk-key-hash:<base64Url-string-without-padding-of-fingerprint>) through supertokens_python.recipe.webauthn.register_options and supertokens_python.recipe.webauthn.sign_in_options, the Core returns anINVALID_OPTIONS_ERRORstatus without specifying a reason. The "origin" field of these functions appears to only work with HTTP(S) URLs.There is no indication of this limitation in any of the documentation I've reviewed, which leads me to believe this has never been tested under these conditions (i.e., from an Android Native application, without an Pre-Built UI (frontend SDK), as is possible with react-native-passkey).
I initially attempted to use Function overrides, a solution I'm not particularly fond of. While this can work during the "Register Options" phase (where it's possible to switch the Android Native origin to the HTTPS URL provided as the origin when calling the Python function to bypass the Core), it becomes impossible during the Sign-In phase, as this invalidates the signature sent by the device, causing the Core to legitimately reject the request.
Therefore, I propose this PR with several modifications to allow the Core to support this origin format in the same way it handles HTTP(S) URLs, avoiding these workarounds (which don't work anyway).
This is my first pull request to an open source project of this scale, and I'm open to any feedback if I'm on the wrong track or doing things incorrectly.
Modified Files
1. OptionsValidator.java
File:
src/main/java/io/supertokens/webauthn/validator/OptionsValidator.javaChangelog:
android:apk-key-hash:2. Utils.java (Tests)
File:
src/test/java/io/supertokens/test/webauthn/Utils.javaModifications:
registerOptions()andsignInOptions()accepting anoriginparameter3. TestAndroidOriginValidation.java (New File)
File:
src/test/java/io/supertokens/test/webauthn/api/TestAndroidOriginValidation.javaTests Added:
testValidAndroidOrigin(): Verifies that a valid Android origin is acceptedtestValidAndroidOriginWithAlternativeHash(): Tests with an alternative valid hashtestAndroidOriginWithEmptyHash(): Verifies rejection of an empty hashtestAndroidOriginWithInvalidCharacters(): Verifies rejection of invalid characterstestAndroidOriginWithInvalidLength(): Verifies rejection of incorrect length (must be exactly 43 characters)testAndroidOriginForSignInOptions(): Tests Android origins for sign-intestMixedOriginsSupport(): Verifies that HTTP, HTTPS, and Android coexistTest Execution
I executed this test to validate proper functionality:
From the supertokens-root:
./gradlew :supertokens-core:test --tests "io.supertokens.test.webauthn.api.TestAndroidOriginValidation"Origin Examples
Valid Android Origins
Invalid Android Origins
HTTP(S) Origins (Still Supported)
WebAuthn Specification Compliance
These modifications comply with the WebAuthn specification, which defines different origin formats depending on the platform:
https://example.com,http://localhost, andhttps://<RPID>(in accordance with Apple App Site Association (AASA))android:apk-key-hash:<base64Url-string-without-padding-of-fingerprint>(see https://developer.android.com/identity/passkeys/create-passkeys#verify)Security Notes
relyingPartyIdin the same way as HTTP(S) origins (compliant with the spec)Test Plan
Command used to test the implementation:
Documentation changes
I don't feel it's necessary to make changes to the documentation, as there was nothing to suggest the current limitation. This should be transparent to the few people in this situation.
Checklist for important updates
coreDriverInterfaceSupported.jsonfile has been updated (if needed)pluginInterfaceSupported.jsonfile has been updated (if needed)build.gradlegetPaidFeatureStatsfunction in FeatureFlag.java filebuild.gradle, please make sure to add themin
implementationDependencies.json.getValidFieldsinio/supertokens/config/CoreConfig.javaif new aliases were added for any coreconfig (similar to the
access_token_signing_key_update_intervalconfig alias).git tag) in the formatvX.Y.Z, and then find thelatest branch (
git branch --all) whoseX.Yis greater than the latest released tag.app_id_to_user_idtable, make sure to delete from this table when deletingthe user as well if
deleteUserIdMappingToois false.