-
Notifications
You must be signed in to change notification settings - Fork 136
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
Change registration on API v2 to flow with 3 steps #2629
Conversation
The registration for new identities using API v2 is now split into 3 different steps: 1. start a flow, providing a principal to track progress on that flow 2. solve captcha 3. submit authn_method to tie the identity to This PR is a preparation to making the step 2 dynamically remove step 2 on low load.
const FLOW_EXPIRATION_NS: u64 = 5 * MINUTE_NS; | ||
|
||
#[derive(Default)] | ||
pub struct FlowStates { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lmuntaner: Ultimately, I decided against mixing flow states with temp_keys. I feel this is cleaner in terms of separation.
But it means that the "expiration logic" here and temp_keys is duplicated. I don't think it is big enough to warrant extracting that, but up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So now the temp keys won't be used to track the registration flow, right?
Do we need the enum for the TempKeyId still?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I will revert #2618. I'll do that after this is merged.
/// * Once the flow expires | ||
/// * The Internet Identity canister is upgraded | ||
/// | ||
/// The total number of flow states is limited by the registration rate limit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the captcha is now tied to the flow_state and the number of flow_states is limited by the registration rate limit, the max_unsolved_captchas
config option in the captcha config only has an effect on the legacy registration flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't that depend on what comes furst, the registration rate limit or the max_unsolved_captchas
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, max_unsolved_captchas
is not used at all in the context of the V2 registration flow, as we store the captcha with the flow state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy because after our conversation I was able to follow this PR pretty well. Thanks!
Minor comments, already approving.
@@ -955,8 +955,23 @@ jobs: | |||
steps: | |||
- uses: actions/checkout@v4 | |||
- uses: ./.github/actions/setup-didc | |||
- name: 'Get latest release' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this needs to be done every time we introduce a breaking change?
Do you have a script or how do you remember how to do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I usually pull it out again from git history whenever I need it. My hope was that it would not be worth it improving the infrastructure to do that, as we would eventually stop making breaking changes (as APIv2 would be finished)...
@@ -532,6 +521,72 @@ type SignedIdAlias = record { | |||
id_dapp : principal; | |||
}; | |||
|
|||
type IdRegNextStepResult = record { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not IdRegStartResult
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reuse this result for _start
and check_captcha
. It is essentially a result to indicate a step has been completed correctly and what the next step is.
So if there are more / different steps in the flow in the future, they can also use this.
}) | ||
} | ||
|
||
async fn captcha_flow_state(flow_created_timestamp_ns: u64) -> (Base64, RegistrationFlowState) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will you add that this returns Option<Base64>
afterwards?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean, once the captcha might be skipped? No, I think I will identity_registration_start
with some logic to decide whether this function should be called or if the next step is Finish
.
src/internet_identity/src/anchor_management/registration/registration_flow_v2.rs
Outdated
Show resolved
Hide resolved
} | ||
|
||
fn create_identity(arg: &IdRegFinishArg) -> Result<IdentityNumber, IdRegFinishError> { | ||
let Some(mut identity) = state::storage_borrow_mut(|s| s.allocate_anchor()) else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a thing we will need to change to allow creating the identity number at the beginning of the flow instead of the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there will definitely be changes here. But there need to be many more. Maybe its best we have a separate discussion about it.
/// * Once the flow expires | ||
/// * The Internet Identity canister is upgraded | ||
/// | ||
/// The total number of flow states is limited by the registration rate limit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't that depend on what comes furst, the registration rate limit or the max_unsolved_captchas
?
self.registration_flows.remove(principal); | ||
} | ||
|
||
pub fn registration_flow_state(&self, principal: &Principal) -> Option<RegistrationFlowState> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also prune here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is necessary, as we explicitly check expiration
before returning anything.
IMHO it is more natural to prune alongside other modifications, rather than on read.
@@ -37,6 +38,40 @@ fn should_register_multiple_identities() { | |||
assert_ne!(identity_number_1, identity_number_2); | |||
} | |||
|
|||
#[test] | |||
fn should_transition_flow_principal_to_temp_key() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this name for this test?
It's to make sure that the temp_key is expired after the required time, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test is there for two things:
- the principal used in the flow can still be used after the registration (e.g. to add additional devices / get a delegation, etc.)
- the principal used in the flow expires after the expected amount of time
The registration for new identities using API v2 is now split into 3 different steps:
This PR is a preparation to making the step 2 dynamically remove step 2 on low load.