-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Use Web MFA dialog for admin actions #50373
base: joerger/fix-useMfa-error-state
Are you sure you want to change the base?
Use Web MFA dialog for admin actions #50373
Conversation
18064df
to
aa5c0b7
Compare
235d2e1
to
cfe07e1
Compare
bf14661
to
4c3551c
Compare
5ee3d03
to
e103a1f
Compare
4c3551c
to
e77d074
Compare
Yeah, it might be nice to do some type of moving flow like we do for device management. e.g. edit user -> verify your identity in the same dialog, with option to continue (mfa challenge) or back (edit user page with error telling user mfa is required).
Thanks for pointing this out, the cancellation logic turned out to be pretty fragile and only worked well for per-session MFA with SSH sessions. I've fixed it so you should now see just one error at a time - 0149c12 Also, you should be able to retry or cancel in the mfa dialog. Let me know if you still get locked with my changes. |
@bl-nero take a look at this one when you get some time please |
cb74946
to
34fead1
Compare
* This is intended as a workaround for such cases, and should not be used | ||
* for methods with access to the React scope. Use useMfa directly instead. | ||
*/ | ||
export const MfaContextProvider = ({ children }: PropsWithChildren) => { |
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 this unset the mfaContext in auth/api on unmount? (I'm not sure if that matters)
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 not sure how unmounting in React works, how would I go about this?
setTimeout(() => { | ||
if (!mfaContext) | ||
throw new Error( | ||
'Failed to set up MFA prompt for admin action. This is a bug.' |
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 surface to the user? Should we be more helpful than "This is a bug"?
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.
Hm, looking at this again - this error doesn't go anywhere, as it's thrown within a setTimeout
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're right, for now I'll remove the timeout and just return a better error message:
Failed to set up MFA prompt for admin action. Please try refreshing the page to try again. If the issue persists, contact support as this is likely a bug.
const [mfaCtx, setMfaCtx] = useState<MfaContextValue>(); | ||
|
||
if (!mfaCtx) { | ||
const mfaCtx = { getMfaChallengeResponse }; | ||
setMfaCtx(mfaCtx); | ||
auth.setMfaContext(mfaCtx); | ||
api.setMfaContext(mfaCtx); | ||
} |
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.
Consider using an initializer function. It will save you a re-render and make the state more consistent.
const [mfaCtx, setMfaCtx] = useState<MfaContextValue>(); | |
if (!mfaCtx) { | |
const mfaCtx = { getMfaChallengeResponse }; | |
setMfaCtx(mfaCtx); | |
auth.setMfaContext(mfaCtx); | |
api.setMfaContext(mfaCtx); | |
} | |
const [mfaCtx, setMfaCtx] = useState<MfaContextValue>(()=> { | |
const mfaCtx = { getMfaChallengeResponse }; | |
auth.setMfaContext(mfaCtx); | |
api.setMfaContext(mfaCtx); | |
return mfaCtx; | |
}); |
// Since this is a global object outside of the react scope, there is a marginal | ||
// chance for a race condition here (the react scope should generally be initialized | ||
// before this has a chance of being called). This conditional is not expected to | ||
// be hit, but will catch any major issues that could arise from this solution. |
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.
Hmm. This is quite a hack. The fact that auth service started to depend on an MFA context that is injected on the top level by context provider makes me think that it should be turned into a class (just like the MFA service) that is instantiated by TeleportContext
. This would allow establishing a link to the MFA service/context/whatever when constructing the auth service. Will it be a big refactoring?
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.
It does sound like a big refactor to me, but I'm not really in a position with my level of typescript/React experience to judge or carry out this type of refactor. I also have some other important work to move onto. Do you think it's something we can live with today and fix tomorrow, or do we need to scrap this approach for now?
Note that without this change, we still support SSO MFA for admin actions, we just don't provide the user with the choice between SSO MFA and Webauthn when applicable. Instead we automatically open the Webauthn or SSO MFA pop up without a dialog, which may be jarring, but not the end of the world. In the long term we should find a solution.
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.
@Joerger I think that given above, it would be best to continue with the PR as is, and treat this part as a technical debt that we take to improve UX. Can you please create a tracking issue for this refactoring?
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.
34fead1
to
ebade41
Compare
ebade41
to
b5581df
Compare
7f9a2a2
to
9db6d2b
Compare
Changelog: Add MFA dialog in the WebUI for Admin actions instead of automatically opening up a webauthn/sso pop up.
Adds a global MFA context for prompting MFA from non-react contexts. Currently this is only used for admin actions, which prompts for MFA from basic API requests.
Depends on #49794