-
Notifications
You must be signed in to change notification settings - Fork 82
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
feat: WebAuthN Sign In, Sign Up and Options methods support - NEW #952
feat: WebAuthN Sign In, Sign Up and Options methods support - NEW #952
Conversation
Deploying supertokens-node-pr-check-for-edge-function-compat with Cloudflare Pages
|
options: APIOptions; | ||
userContext: UserContext; | ||
} & ({ email: string } | { recoverAccountToken: string }) | ||
) => Promise< |
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.
How does webauthn flow work for native mobile apps?
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, through WebViews starting from iOS 16 and Android 9 (and 14 in some cases): https://passkeys.dev/docs/reference/android/ and https://passkeys.dev/docs/reference/ios/.
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.
done
lib/ts/recipe/webauthn/types.ts
Outdated
relyingPartyId: string; | ||
relyingPartyName: string; | ||
origin: string; | ||
userName: string; | ||
userDisplayName: string; | ||
email: string; | ||
timeout: string; | ||
attestation: string; | ||
challenge: string; |
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 did we remove relyingPartyName, userName, userDisplayName and attestation?
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 checked the schema and we don't store them in the generated options. userName
is the email and i renamed it to be more simple.
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 ideally, the output of registerOptions function should be similar to the output of this function. For example, in the registerOptions output, we have:
user: {
id: string;
name: string; // user email
displayName: string; //user email
};
Now in the output of getGeneratedOptions, it's totally different. So this is strange.
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.
Because we only store what is needed to verify the credentials. See the schema here (webauthn_user_generated_options
) https://docs.google.com/document/d/1G7tO9_dSNi8wur3ajGg4pq-wiHatKDbHv2sBt-uSbQg/edit?tab=t.0#heading=h.td4zxgo1675k
lib/ts/user.ts
Outdated
@@ -90,6 +92,9 @@ export class User implements UserType { | |||
id: string; | |||
userId: string; | |||
}[]; | |||
public readonly webauthn: { | |||
credentialIds: string[]; | |||
}[]; |
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 use webauthnCredentialId because there is no need to have a list of objects
@@ -192,10 +192,13 @@ export type AccountInfo = { | |||
id: string; | |||
userId: string; | |||
}; | |||
webauthn?: { | |||
credentialIds: string[]; |
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.
This is also used by listUsersByAccount info. We may have to split types, or are there any cases where we'd want to search by multiple credentialIds? How does that function, do we only get a match if all credentialIds are present? Is there a use-case for that?
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 haven't taken that into consideration. But as far as ai can tell, no. there is no use like that. There might the possibllity to search by one of the credentialIds. What do you think?
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 think searching by a single credentialId makes sense.
LINKING_TO_SESSION_USER_FAILED: { | ||
EMAIL_VERIFICATION_REQUIRED: | ||
"Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_013)", | ||
RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: | ||
"Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_014)", | ||
ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: | ||
"Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_015)", | ||
SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: | ||
"Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_016)", | ||
}, |
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 think the error codes will have to be updated. You can add a TODO here and wherever an update like this is pending.
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.
What should be the update? Or am i missing something ?
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.
well the error codes are login method specific, so we'll have to have new ones I think.
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.
done. added to do.
} | ||
|
||
const preAuthCheckRes = await AuthUtils.preAuthChecks({ | ||
authenticatingAccountInfo: { |
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.
shouldn't this have the credentialId? or is that something we only get later?
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 so. We are identifying the user by email. And since we are signing up, the credential isn't stored yet.
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 in no cases would this be relevant to this or other linking related functions? if so then the types may require some cleanup
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 check if we need to remove webauthn credential ids from the type - it is not used atm
const verifyCredentialsResponse = await options.recipeImplementation.verifyCredentials({ | ||
credential, | ||
webauthnGeneratedOptionsId, | ||
tenantId, | ||
userContext, | ||
}); | ||
const checkCredentialsOnTenant = async () => { | ||
return verifyCredentialsResponse.status === "OK"; | ||
}; |
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 correct? is credential validation independent of the tenant?
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.
Done.
Was doing it like this, because at the moment of implementation, we hadn't decided on having a method for retrieving the webauthGeneratedOptions
(which contained the email) and i had to retrieve the email before calling AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired
.
In the last few chats with Rishabh we deciede on adding the new method, but didn't update the API implmentation yet.
As a side note:
The credential can be shared across tenants and is not linked to a tenant.
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 see. So the point of checkCredentialsOnTenant
is to find out if the user can use the current set of credentials to log in on the given tenantId
(it can take it as a first parameter). This is tenant independent for pwless and thirdparty, but not for emailpassword for example.
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.
reverted to previous version because we don't need to check in the scope of the tenant.
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.
done
}; | ||
} | ||
|
||
const authenticatingUser = await AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired({ |
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.
this function also needs to be updated to take the new account info prop into account (plus I think you'll need to check all places where we use the account info)
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.
maybe we could have a chat about this.
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.
same as previous comments. also need to check method to see if ti works with webauthn
lib/ts/recipe/webauthn/types.ts
Outdated
} | ||
// | SignUpErrorResponse | ||
| { status: "EMAIL_ALREADY_EXISTS_ERROR" } | ||
| { status: "WRONG_CREDENTIALS_ERROR" } |
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.
This feels weird on a signUp
endpoint, maybe specify which param is wrong/how?
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 status is a generic one, for whatever error happens because of the Webauthn credentials flow. If we'd need to be more specific here (not in the API implementation - we should keep it generic there), then we'd need to do the actual core implementation, as there might lots of stuff that we can only find out when we start implementing.
There is another type of status "INVALID_AUTHENTICATOR_ERROR" (along with the reason) which means that the credential has been generated by an "unsupported" authenticator (this could happen by overriding the registerOptions method and overriding the default values for attestation
, requireResidentKey
, residentKey
, userVerification
, supportedAlgorithmIds
, etc.).
What do you think ?
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 INVALID_AUTHENTICATOR_ERROR
sounds good. My main issue with WRONG_CREDENTIALS_ERROR
is that it overlaps with the error status we have for people submitting wrong passwords I guess.
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.
same as previous error discussion
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.
done
ONLY REVIEW REQUIRED. NOTHING TESTED YET.
Summary of change
Implement WebAuthN support according to:
https://docs.google.com/document/d/1G7tO9_dSNi8wur3ajGg4pq-wiHatKDbHv2sBt-uSbQg/edit#heading=h.olee876uqu8a
Related
Check #942 for more feedback
Test Plan
No testing at the moment.
Documentation changes
Will have to add WebAuthN recipe documentation
Checklist for important updates
coreDriverInterfaceSupported.json
file has been updated (if needed)lib/ts/version.ts
frontendDriverInterfaceSupported.json
file has been updated (if needed)package.json
package-lock.json
lib/ts/version.ts
npm run build-pretty
recipe/thirdparty/providers/configUtils.ts
file,createProvider
function.git tag
) in the formatvX.Y.Z
, and then find the latest branch (git branch --all
) whoseX.Y
is greater than the latest released tag.add-ts-no-check.js
file to include thatsomeFunc: function () {..}
).exports
inpackage.json
Remaining TODOs for this PR