Please upgrade here. These earlier versions are no longer being updated and have security issues.

Enabling SSL in Vanilla 2?

derekdonderekdon New
edited January 2010 in Vanilla 2.0 - 2.8
Is there a setting for this? Had a quick look but I can't see one. What to secure the join and sign up process. Cheers.
«13456

Comments

  • Anyone? I really need to get this up and running in the next few hours. I have the cert. Typing https works a treat... anyway to make the EntryController change the connection to https?
  • Do you only want to secure the sign in process or the entire forum activity?
  • Hey Minisweeper,

    Preferably just the sign in and register processes. Any ideas?

    Derek.
  • MarkMark Vanilla Staff
    It gets tricky because we ajax the sign in form into pages where you don't want to have ssl. Because of that, the easiest thing to do is ssl the entire application. We don't have anything set up to just ssl the sign-in pages at the moment.
  • Hey Mark,

    Thanks for your speedy response and for letting me know. Is it possible to create a plugin for this purpose? Or is there no way this will work right now? Doesn't the class.dispatcher.php handle these requests?

    Derek.
  • If I enable SSL for the entire site the with something like this in my htaccess file...
    RewriteCond %{SERVER_PORT} 80
    RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]

    an unspecified error is returned when focusing out of the username form field during a new registration? when removed there's no more error but no SSL! Any idea?
  • derekdonderekdon New
    edited January 2010
    If I manually enter https://www.example.com/entry/register with the previous rewrite rules in the .htacess file removed, I still get the error when I attempt to focus out of the Name/Username field...

    A fatal error occurred while processing the request. The server returned the following response: error
  • think the problem is in the entry.js file!
  • Okay I got this working...

    Please note that this is using SSL for the entire app for the moment... and without these steps you'll have errors in your ajax forms when then check if the username already exists etc.

    My .htaccess file looks like this but it may be possible to simplify (no htaccess expert)


    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^example.com [NC]
    RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,NC,L]
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php/$1 [QSA,L]
    RewriteCond %{SERVER_PORT} 80
    RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]


    In your conf/config.php...

    $Configuration['Garden']['WebRoot'] = ''; // Mine is blank
    $Configuration['Garden']['RewriteUrls'] = TRUE; // Mine is TRUE
    $Configuration['Garden']['Domain'] = 'www.example.com/'; // Remove http:// reference
    $Configuration['Garden']['SSL'] = TRUE; // And add this line under the above

    In library/core/class.url.php update the Domain function to look like this...

    public static function Domain() {
    // Attempt to get the domain from the configuration array
    $Domain = Gdn::Config('Garden.Domain', '');
    $SSL = Gdn::Config('Garden.SSL', FALSE);

    if ($Domain === FALSE || $Domain == '')
    $Domain = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';

    if ($Domain != '' && $Domain !== FALSE) {
    if (substr($Domain, 0, 7) != 'http://')
    {
    (!$SSL) ? $Domain = 'http://'.$Domain : 'https://'.$Domain;
    }

    if (substr($Domain, -1, 1) != '/')
    $Domain = $Domain . '/';
    }
    return $Domain;
    }

    Now when you access your site you should be kicked into SSL and the forms should work as expected.

    Cheers.
  • Great work thanks for the tutorial. Looks like this might still need a bit of work in the back end then.
  • No problem... Yeah I think this can be tackled though with a plugin... might look at putting something together. Like to know if those .htaccess rules are as simple as they should be.
  • derekdonderekdon New
    edited January 2010
    I actually don't think having the SSL enabled for the entire application is a good idea from an SEO and performance perspective. Don't think a lot of spiders will crawl and index the site correctly if at all. @Mark now that I have the above working, and the ajax forms error free with SSL on, is there no way at all I could wire it up to just use SSL when the sign in and register are in use? Is it possibly for a controller "EntryController" to change the protocol to https? Or for the signin.php or registerbasic.php views to trigger this? Thanks.
  • MarkMark Vanilla Staff
    It's not possible right now, but it should be a part of the core product to do so. All it really takes is:

    1. We need some slick way of NOT popping the the sign-in form up in pages if SSL authentication is enabled.
    2. We need to use absolute urls (with https) when ssl auth is enabled.
    3. We need the entry controller to detect if it is on https and redirect back to itself on https if it is not (when ssl auth is enabled).

    Those are the steps necessary, and it really shouldn't be difficult to do. Does anyone want to take a stab at this?
  • @Mark
    Thanks Mark. I'm actually almost there with this. I've tried different methods of doing it all with mixed results. My latest attempt is long the lines of what you mentioned. I've had to modify the core a bit to make it work, but I've had enough success to know that it will work. I've done nothing that breaks the way things currently work, mainly just added an extra attribute or two to some of the functions in the following files.
    class.controller.php, functions.general.php, class.url.php
    May need some guidance on what you guys prefer and if and how I can bundle my changes into a plugin that overrides the core functions in question or if it's okay to edit them directly as I am. Once I finish I may look at how I can move them.

    In my version anyone can add an https link in a view by adding a sixth param that equals TRUE. Example:
    Anchor('Sign In', Gdn::Authenticator()->SignInUrl($this->_Sender->SelfUrl), 'Button', NULL, NULL, TRUE); // Had to remove the extra popup css class while testing
    Extra argument placement in functions.general...
    Anchor($Text, $Destination = '', $CssClass = '', $Attributes = '', $ForceAnchor = FALSE, $Secure = FALSE)

    This $Secure arg gets passed around until it reaches the class.url Domain method.

    public static function WebRoot($WithDomain = FALSE, $Secure = FALSE) {
    ....condensed....
    if (is_string($WebRoot) && $WebRoot != '') {
    // Strip forward slashes from the beginning of webroot
    return ($WithDomain ? Gdn_Url::Domain($Secure) : '') . preg_replace('/(^\/+)/', '', $WebRoot);
    } else {
    return $WithDomain ? Gdn_Url::Domain($Secure) : '';
    }
    }

    public static function Domain($Secure = FALSE) {
    // Attempt to get the domain from the configuration array
    $Domain = Gdn::Config('Garden.Domain', '');
    $SSLAvailable = Gdn::Config('Garden.SSL', FALSE);

    if ($Domain === FALSE || $Domain == '')
    $Domain = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';

    if ($Domain != '' && $Domain !== FALSE) {
    if ((substr($Domain, 0, 7) != 'http://') || (substr($Domain, 0, 8) != 'https://'))
    {
    $Domain = ($SSLAvailable && $Secure) ? 'https://'.$Domain : 'http://'.$Domain;
    }

    if (substr($Domain, -1, 1) != '/')
    $Domain = $Domain . '/';
    }
    return $Domain;
    }

    This is still available but I was thinking that the controller should be told to use SSL explicitly if available. I've added a...

    /**
    * A flag to use https if available.
    *
    * @var boolen
    */
    protected $_SecureController;

    to the base class.controller file.

    In the EntryController's initialize method I've...

    public function Initialize() {
    ....condensed....
    $this->AddCssFile('style.css');
    $this->MetaRobots('noindex,nofollow');
    $this->SecureController = TRUE;
    parent::Initialize();
    }

    then for in the same file...

    private function RegisterBasic() {
    if ($this->Form->IsPostBack() === TRUE) {
    ....condensed....
    }
    else
    {
    if(($this->SecureController) && (!$this->SentSSLRedirect)) // What can I check here?
    {
    $this->SentSSLRedirect = TRUE; // Remove this! Check other way, also needs reset
    Redirect($this->SelfUrl, TRUE); // Not right yet...
    }
    }
    $this->Render(); // Maybe I can hook before render later...
    }

    One thing that you may be able to help me with now is the redirection stuff... the rest I think I'll manage. Not the https aspect of it! Just what to check after a redirect back to the same controller method? count headers array?

    I'll have more questions soon...

    Work in progress...

  • @Mark

    I've started a plugin version of this. Having a problem calling the functions.general Redirect function from within the plugin. The Redirect doesn't exist in the controller, but in the controller file it looks like its called just as Redirect($URL). Do I need to import something in the plugin?

    public function Base_Render_Before(&$Sender)
    {
    ....condensed....
    $Sender->Redirect($Sender->SelfUrl, TRUE);
    ....condensed....
    }

    tried $this->Redirect($Sender->SelfUrl, TRUE);

    also fails... I know I'm missing something obvious!
  • Please ignore the last comment! Stupid!
    Redirect($Sender->SelfUrl, TRUE); // works thanks to the bootstrap file
  • Might it be easier to actually edit the core files rather than making a plugin? Then all your hard work can be integrated into the application release :)
  • lucluc ✭✭
    Indeed, that's definitely something that should work right out of the box, hence in the core.
  • derekdonderekdon New
    edited January 2010
    @Minisweeper
    I'm going to keep it as a plugin I think as it's a lot cleaner then rewriting core methods. The core developers can then review the changes the plugin contains and intergrate them if they like. The approach I'm currently using doesn't really make core changes and is clean and simple enough.

    @Mark
    Most of the stuff I mentioned before, core changes etc have been removed.
    My plugin defines a secure controllers array
    $Configuration['Garden']['WebRoot'] = '';
    $Configuration['Garden']['RewriteUrls'] = TRUE;
    $Configuration['Garden']['Domain'] = 'www.example.com/'; // Protocols here will be automatically removed
    $Configuration['Garden']['SSL'] = TRUE; // Override a system check
    $Configuration['Garden']['SecureControllers'] = 'arr:["entrycontroller"]'; // Specify the controllers you wish to secure

    This approach feels a lot cleaner.

    I can now move in an out of secure and unsecure controllers in my application regardless of the hrefs protocol. This works fine but when I log out I get "Failed to sign out of the application because of failed postback authentication" but I'm trying to sort that now.

    From the plugin can I override methods of the core? Or is this allowed? ie. methods in Gdn_Url. Can I override methods in functions.general just by defining them in the plugin?

    Cheers.
  • @Mark
    I assume its not possible to override a static function from a plugin?

    ie
    class Gdn_Url
    {
    public static function WebRoot($WithDomain = FALSE)

    ...with

    class SSLControllers implements Gdn_IPlugin
    {
    public function Gdn_Url_WebRoot_Override($WithDomain) // Written correctly?
    {
    return "test";
    }

    Cheers
Sign In or Register to comment.