Skip to content

implement start passkey enrollment- updated #15162

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

Open
wants to merge 8 commits into
base: passkey-new
Choose a base branch
from

Conversation

srushtisv
Copy link
Contributor

No description provided.

Copy link
Contributor

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

@google-oss-bot
Copy link

1 Warning
⚠️ Did you forget to add a changelog entry? (Add #no-changelog to the PR description to silence this warning.)

Generated by 🚫 Danger

@srushtisv srushtisv self-assigned this Jul 30, 2025
@srushtisv srushtisv requested a review from pashanka July 31, 2025 06:44
@srushtisv srushtisv marked this pull request as ready for review July 31, 2025 07:41
Copy link
Contributor

@pashanka pashanka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High level LGTM

requestConfiguration: requestConfiguration
)
let response = try await backend.call(with: request)
passkeyName = (name?.isEmpty ?? true) ? "Unnamed account (Apple)" : name!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use guard or if let construct here to prevent force unwrapping similar to how we did in StartPasskeyEnrollmentRequest?

Also nit: We should either do it in the top of the method as a input validation and assignment or just before we use it so that we can look at it's value where it is being used. In this particular case, I would lean in to do it in the beginning of the method as this is a class level variable.

Copy link
Contributor Author

@srushtisv srushtisv Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually force unwrapping is not neccesarily required here. we can safely remove it (also it wont go in that condition anyways, i added it just to be on the safe side). Removed force execution and used guard instead.
also Pavan, thanks for pointing that correctly but we are assigning the value just before we use it (in the just below registration request). I added it below the startEnrollment backend call because incase the backend call fails, we dont need to store the passkey name in that case.

)
let registrationRequest = provider.createCredentialRegistrationRequest(
challenge: challengeInData,
name: passkeyName ?? "Unnamed account (Apple)",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required? We are just setting passkeyName above with default value. Is there a case where passkeyName would still be not populated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out Pavan, removed the optional from here.

name: passkeyName ?? "Unnamed account (Apple)",
userID: userIdInData
)
return registrationRequest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel we can directly return from the previous statement, instead of storing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

requestConfiguration: requestConfiguration
)
let response = try await backend.call(with: request)
passkeyName = (name?.isEmpty ?? true) ? "Unnamed account (Apple)" : name!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should store "Unnamed account (Apple)" as a constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure Pavan, created a constant defaultPasskeyName to store this. refactored.

Comment on lines 44 to 77
func testInitWithMissingRpThrowsError() {
var dict = makeValidDictionary()
if var options = dict["credentialCreationOptions"] as? [String: Any] {
options.removeValue(forKey: "rp")
dict["credentialCreationOptions"] = options as? AnyHashable
}
XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict))
}

func testInitWithMissingRpIdThrowsError() {
var dict = makeValidDictionary()
if var options = dict["credentialCreationOptions"] as? [String: Any],
var rp = options["rp"] as? [String: Any] {
rp.removeValue(forKey: "id")
options["rp"] = rp
dict["credentialCreationOptions"] = options as? AnyHashable
}
XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict))
}

func testInitWithMissingUserThrowsError() {
var dict = makeValidDictionary()
if var options = dict["credentialCreationOptions"] as? [String: Any] {
options.removeValue(forKey: "user")
dict["credentialCreationOptions"] = options as? AnyHashable
}
XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict))
}

func testInitWithMissingUserIdThrowsError() {
var dict = makeValidDictionary()
if var options = dict["credentialCreationOptions"] as? [String: Any],
var user = options["user"] as? [String: Any] {
user.removeValue(forKey: "id")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional suggestion: Should we club all these test cases together and say testInitWithInvalid parameters and then loop them inside for each type of object as I see the testing as assertion part is same for all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve added a new test case in this file to validate all these parameters together and assert them collectively. (I had tried it earlier to make these tests more effficient but was encountering some errors so for now I added this extra case.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the tests as discussed.

options.removeValue(forKey: "challenge")
dict["credentialCreationOptions"] = options as? AnyHashable
}
XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also assert the error type to make sure code is not throwing error due to some other reason here? Similar for other testcases:
Something like below

XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict)) { error in
        XCTAssertEqual(error.code, "expected code  or message here")
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure Pavan, updated the tests to assert specific errors.

@srushtisv srushtisv requested a review from pashanka July 31, 2025 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants