1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

1.5: Documentation for two step authentication?

Discussion in 'XenForo Development Discussions' started by rugk, Aug 7, 2015.

  1. rugk

    rugk Active Member

    Mike said in his post about the new 2FA in XenForo:
    Are there any more details about this? Or will there be?
    I mean is there any documentation or example implementation of this? Or is planned that there will be one released?

    Are there any special APIs at all?
     
  2. Chris D

    Chris D XenForo Developer Staff Member

    To add new providers to the 2FA system is pretty much no different from how we have added the default ones.

    An entry needs to be added to the provider database table, and a class needs to be created which extends XenForo_Tfa_AbstractProvider. Aside from that, some templates and phrases will be required for the user interface.

    It's unlikely we will write any specific documentation for it though I'm certain that if you have any questions, ask them in this forum and they'll get answered.

    Good luck!
     
    Valhalla and rugk like this.
  3. rugk

    rugk Active Member

    Okay, anyway thanks for fast answer and the tips.
    I will have a look on it.
     
  4. rugk

    rugk Active Member

    Okay, I have a question:
    Is there any way to execute code when the add-on is disabled/enabled? And I know, this was asked before, but has something changed since 2012?

    The issue is just: If you have an 2FA add-on installed and disable it I'm quite sure you want to disable the 2FA. (Well... I would highly assume this. :)) But since you cannot get any code to work when disabling (AFAIK) you can't modify the 2FA provider database and so you can't disable it there.
    Finally the add-on just stays enabled. And that's obviously not what the user expects when he disables an add-on.
     
    Last edited: Aug 11, 2015
  5. Chris D

    Chris D XenForo Developer Staff Member

    It's actually probably possible to run a bit of code on disable.

    It would require extending the _postSave() function of the AddOn DataWriter. Have your code execute before the parent code executes (checking for the add-on ID, the active state, etc.). There's also the AddOn Model and rebuildAddOnCachesAfterActiveSwitch().

    Actually the big problem is reverting that when the add-on is re-enabled. When the code I mentioned above is run, technically the add-on is still disabled so extending the code above won't work for the enable case. That's maybe where the idea of a Cron entry comes in. If it ran every minute (it would only run when the add-on is enabled) then you could get it to check that the providers are enabled, and enable them if they're not.
     
  6. rugk

    rugk Active Member

    Okay, sounds difficult and more like a workaround...

    And about:
    If it runs every minute when the add-on is enabled it also runs every minute after the provider is enabled.
    And I don't want to query the database every minute just to check whether the provider is actually enabled.

    Okay, it would be possible if the cron entry is just disabled/deleted after itself 'corrected' the providers entry. And it would have to be readded/activated if the add-on disables. :unsure:
     
  7. James

    James Well-Known Member

    Would it not be possible to enable the cron entry on postSave so when the addon is disabled the cron is enabled.

    Then, in the cron, you can possibly disable the cron from inside the cron? So it runs the required code then disables itself so it doesn't run until the addon is disabled and the cron is re-enable on postSave?

    (this is all theoretical I've not seen the code)
     
  8. rugk

    rugk Active Member

    Yes that's what I thought too:
    So theoretically I think it should be possible.
    But it's still a heavy workaround. But well... if there is no other method.
    It's just that this workaround has to be in place for all 2FA add-ons as they all have the same problem.
     
  9. rugk

    rugk Active Member

    So the code for generating a random 6-digits number I found in your implementation is this one:
    PHP:
    $length 6;

    $random XenForo_Application::generateRandomString(4true);
    $code = (
        ((
    ord($random[0]) & 0x7f) << 24) |
       ((
    ord($random[1]) & 0xff) << 16) |
      ((
    ord($random[2]) & 0xff) << 8) |
      (
    ord($random[3]) & 0xff)
    ) % 
    pow(10$length);
    $code str_pad($code$length'0'STR_PAD_LEFT);
    I have to admit that I don't really know what you do and bitshift there, but as it seems to work quite good and such codes may be used in many 2FA methods I would like to ask whether I could use this code snipped in my add-on too. Note that I may publish it under an open source license.
     
  10. Mike

    Mike XenForo Developer Staff Member

    Well that code depends on an XF library function, but all you're seeing is how to turn a bit stream into an integer.
     
  11. rugk

    rugk Active Member

    Yes of course. I'm not going to publish the XenForo libaries.

    Okay, thanks for the info, so it's nothing special and I can publish this piece of code. Thanks. :)
     
  12. rugk

    rugk Active Member

    Another question: There are requiresSetup and renderSetup in the abstract class. But as it is not used in any of the included 2FA methods I have no example code for implementing.
    I've tried to create an template with $view->createTemplateObject in renderSetup (requiresSetup obviously returns true). However when accessing the site (enabling the 2FA provider) it only shows me a blank site. I got out that XenForo does not even execute renderSetup at all. (requiresSetup is executed)

    So when looking in the XenForo code I saw that it all seems to go well until line 1204 in XenForo_ControllerPublic_Account. There I don't understand how it can call the class XenForo_ViewPublic_Account_TwoStepSetup - there is no file TwoStepSetup.php in the Account directory.
     
    Last edited: Jan 24, 2016
  13. rugk

    rugk Active Member

    Does anybody have an idea?
     
  14. Brogan

    Brogan XenForo Moderator Staff Member

    The view class doesn't actually have to exist as a PHP file.
     
  15. rugk

    rugk Active Member

    That's not mentioned in https://xenforo.com/community/resources/understanding-the-xenforo-class-proxy-system.2080/...
    Okay, so where does it load XenForo_ViewPublic_Account_TwoStepSetup? Respectively in what file is this class?

    BTW "view class and" what?

    And what about the original issue that renderSetup is not called at all?

    BTW I'm using XF 1.5.2 so maybe a newer version contains some fixes. May this be an issue?
     
  16. Chris D

    Chris D XenForo Developer Staff Member

    You're right. These methods aren't actually implemented properly - they weren't needed and were just not used. Realistically, you'd probably be best to pretend they don't exist. At best, you might be able to piggy back the code here to do what you need to do.

    This is common within XF, as Brogan explains. View classes (the first argument of renderView()) don't actually need to exist (but theoretically you would be able to extend that non-existing class if required), so there's nothing really to see there. Part of what I was saying above is actually the "account_two_step_setup" template doesn't exist either so effectively this code here has no use at all.

    You would be able to theoretically inject some behaviours here, but in a slightly more convoluted way than the code would lead you to believe.

    For example, you could extend that controller action, e.g.
    PHP:
    public function actionTwoStepEnable()
    {
        
    $parent parent::actionTwoStepEnable();

        if (
    $parent instanceof XenForo_ControllerResponse_View)
        {
            
    // At this point, we should already be at the "TwoStepSetup" stage
            // You should get your provider here, and do the necessary steps to ensure it is valid and check it is your provider...

            
    if ($provider->provider_id == 'YourProviderId')
            {
                
    // Do whatever you need to do here to get your provider set up
            
    }
        }

        return 
    $parent;
    }
    That needs fleshing out a bit, but hopefully you get the idea.
     
    rugk likes this.
  17. rugk

    rugk Active Member

    :cry:
    That's why we need a developer documentation. Okay at least a comment in the abstract class would have been enough to know that it is not completely implemented. I tried to find the error since yesterday and now I hear that it's just not completely implemented in XenForo...
    And about "they weren't needed and were just not used": As you see other 2FA providers possibly need.

    Thanks for the description and code example. Just as a theoretically question: Can't I also override these non-existent classes (in this case XenForo_ViewPublic_Account_TwoStepSetup) and put the code there? There I would not need all these checks.

    Back to this example:
    So when I confirmed that the provider is mine, how can I output a template then? I assume I somehow have to add it to $parent, but $parent already seems to be a finished view (it is not even an instance of XenForo_View), so how can I do that?
     
  18. Chris D

    Chris D XenForo Developer Staff Member

    Yes, that is another option though there are considerations there in case other add-ons want to extend the same thing.

    You can just return your own response view, e.g.
    PHP:
    public function actionTwoStepEnable()
    {
        
    $parent parent::actionTwoStepEnable();

        if (
    $parent instanceof XenForo_ControllerResponse_View)
        {
            
    // At this point, we should already be at the "TwoStepSetup" stage
            // You should get your provider here, and do the necessary steps to ensure it is valid and check it is your provider...

            
    if ($provider->provider_id == 'YourProviderId')
            {
                    
    // Do whatever you need to do here to get your provider set up
                    
    $viewParams = array();
                    return 
    $this->responseView('YourAddOn_Blah_Blah''youraddon_template_blah_blah'$viewParams);
            }
        }

        return 
    $parent;
    }
     
    rugk likes this.
  19. rugk

    rugk Active Member

    I begin to doubt that this (using the "setup" part) is a good way to implement it.
    So a more general question: The current 2FA methods all trigger the verification already when you set them up. Before the user even sees the setup. Only the setup is done before, but if you use the setup it does not redirect to the handleManage any more, but just to the main site.
    What I want to have is basically both modes together. So when the provider is enabled the user is at first presented with some options which need to be set before the provider is triggered. These options are similar or even the same which may be showed later when the user "manages" the provider.
    So after he put all the details into this he can submit it and the verification is triggered. Afterwards the user should just pass the verification (so renderVerification and verifyFromInput after submitting the input) like it is already done with all verification modes. Only if these two steps are done the provider should be enabled.

    So I thought the setup section would be a thing where I can do the first thing, but I'm not sure whether I could not reuse the management a bit better.
    Basically I just want 3 steps for enabling a provider instead of two. So what's the best way to do this?
     
  20. rugk

    rugk Active Member

    I'd like to add another thing you should be aware when creating an 2FA add-on: The templates for the normal user login (2FA verification) and the administrative login (2FA verification) when logging into the ACP are two different ones: So you almost certainly have to create your "two_step_..." template two times (with the same name): One time as a normal template and one as an admin template, otherwise your ACP 2FA login page may show nothing.
     

Share This Page