JSON API does not support TFA (Multi Factor)?..

82 views
Skip to first unread message

Dennis O'Connell

unread,
Nov 21, 2021, 5:06:41ā€ÆAM11/21/21
to Rodauth
Hi,

I have created an user and also setup OTP. When I logout and login back via Browser (HTML) after I enter my password, system asks me TFA Code. Good.

However, When JSON API request made using username and password, I just get log in :(

Does JSON supportĀ  TFA auths? If so why am i not asked for TFA. If not how can I simply enable or replicate this behavior just like in HTML Views?

P.S.: I've also enabled JWT-related plugins.

Thanks,
-Den

Jeremy Evans

unread,
Nov 21, 2021, 3:12:36ā€ÆPM11/21/21
to rod...@googlegroups.com
On Sun, Nov 21, 2021 at 2:06 AM Dennis O'Connell <denniso...@gmail.com> wrote:
Hi,

I have created an user and also setup OTP. When I logout and login back via Browser (HTML) after I enter my password, system asks me TFA Code. Good.

However, When JSON API request made using username and password, I just get log in :(Ā 
Does JSON supportĀ  TFA auths? If so why am i not asked for TFA. If not how can I simply enable or replicate this behavior just like in HTML Views?

The JSON API in Rodauth is handled almost exactly the same as regular HTML, by design.Ā  The only difference is JSON doesn't not automatically redirect., you need to have your front-end submit the request to the otp_auth route after logging in.Ā  Ā If you are logging into an TFA-enabled account via JSON, after login, you are considered logged in, but you are not considered fully authenticated (rodauth.authenticated? returns false).Ā  This is the same behavior after HTML view login, if you try to navigate away after logging in but before submitting the OTP code.

Thanks,
Jeremy

Dennis O'Connell

unread,
Nov 22, 2021, 12:19:47ā€ÆAM11/22/21
to Rodauth
Hi Jeremy,

Now this makes sense. However, the thing that confuses me was that there was no any message or code that asks me to send request to TFA.

After user successfully logged in, how do I know if TFA required or not? Is there any api endpoint to check this? Because response just says "user logged in".

Thanks,
-Den.

Jeremy Evans

unread,
Nov 22, 2021, 11:06:41ā€ÆAM11/22/21
to rod...@googlegroups.com
On Sun, Nov 21, 2021 at 9:19 PM Dennis O'Connell <denniso...@gmail.com> wrote:
Hi Jeremy,

Now this makes sense. However, the thing that confuses me was that there was no any message or code that asks me to send request to TFA.

After user successfully logged in, how do I know if TFA required or not? Is there any api endpoint to check this? Because response just says "user logged in".

Currently, I don't think there is one.Ā  It's not hard to add yourself using rodauth.possible_authentication_methods, but I think it's reasonable to expect that Rodauth would have such an endpoint.Ā  I'll add that today.

Thanks,
Jeremy

Dennis O'Connell

unread,
Nov 22, 2021, 11:43:59ā€ÆAM11/22/21
to Rodauth
Hi Jeremy,

I'll be (and many users im sure) very happy to have such feature. Thank you for your quick reply and solution. šŸ‘ Because I tend to rely on full JSON API instead of implementing my own auth flow. It will be much more easier for many users including me to check extra endpoint if extra verification is needed or not. (Perhaps what will be needed can be added as a response such as TFA/SMS etc.. first)

-Den.

Jeremy Evans

unread,
Nov 22, 2021, 11:49:57ā€ÆAM11/22/21
to rod...@googlegroups.com
On Mon, Nov 22, 2021 at 8:44 AM Dennis O'Connell <denniso...@gmail.com> wrote:
Hi Jeremy,

I'll be (and many users im sure) very happy to have such feature. Thank you for your quick reply and solution. šŸ‘ Because I tend to rely on full JSON API instead of implementing my own auth flow. It will be much more easier for many users including me to check extra endpoint if extra verification is needed or not. (Perhaps what will be needed can be added as a response such as TFA/SMS etc.. first)

I'm going to implement the support by allowing JSON requests to the multifactor-auth and multifactor-manage routes.Ā  These will return links to endpoints for supported multifactor authentication or setup/disable.Ā  This mirrors the authentication flow that the HTML interface uses.

Thanks,
JeremyĀ 

Jeremy Evans

unread,
Nov 22, 2021, 12:03:13ā€ÆPM11/22/21
to rod...@googlegroups.com

Dennis O'Connell

unread,
Nov 22, 2021, 12:06:21ā€ÆPM11/22/21
to Rodauth
Hi Jeremy!,

WOW! Thank you so much. That was faster than I can imagine!

I'll test the endpoints on my end using `master` branch ASAP. And hope you can release a new version soon for this.

Jeremy Evans

unread,
Nov 22, 2021, 12:09:49ā€ÆPM11/22/21
to rod...@googlegroups.com
On Mon, Nov 22, 2021 at 9:06 AM Dennis O'Connell <denniso...@gmail.com> wrote:
Hi Jeremy!,

WOW! Thank you so much. That was faster than I can imagine!

I'll test the endpoints on my end using `master` branch ASAP. And hope you can release a new version soon for this.

I was thinking about a release tomorrow, so if you can get the master branch tested today and provide feedback as to whether this works for you, that would be great.

Thanks,
Jeremy

Dennis O'Connell

unread,
Nov 22, 2021, 12:32:43ā€ÆPM11/22/21
to Rodauth
Hi Jeremy,

Here are the results. After /login as usual:

Endpoint: /multifactor-manage
Response: 401 - You need to authenticate via an additional factor before continuing
SNAG-0568.jpg

Endpoint
: /multifactor-auth
Response: 200 - Links: ["/auth/api/v1/otp-auth"]
SNAG-0570.jpg

So, The rest is to visit that OTP link and request a code from client as expected.

What if user does not have OTP/SMS?

Endpoint: /multifactor-manage
Response:Ā 200Ā - /otp-setup link given...
SNAG-0571.jpg

Endpoint
: /multifactor-auth
Response:Ā 403Ā -Ā This account has not been setup for multifactor authentication
SNAG-0572.jpg

Is there any other endpoint should I test?

Thanks,
-Den.

Dennis O'Connell

unread,
Nov 22, 2021, 12:36:02ā€ÆPM11/22/21
to Rodauth
Hi Jeremy,

One more thing. Should we have something like this? Or would this break the standards?

Current response:

{
Ā  Ā  "access_token": "ACCESS_TOKEN_HERE",
Ā  Ā  "refresh_token": "REFRESH_TOKEN_HERE",
Ā  Ā  "success": "You have been logged in"
}

Suggestion:

{
Ā  Ā  "access_token": "ACCESS_TOKEN_HERE",
Ā  Ā  "refresh_token": "REFRESH_TOKEN_HERE",
Ā  Ā  "success": "You have been logged in",
Ā  Ā  "mfa": true # <-- here. or false if no multifactor required...
}


My previous email contains test results.

Thanks,
-Den.

Jeremy Evans

unread,
Nov 22, 2021, 12:45:38ā€ÆPM11/22/21
to rod...@googlegroups.com
On Mon, Nov 22, 2021 at 9:32 AM Dennis O'Connell <denniso...@gmail.com> wrote:
Hi Jeremy,

Here are the results. After /login as usual:

Endpoint: /multifactor-manage
Response: 401 - You need to authenticate via an additional factor before continuing
SNAG-0568.jpg


This is expected.Ā  If you have already setup multifactor authentication, you need to be multifactor authenticated before you can manage your multifactor authentication.Ā  After all, we don't want someone only single factor authenticated to remove multifactor authentication.
Ā 
Endpoint: /multifactor-auth
Response: 200 - Links: ["/auth/api/v1/otp-auth"]
SNAG-0570.jpg

So, The rest is to visit that OTP link and request a code from client as expected.

Correct.
Ā 
What if user does not have OTP/SMS?

I guess you mean what if the user has not setup multifactor authentication?
Ā 
Endpoint: /multifactor-manage
Response:Ā 200Ā - /otp-setup link given...
SNAG-0571.jpg

This is expected.Ā  As multifactor authentication has not been setup, the user is fully authenticated after logging in, so the multifactor setup links are shown.
Ā 
Endpoint: /multifactor-auth
Response:Ā 403Ā -Ā This account has not been setup for multifactor authentication
SNAG-0572.jpg

This is expected as the user has not setup multifactor authentication.
Ā 
Is there any other endpoint should I test?

No, those are the only two added.

Auth flow should be easy to handle.Ā  After login, submit JSON request to multifactor-auth.Ā  If 403 is returned, user is likely already fully authenticated.Ā  If 200 is returned, you can use the auth_links to go to the next step in the flow.Ā  Will that work for you?

Thanks,
Jeremy

Jeremy Evans

unread,
Nov 22, 2021, 12:50:13ā€ÆPM11/22/21
to rod...@googlegroups.com
On Mon, Nov 22, 2021 at 9:36 AM Dennis O'Connell <denniso...@gmail.com> wrote:
Hi Jeremy,

One more thing. Should we have something like this? Or would this break the standards?

Current response:

{
Ā  Ā  "access_token": "ACCESS_TOKEN_HERE",
Ā  Ā  "refresh_token": "REFRESH_TOKEN_HERE",
Ā  Ā  "success": "You have been logged in"
}

Suggestion:

{
Ā  Ā  "access_token": "ACCESS_TOKEN_HERE",
Ā  Ā  "refresh_token": "REFRESH_TOKEN_HERE",
Ā  Ā  "success": "You have been logged in",
Ā  Ā  "mfa": true # <-- here. or false if no multifactor required...
}

I don't want to add this, as I don't think it contains enough information to be useful in the general case.Ā  The current approach offers more information and better mirrors in the JSON interface what happens in the HTML interface, and Rodauth tries to make the interfaces the same as much as possible. However, you can certainly implement this yourself using after_login.

Thanks,
Jeremy

Dennis O'Connell

unread,
Nov 22, 2021, 1:08:15ā€ÆPM11/22/21
to Rodauth
>> Auth flow should be easy to handle.Ā  After login, submit JSON request to multifactor-auth.Ā  If 403 is returned, user is likely already fully authenticated.Ā  If 200 is returned, you can use the auth_links to go to the next step in the flow.Ā  Will that work for you?

Absolutely. As soon as I get 403, job is done. Otherwise I'll do all necessary steps on the client side. Of course, If you have a better idea other than this, I'd like to hear it as well. But so far so good and more than enough.

>> I don't want to add this, as I don't think it contains enough information to be useful in the general case.Ā  The current approach offers more information and better mirrors in the JSON interface what happens in the HTML interface, and Rodauth tries to make the interfaces the same as much as possible. However, you can certainly implement this yourself using after_login.

That is the point actually. If we have `mfa` is true, then we have to go those new endpoints and check the required authentication methods. If `mfa` is false then no action is required therefore no second API request can be sacrificed (response time will be lower). Much faster :) But of course, you know this better then me, so, it is your decision in the end.

As I said, first one will work for me. Second suggestion is there to save another request being sent to server. true for another request, false for OK.

Thank you so much for your replies and implementations, Jeremy. ā¤ļø

Thanks,
-Den.


Dennis O'Connell

unread,
Nov 22, 2021, 1:10:23ā€ÆPM11/22/21
to Rodauth
Ah, About ` after_login`, can you give me a little example? How can I append this information into existing response?

Thanks,
-Den.

Jeremy Evans

unread,
Nov 22, 2021, 1:16:17ā€ÆPM11/22/21
to rod...@googlegroups.com
On Mon, Nov 22, 2021 at 10:08 AM Dennis O'Connell <denniso...@gmail.com> wrote:
>> Auth flow should be easy to handle.Ā  After login, submit JSON request to multifactor-auth.Ā  If 403 is returned, user is likely already fully authenticated.Ā  If 200 is returned, you can use the auth_links to go to the next step in the flow.Ā  Will that work for you?

Absolutely. As soon as I get 403, job is done. Otherwise I'll do all necessary steps on the client side. Of course, If you have a better idea other than this, I'd like to hear it as well. But so far so good and more than enough.

Nope, that's basically the same idea I had.
Ā 

>> I don't want to add this, as I don't think it contains enough information to be useful in the general case.Ā  The current approach offers more information and better mirrors in the JSON interface what happens in the HTML interface, and Rodauth tries to make the interfaces the same as much as possible. However, you can certainly implement this yourself using after_login.

That is the point actually. If we have `mfa` is true, then we have to go those new endpoints and check the required authentication methods. If `mfa` is false then no action is required therefore no second API request can be sacrificed (response time will be lower). Much faster :) But of course, you know this better then me, so, it is your decision in the end.

I can see how it makes things slightly faster.Ā  Not sure how it would make things much faster.Ā  The request to login should take much longer than the request to check for multifactor authentication due to checking the bcrypt password hash (or whatever you are doing to authenticate).
Ā 
As I said, first one will work for me. Second suggestion is there to save another request being sent to server. true for another request, false for OK.

In terms of implementing the after_login, maybe something like this (untested):

after_login do
Ā  json_response['mfa'] = !authenticated? if use_json?
end

Thanks,
Jeremy

Dennis O'Connell

unread,
Nov 22, 2021, 1:20:22ā€ÆPM11/22/21
to Rodauth
>> I can see how it makes things slightly faster.Ā  Not sure how it would make things much faster.Ā  The request to login should take much longer than the request to check for multifactor authentication due to checking the bcrypt password hash (or whatever you are doing to authenticate).

Good point, actually :=). Not much, but slightly. I think I will go with current approach. (But will save your example as a reference for later maybe for another usage)

Thank you so much!,
-Den.

Reply all
Reply to author
Forward
0 new messages