Replies: 2 comments
-
I would also love to hear about an idea for such a workflow. I mean... i can build "something" Variant A) - not using OTP for the login at all, but capture the user after having a valid session in a completely new page where the OTP has to get entered until i "grant" the session valid. The drawback is that there is an already active session, while actually there should be none. I kind of keep the user trapped until the OTP is provided. Variant B) - "hijacking" the sessions controller with a before filter - checking whether OTP was NOT send along, using devises internals to "pre-verify" whether email and password on their own fit and then (B-1) if OTP is not required log-in fully, or (b-2) redirect back to the login page and "loop" email and password through the frontend again, but this time showing the OTP field. Drawback: I code some sort of preflight via before actions, which feels like duplicating the code. Like @eimantas said "Accepting failure from two_factor_authenticable as a sign to show OTP attempt input seems like a hack/workaround to me." it actually is a hack - think of the interplay with locking on failed attempts. I don't want to increase the failed attempts, but simply rerender the :new form with a field for the OTP. If someone has a working solution i'd love to hear about it or discuss some pros/cons here. |
Beta Was this translation helpful? Give feedback.
-
Hey @ans-ioki, thanks for the reply! I dabbled a bit and here is my sessions' def create
user = User.where(email: params[:user][:email]).first
if user != nil && params[:user][:otp_attempt].blank? && user.otp_required_for_login
respond_to do |format|
format.turbo_stream
end
else
super
end
end We basically respond with an otp form through turbo stream (and update the UI w/ Stimulus controller) if we found a user, the otp attempt is needed and is blank. Otherwise just forward everything to a standard devise controller. And this is a basic stimulus sessions controller: export default class extends Controller {
static targets = ['credentials']
connect() {
this.element.addEventListener('turbo:submit-end', (event) => {
if (event.target.id === 'new_user') {
this.credentialsTarget.classList.add('hidden')
}
})
}
} The UI is basic:
Now when |
Beta Was this translation helpful? Give feedback.
-
I found the demo app very simple and it basically very well distils how this gem should be used:
a) when user has OTP turned on, then strategy authenticates against DB and then attempts to verify OTP
b) when user has no OTP it returns true
From the backend perspective all seems fine. I am trying to create a UI for this where users first enter the username/password pair and only if OTP is needed, are they shown the OTP attempt field.
This makes me wonder if I can distinguish during the authentication if OTP is needed before failing the authentication using 2FA strategy? Accepting failure from
two_factor_authenticable
as a sign to show OTP attempt input seems like a hack/workaround to me.For now I'm thinking of generating devise session controller, adding check in
create
method and performing some response to show the OTP input. What are your thoughts?Beta Was this translation helpful? Give feedback.
All reactions