Simple user-authentication solution, embedded into a small framework.

Overview

HUGE, formerly "php-login" logo

HUGE

Scrutinizer Code Quality Code Climate Codacy Badge Travis CI Dependency Status Support

Just a simple user authentication solution inside a super-simple framework skeleton that works out-of-the-box (and comes with an auto-installer), using the future-proof official bcrypt password hashing/salting implementation of PHP 5.5+, plus some nice features that will speed up the time from idea to first usable prototype application dramatically. Nothing more. This project has its focus on hardcore simplicity. Everything is as simple as possible, made for smaller projects, typical agency work and quick drafts. If you want to build massive corporate applications with all the features modern frameworks have, then have a look at Laravel, Symfony or Yii, but if you just want to quickly create something that just works, then this script might be interesting for you.

HUGE's simple-as-possible architecture was inspired by several conference talks, slides and articles about huge applications that - surprisingly and intentionally - go back to the basics of programming, using procedural programming, static classes, extremely simple constructs, not-totally-DRY code etc. while keeping the code extremely readable (StackOverflow, Wikipedia, SoundCloud).

Some interesting Buzzwords in this context: KISS, YAGNI, Feature Creep, Minimum viable product.

HUGE has reached "soft End Of Life"

To keep this project stable, secure, clean and minimal I've decided to reduce the development of HUGE to a minimum. Don't worry, this is actually a good thing: New features usually mean new bugs, lots of testing, fixes, incompatibilities, and for some people even hardcore update stress. As HUGE is a security-critical script new features are not as important as a stable and secure core, this is why people use it. This means:

  • HUGE will not get new features
  • but will be maintained, so it will get bugfixes, corrections etc for sure, maybe for years

And to be honest, maintaining a framework for free in my rare free-time is also not what I want to do permanently. :)

Finally a little note: The PHP world has evolved dramatically, we have excellent frameworks with awesome features and big professional teams behind, very well written documentations and large communities, so there's simply no reason to put much work into another framework. Instead, please commit to the popular frameworks, then your work will have much more impact and is used by much more people!

Thanks to everybody around this project, have a wonderful time! XOXO, Chris

Releases & development

  • stable v3.1,
  • public beta branch: master
  • public in-development branch (please commit new code here): develop

Quick-Index

The History of HUGE

Back in 2010/2011 there were no useful login solutions in the PHP world, at least not for non-experts. So I did the worst mistake every young developer does: Trying to build something by myself without having any clue about security basics. What made it even worse was: The web was (and is) full of totally broken tutorials about building user authentication systems, even the biggest companies in the world did this completely wrong (we are talking about SONY, LinkedIn and Adobe here), and also lots of major framework in all big programming languages (!) used totally outdated and insecure password saving technologies.

However, in 2012 security expert Anthony Ferrara published a little PHP library, allowing extremely secure, modern and correct hashing of passwords in PHP 5.3 and 5.4, usable by every developer without any stress and without any knowledge about security internals. The script was so awesome that it was written into the core of PHP 5.5, it's the de-facto standard these days.

When this came out I tried to use this naked library to build a fully working out-of-the-box login system for several private and commercial projects, and put the code on GitHub. Lots of people found this useful, contributed and bugfixed the project, made forks, smaller and larger versions. The result is this project.

Please note: Now, in 2015, most major frameworks have excellent user authentication logic embedded by default. This was not the case years ago. So, from today's perspective it might be smarter to chose Laravel, Yii or Symfony for serious projects. But feel free to try out HUGE, the auto-installer will spin up a fully working installation within minutes and without any configuration.

And why the name "HUGE" ? It's a nice combination to TINY, MINI and MINI2, MINI3, which are some of my other older projects. Super-minimal micro frameworks for extremely fast and simple development of simple websites.

Features

  • built with the official PHP password hashing functions, fitting the most modern password hashing/salting web standards
  • proper security features, like CSRF blocking (via form tokens), encryption of cookie contents etc.
  • users can register, login, logout (with username, email, password)
  • password-forget / reset
  • remember-me (login via cookie)
  • account verification via mail
  • captcha
  • failed-login-throttling
  • user profiles
  • account upgrade / downgrade
  • simple user types (type 1, type 2, admin)
  • supports local avatars and remote Gravatars
  • supports native mail and SMTP sending (via PHPMailer and other tools)
  • uses PDO for database access for sure, has nice DatabaseFactory (in case your project goes big)
  • uses URL rewriting ("beautiful URLs")
  • proper split of application and public files (requests only go into /public)
  • uses Composer to load external dependencies (PHPMailer, Captcha-Generator, etc.) for sure
  • fits PSR-0/1/2/4 coding guidelines
  • uses Post-Redirect-Get pattern for nice application flow
  • masses of comments
  • is actively maintained and bug-fixed (however, no big new features as project slowly reaches End of Life)

Planned features

  • A real documentation (currently there's none, but the code is well commented)

Live-Demo

See a live demo of older 3.0 version here and the server's phpinfo() here.

Support the project

There is a lot of work behind this project. I might save you hundreds, maybe thousands of hours of work (calculate that in developer costs). So when you are earning money by using HUGE, be fair and give something back to open-source. HUGE is totally free to private and commercial use.

Support the project by renting a server at 1&1 or at DigitalOcean. Thanks! :)

Also feel free to contribute to this project.

License

Licensed under MIT. Totally free for private or commercial projects.

Requirements

Make sure you know the basics of object-oriented programming and MVC, are able to use the command line and have used Composer before. This script is not for beginners.

  • PHP 5.5+
  • MySQL 5 database (better use versions 5.5+ as very old versions have a PDO injection bug
  • installed PHP extensions: pdo, gd, openssl (the install guideline shows how to do)
  • installed tools on your server: git, curl, composer (the install guideline shows how to do)
  • for professional mail sending: an SMTP account (I use SMTP2GO)
  • activated mod_rewrite on your server (the install guideline shows how to do)

Auto-Installations

Yo, fully automatic. Why ? Because I always hated it to spend days trying to find out how to install a thing. This will save you masses of time and nerves. Donate a coffee if you like it.

Auto-Installation (in Vagrant)

If you are using Vagrant for your development, then simply

  1. Add the official Ubuntu 14.04 LTS box to your Vagrant: vagrant box add ubuntu/trusty64
  2. Move Vagrantfile and bootstrap.sh (from _one-click-installation folder) to a folder where you want to initialize your project.
  3. Do vagrant up in that folder.

5 minutes later you'll have a fully installed HUGE inside Ubuntu 14.04 LTS. The full code will be auto-synced with the current folder. MySQL root password and the PHPMyAdmin root password are set to 12345678. By default 192.168.33.111 is the IP of your new box.

Auto-Installation in a naked Ubuntu 14.04 LTS server

Extremely simple installation in a fresh and naked typical Ubuntu 14.04 LTS server:

Download the installer script

wget https://raw.githubusercontent.com/panique/huge/master/_one-click-installation/bootstrap.sh

Make it executable

chmod +x bootstrap.sh

Run it! Give it some minutes to perform all the tasks. And yes, you can thank me later :)

sudo ./bootstrap.sh

Installation

Quick guide:

  1. Make sure you have Apache, PHP, MySQL installed. Tutorial.
  2. Clone the repo to a folder on your server
  3. Activate mod_rewrite, route all traffic to application's /public folder. Tutorial.
  4. Edit application/config: Set your database credentials
  5. Execute SQL statements from application/_installation to setup database tables
  6. Install Composer, run Composer install on application's root folder to install dependencies
  7. Make avatar folder (application/public/avatars) writable
  8. For proper email usage: Set SMTP credentials in config file, set EMAIL_USE_SMTP to true

"Email does not work" ? See the troubleshooting below. TODO

Detailed guide (Ubuntu 14.04 LTS):

This is just a quick guideline for easy setup of a development environment!

Make sure you have Apache, PHP 5.5+ and MySQL installed. Tutorial here. Nginx will work for sure too, but no install guidelines are available yet.

Edit vhost to make clean URLs possible and route all traffic to /public folder of your project:

sudo nano /etc/apache2/sites-available/000-default.conf

and make the file look like

<VirtualHost *:80>
    DocumentRoot "/var/www/html/public"
    <Directory "/var/www/html/public">
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Enable mod_rewrite and restart apache.

sudo a2enmod rewrite
service apache2 restart

Install curl (needed to use git), openssl (needed to clone from GitHub, as github is https only), PHP GD, the graphic lib (we create captchas and avatars), and git.

sudo apt-get -y install curl
sudo apt-get -y install php5-curl
sudo apt-get -y install openssl
sudo apt-get -y install php5-gd
sudo apt-get -y install git

git clone HUGE

sudo git clone https://github.com/panique/huge "/var/www/html"

Install Composer

curl -s https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Go to project folder, load Composer packages (--dev is optional, you know the deal)

cd /var/www/html
composer install --dev

Execute the SQL statements. Via phpmyadmin or via the command line for example. 12345678 is the example password. Note that this is written without a space.

sudo mysql -h "localhost" -u "root" "-p12345678" < "/var/www/html/application/_installation/01-create-database.sql"
sudo mysql -h "localhost" -u "root" "-p12345678" < "/var/www/html/application/_installation/02-create-table-users.sql"
sudo mysql -h "localhost" -u "root" "-p12345678" < "/var/www/html/application/_installation/03-create-table-notes.sql"

Make avatar folder writable (make sure it's the correct path!)

sudo chown -R www-data "/var/www/html/public/avatars"

If this doesn't work for you, then you might try the hard way by setting alternatively

sudo chmod 0777 -R "/var/www/html/public/avatars"

Remove Apache's default demo file

sudo rm "/var/www/html/index.html"

Edit the application's config in application/config/config.development.php and put in your database credentials.

Last part (not needed for a first test): Set your SMTP credentials in the same file and set EMAIL_USE_SMTP to true, so you can send proper emails. It's highly recommended to use SMTP for mail sending! Native sending via PHP's mail() will not work in nearly every case (spam blocking). I use SMTP2GO.

Then check your server's IP / domain. Everything should work fine.

NGINX setup:

This is an untested NGINX setup. Please comment on the ticket if you see issues.

server {
    # your listening port
    listen 80;

    # your server name
    server_name example.com;

    # your path to access log files
    access_log /srv/www/example.com/logs/access.log;
    error_log /srv/www/example.com/logs/error.log;

    # your root
    root /srv/www/example.com/public_html;

    # huge
    index index.php;

    # huge
    location / {
        try_files $uri /index.php?url=$uri&$args;
    }

    # your PHP config
    location ~ \.php$ {
        try_files $uri  = 401;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

IIS setup:

Big thanks to razuro for this fine setup: Put this inside your root folder, but don't put any web.config in your public folder.

<?xml version="1.0" encoding="UTF-8"?><configuration>
    <system.webServer>
        <rewrite>
            <rules>
			
                <rule name="Imported Rule 1" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
					<conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="public/index.php?url={R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Find the original ticket here.

Testing with demo users

By default there are two demo users, a normal user and an admin user. For more info on that please have a look on the user role part of the small documentation block inside this readme.

Normal user: Username is demo2, password is 12345678. The user is already activated. Admin user (can delete and suspend other users): Username is demo, password is 12345678. The user is already activated.

What the hell are .travis.yml, .scrutinizer.yml etc. ?

There are several files in the root folder of the project that might be irritating:

  • .htaccess (optionally) routes all traffic to /public/index.php! If you installed this project correctly, then this file is not necessary, but as lots of people have problems setting up the vhost correctly, .htaccess it still there to increase security, even on partly-broken-installations.
  • .scrutinizer.yml (can be deleted): Configs for the external code quality analyzer Scrutinizer, just used here on GitHub, you don't need this for your project.
  • .travis.yml (can be deleted): Same like above. Travis is an external service that creates installations of this repo after each code change to make sure everything runs fine. Also runs the unit tests. You don't need this inside your project.
  • composer.json (important): You should know what this does. ;) This file says what external dependencies are used.
  • travis-ci-apache (can be deleted): Config file for Travis, see above, so Travis knows how to setup the Apache.

README and CHANGELOG are self-explaining.

Documentation

A real documentation is in the making. Until then, please have a look at the code and use your IDE's code completion features to get an idea how things work, it's quite obvious when you look at the controller files, the model files and how data is shown in the view files. A big sorry that there's no documentation yet, but time is rare and we are all doing this for free in our free time :)

  • TODO: Full documentation
  • TODO: Basic examples on how to do things

How to use the different user roles

Currently there are two types of users: Normal users and admins. There are exactly the same, but...

  1. Admin users can delete and suspend other users, they have an additional button "admin" in the navigation. Admin users have a value of 7 inside the database table field user_account_type. They cannot upgrade or downgrade their accounts (as this wouldn't make sense).

  2. Normal users don't have admin features for sure. But they can upgrade and downgrade their accounts (try it out via /user/changeUserRole), which is basically a super-simple implementation of the basic-user / premium-user concept. Normal users have a value of 1 or 2 inside the database table field user_account_type. By default all new registered users are normal users with user role 1 for sure.

See the "Testing with demo users" section of this readme for more info.

There's also a very interesting pull request adding user roles and user permissions, which is not integrated into the project as it's too advanced and complex. But, this might be exactly what you need, feel free to try.

How to use the CSRF feature

To prevent CSRF attacks, HUGE does this in the most common way, by using a security token when the user submits critical forms. This means: When PHP renders a form for the user, the application puts a "random string" inside the form (as a hidden input field), generated via Csrf::makeToken() (application/core/Csrf.php), which also saves this token to the session. When the form is submitted, the application checks if the POST request contains exactly the form token that is inside the session.

This CSRF prevention feature is currently implemented on the login form process (see application/view/login/index.php) and user name change form process (see application/view/user/editUsername.php), most other forms are not security- critical and should stay as simple as possible.

So, to do this with a normal form, simply: At your form, before the submit button put: <input type="hidden" name="csrf_token" value="<?= Csrf::makeToken(); ?>" /> Then, in the controller action validate the CSRF token submitted with the form by doing:

// check if csrf token is valid
if (!Csrf::isTokenValid()) {
    LoginModel::logout();
    Redirect::home();
    exit();
}

A big thanks to OmarElGabry for implementing this!

Can a user be logged in from multiple devices ?

In theory: Yes, but this feature didn't work in my tests. As it's an external feature please have a look into the according ticket for more.

Troubleshooting & Glitches

  • In 3.0 and 3.1 a user could log into the application from different devices / browsers / locations. This was intended behaviour as this is standard in most web applications these days. In 3.2 still feature is "missing" by default, a user will only be able to log in from one browser at the same time. This is a security improvement, but for sure not optimal for many developers. The plan is to implement a config switch that will allow / disallow logins from multiple browsers.
  • Using this on a sub-domain ? You might get problems with the cookies in IE11. Fix this by replacing "/" with "./" of the cookie location COOKIE_PATH inside application/config/config.xxx.php! Check ticket #733 for more info. Thanks to jahbiuabft for figuring this out. Update: There's another ticket focusing on the same issue: ticket #681

Community-provided features & feature discussions

There are some awesome features or feature ideas build by awesome people, but these features are too special-interest to go into the main version of HUGE, but have a look into these tickets if you are interested:

Future of HUGE: Announcing "soft End Of Life"

The idea of this project is and was to provide a super-simple barebone application with a full user authentication system inside that just works fine and stable. Due to the highly security-related nature of this script any changes mean a lot of work, lots of testing, catching edge cases etc., and in the end I spent 90% of the time testing and fixing new features or new features break existing stuff, and doing this is really not what anybody wants to do for free in the rare free-time :)

To keep the project stable, clean and maintainable, I would kindly announce the "soft-End of Life" for this project, meaning:

A. HUGE will not get any new features in the future, but ... B. bugfixes and corrections will be made, probably for years

Coding guideline behind HUGE

While HUGE was in development, there were 3 main rules that helped me (and probably others) to write minimal, clean and working code. Might be useful for you too:

  1. Reduce features to the bare minimum.
  2. Don't implement features that are not needed by most users.
  3. Only build everything for the most common use case (like MySQL, not PostGre, NoSQL etc).

As noted in the intro of this README, there are also some powerful concepts that might help you when developing cool stuff: KISS, YAGNI, Feature Creep, Minimum viable product.

List of features / ideas provided in tickets / pull requests

To avoid unnecessary work for all of us I would kindly recommend everybody to use HUGE for simple project that only need the features that already exist, and if you really need a RESTful architecture, migrations, routing, 2FA etc, then it's easier, cleaner and faster to simply use Laravel, Symfony or Zend.

However, here are the community-suggested possible features, taken from lots of tickets. Feel free to implement them into your forks of the project:

  • OAuth2 implementation (let your users create accounts and login via 3rd party auth, like Facebook, Twitter, GitHub, etc). As this is a lot of work and would make the project much more complicated it might make sense to do this in a fork or totally skip it. (see Ticket #528)
  • Router (map all URLs to according controller-methods inside one file), Ticket 727
  • RESTful architecture (see ticket #488 for discussion)
  • Horizontal MySQL scaling (see ticket #423 for discussion)
  • Modules / middleware
  • Logging
  • Two-Factor-Authentication (see ticket #732)
  • Controller-less URLs (see ticket #704)
  • Email-re-validation after email change (see ticket #705)
  • Connect to multiple databases (see ticket #702)
  • A deeper user role system (see ticket #701, pull-request #691), ticket #603
  • How to run without using Composer ticket #826

Why is there no support forum (anymore) ?

There were two (!) support forums for v1 and v2 of this project (HUGE is v3), and both were vandalized by people who didn't even read the readme and / or the install guidelines. Most asked question was "script does not work plz help" without giving any useful information (like code or server setup or even the version used). While I'm writing these lines somebody just asked via Twitter "how to install without Composer". You know what I mean :) - 99% of the questions were not necessary if the people would had read the guidelines, do a minimal research on their own or would stop making things so unnecessarily complicated. And even when writing detailed answers most of them still messed it up, resulting in rants and complaints (for free support for a free software!). It was just frustrating to deal with this every day, especially when people take it for totally granted that it's the duty of open-source developers to give detailed, free and personal support for every "plz help"-request.

So I decided to completely stop any free support. For serious questions about real problems inside the script please use the GitHub issues feature.

Zero tolerance for idiots, trolls and vandals!

Harsh words, but as basically every public internet project gets harassed, vandalized and trolled these days by very strange people it's necessary: Some simple rules.

  1. Respect that this is just a simple script written by unpaid volunteers in their free-time. This is NOT business-software you've bought for $10.000. There's no reason to complain (!) about free open-source software. The attitude against free software is really frustrating these days, people take everything for granted without realizing the work behind it, and the fact that they get serious software totally for free, saving thousands of dollars. If you don't like it, then don't use it. If you want a feature, try to take part in the process, maybe even build it by yourself and add it to the project! Be nice and respectful. Constructive criticism is for sure always welcome!

  2. Don't bash, don't hate, don't spam, don't vandalize. Please don't ask for personal free support, don't ask if somebody could do your work for you. Before you ask something, make sure you've read the README, followed every tutorial, double-checked the code and tried to solve the problem by yourself.

Trolls and very annoying people will get a permanent ban / block. GitHub has a very powerful anti-abuse team.

Contribute

Please commit only in develop branch. The master branch will always contain the stable version.

Code-Quality scanner links

Scrutinizer (master branch), Scrutinizer (develop branch), Code Climate, Codacy, SensioLabs Insight.

Found a bug (Responsible Disclosure) ?

Due to the possible consequences when publishing a bug on a public open-source project I'd kindly ask you to send really big bugs to my email address, not posting this here. If the bug is not interesting for attackers: Feel free to create an normal GitHub issue.

Current and further development

See active issues here: https://github.com/panique/huge/issues?state=open

Why you should use a favicon.ico in your project :)

Interesting issue: When a user hits your website, the user's browser will also request one or more (!) favicons (different sizes). If these static files don't exist, your application will start to generate a 404 response and a 404 page for each file. This wastes a lot of server power and is also useless, therefore make sure you always have favicons or handle this from Apache/nginx level.

HUGE tries to handle this by sending an empty image in the head of the view/_templates/header.php !

More inside this ticket: Return proper 404 for missing favicon.ico, missing images etc.

More here on Stackflow: How to prevent favicon.ico requests?, Isn't it silly that a tiny favicon requires yet another HTTP request? How to make favicon go into a sprite?.

Useful links

Interesting links regarding user authentication and application security

My blog

I'm also blogging at Dev Metal.

Comments
  • Weak Password Hashing

    Weak Password Hashing

    SHA256 is known to be weak. Please change to use crypt (specifically the latest adopted bcrypt) and user-specific salts that get regenerated from time to time. Then this will be a great class to use!

    opened by shackrock 33
  • [STICKY][Optional feature] ReCaptcha Support

    [STICKY][Optional feature] ReCaptcha Support

    I fully understand that we don't want any more features for the project. I am simply creating this to give people a concept of how to add ReCaptcha to their own pages.

    Composer command (official google lib) composer require google/recaptcha "~1.1"

    Code to add to any pages you want a captcha (will use built in if recaptcha not enabled)

    <?php if (Config::get('RECAPTCHA_ENABLED')) { ?>
    <div class="g-recaptcha" data-sitekey="<?php echo Config::get('RECAPTCHA_SITEKEY'); ?>"></div>
    <script src="https://www.google.com/recaptcha/api.js"></script>
    <?php } else { ?>
    <br><img id="captcha" src="<?php echo URL; ?>login/showCaptcha"/>
    <br><input type="text" name="captcha" placeholder="Please enter above characters" required/>
    
    <!-- quick & dirty captcha reloader -->
    <a href="#" style="display: block; font-size: 11px; margin: 5px 0 15px 0; text-align: center" onclick="document.getElementById('captcha').src = '<?php echo URL; ?>login/showCaptcha?' + Math.random(); return false">Reload Captcha</a>
    <?php } ?>
    

    CaptchaModel Function (add anywhere you'd like)

    public static function checkRecaptcha($gReCaptchaResponse) {
        $recaptcha = new \ReCaptcha\ReCaptcha(Config::get('RECAPTCHA_SECRET'));
        $resp = $recaptcha->verify($gReCaptchaResponse, Request::server('REMOTE_ADDR'));
         if($resp->isSuccess()) {
            return true;
        } else {
            return false;
        }
    }
    

    Part you put into your function that checks for captcha (again compatible with built in captcha)

    if (Config::get('RECAPTCHA_ENABLED')) {
        if (!CaptchaModel::checkRecaptcha($captcha)) {
           Session::add('feedback_negative', Language::getText('captcha-wrong'));
           return false;
        }
    } else {
       if (!CaptchaModel::checkCaptcha($captcha)) {
            Session::add('feedback_negative', Language::getText('captcha-wrong'));
            return false;
        }
    }
    

    And last but not least this will need to be added to the config array

    'RECAPTCHA_ENABLED' => true,
    'RECAPTCHA_SECRET' => 'xxxxxxxxx',
    'RECAPTCHA_SITEKEY' => 'xxxxxxxxxx',
    
    opened by tankerkiller125 25
  • [OPTIONAL FEATURE] Facebook login/register ?

    [OPTIONAL FEATURE] Facebook login/register ?

    Is it possible to have Facebook login and register implemented ? I was looking at this my self but not much success ... I'm trying to make some kind of social website this script is simple and good, but i would like to connect it with Facebook. Also uploading/grabbing avatars from Facebook would be nice as well if its possible.

    enhancement 
    opened by racha 22
  • [Feature] Added account deletion and suspension

    [Feature] Added account deletion and suspension

    I have added the ability to soft delete and account so you don't need to delete valuable user information, also added account suspension based on timestamps

    opened by jjkirkpatrick 21
  • [feature discussion] Roles (partly done by the way, see admin feature)

    [feature discussion] Roles (partly done by the way, see admin feature)

    Hi, i'm not sure if this has been discussed or not yet, but i feel like user roles is part of the user creation/login process. so with a few tweeks to the database to allow roles to be assigned to a user, we could then have a function in the Auth class to check if they have the required roles to view a view or a controller. here is a quick thrown together example

    public static function canUserAccsess($requiredRoles = array()) {
        $Count = count($requiredRoles);
        $i = 0;
        while ($i < $Count) {      
            $status =  (session::get('user_' . $requiredRoles[$i]) ? true : false ) ;
            //return true as soon as one of the required roles is present.
            if($status == true){
                return true;
            }
            $i++;
        }
        //of non of them passed then we don't have the roles
        return false;
    }
    

    And then in the views or where ever we can simply do something like this.

    if(Auth::canUserAccsess(['Sales','Admin'])){
    echo "We got in!";
    }
    
    opened by jjkirkpatrick 20
  • [3.x][feature] Support for horizontal MySQL scaling

    [3.x][feature] Support for horizontal MySQL scaling

    How about to use 2 or more MySQL connections for MySQL scaling? I think it's must have feature. For example, if i want store Users in 1 DB, but Notes of these Users, i want store into 2 DB.

    opened by TemaSM 20
  • Release for

    Release for "#2 Advanced" still May 2013?

    Sorry to bug you about this. Wondering if you could comment on the release date? I really just need email verification.

    Would like to donate and help test if at all possible, if you could contact me at blake [at] alertustech.com so we could discuss offline would appreciate it.

    opened by blak3r 20
  • [INTERESTING] login without password (using smartphone QRs)

    [INTERESTING] login without password (using smartphone QRs)

    Gentlemen,

    one of my favourite (german) PHP blogs just posted a very very interesting solution for SECURE login-processes while using a (possibly infected, keylogged etc.) computer in internet cafes, hotels, universities etc. You know what I mean.

    This is awesome! According to the article this/something similar has been tested by Google, too.

    (german) article: http://www.phpgangsta.de/sesam-oeffne-dich-sicher-einloggen-im-internetcafe

    Github repo: https://github.com/PHPGangsta/Sesame

    Demo: http://sesame.phpgangsta.de/

    Feel free to experiment with this and maybe pushing this feature into the 2-advanced / 4-full version.

    opened by panique 19
  • [SOLVED!?] Prevent Curl Views without Exit() and with added security backup

    [SOLVED!?] Prevent Curl Views without Exit() and with added security backup

    Well, it took me all night and today to come up with, what I believe, is a real sound solution.

    Auth Class We start by replacing the exit() function with the following.

    // Initialize a new Session
    Session::init();
    // Set a session 'Restrict' flag
    Session::set('restrict', true);
    

    The header('location') function has already been called at this point so the above script would presumably only affect a curl request. Easy enough...

    View Class In my understanding, it is ultimately the view that we need to protect.

    We begin by adding a new function called clean($filename) (we can name it better later on) Refer to the comments in this script for an understanding of the function...

    public static function clean($filename)
    {
        // If the restrict flag is set to true
        if(Session::get('restrict')==true){
            // Change the $filename to another page
            $filename = 'login/index';
            // Destroy the Session as it is no longer needed
            Session::destroy();
        }   
        // Return the $filename to render
        // restrict=true $filename='login/index';
        // else $filename=original $filename;
        return $filename;       
    }
    

    Finally, in all of the render functions that will be used to render secured areas you would call this function first and foremost.

    public function render($filename, $data = null)
    {
        // Here is the call
        $filename = self::clean($filename);     
    
        if ($data) {
            foreach ($data as $key => $value) {
                $this->{$key} = $value;
            }
        }   
        require Config::get('PATH_VIEW') . '_templates/header.php';
        require Config::get('PATH_VIEW') . $filename . '.php';
        require Config::get('PATH_VIEW') . '_templates/footer.php';
     }
    

    As you can see, we completely avoid using the exit() function and mimic the effect of the original header("location") function

    The beauty of this is that it only gets initiated if the script runs past the header redirect, via curl, or for any other unforeseen reason. Nice backup either way :)

    I have tested this in all ways possible that I know of, but if any of you could break this, please tell me so.

    I would really like to know what you guys think!

    opened by videsignz 18
  • [no bug] Password Hash

    [no bug] Password Hash

    Hi,

    I installed your script here: http://vserv08.neogreen.net/servermonitor/ Yes i can create an account but when i try to Login after verify my E-Mail it dosent works. So i took a look into my Database but password thingi is empty?

    opened by ghost 18
  • Update composer.json

    Update composer.json

    Waiting on ~~https://github.com/PHPMailer/PHPMailer/issues/213 and~~ ~~https://github.com/raveren/kint/pull/112~~ to be fixed before this can be merged. Also, as this project stands at the moment, before this pull request, the dependencies are actually not installable because the phpmailer 5.2 releases don't exist.

    opened by GrahamCampbell 17
  • ErrorController redeclaration

    ErrorController redeclaration

    Hi all,

    At this URL: {Base URL}/error/whatever

    The following error will appear: "Fatal error: Cannot declare class ErrorController, because the name is already in use..." (due a double "require" in application/core/Application.php at L37 and L51).

    My suggestion for fixing this issue is to change L51 in application/core/Application.php: (before) require Config::get('PATH_CONTROLLER') . 'ErrorController.php'; (after)require_once Config::get('PATH_CONTROLLER') . 'ErrorController.php';

    Greetings

    opened by elbenjaz 2
  • Trying to get in touch regarding a security issue

    Trying to get in touch regarding a security issue

    Hi there,

    I couldn't find a SECURITY.md in your repository and am not sure how to best contact you privately to disclose a security issue.

    Can you add a SECURITY.md file with an e-mail to your repository, so that our system can send you the vulnerability details? GitHub suggests that a security policy is the best way to make sure security issues are responsibly disclosed.

    Once you've done that, you should receive an e-mail within the next hour with more info.

    Thanks! (cc @huntr-helper)

    opened by JamieSlome 4
  • Agregar AJAX al proyecto

    Agregar AJAX al proyecto

    If anyone is trying to integrate AJAX and DATATABLE I will show you how I did it.

    Show records and add register note/index

    <form method="post" id="new_form_notes">
                                <label>Nota: </label>
                                <input type="text" name="note_text" id="note_text"/>
                                <input type="hidden" name="csrf_token" value="<?= Csrf::makeToken(); ?>" />
                                <button type="submit" >Agregar</button>
    </form>
    
    <table id="note_data" >
                <thead>
                    <tr>
                        <td>Id</td>
                        <td>Note</td>
                        <td>EDIT</td>
                        <td>DELETE</td>
                    </tr>
                </thead>
            </table>
    

    In _templates/footer.php

    <script type="text/javascript" language="javascript" >
     var url = "<?php echo Config::get('URL'); ?>";
    var csrf_token = "<?= Csrf::makeToken(); ?>";
    </script>
    
    <script src="<?php echo Config::get('URL'); ?>js/demo.js"></script>
    

    demo.js

    $(document).ready(function(){
    	var dataTable = $('#note_data').DataTable({
            "processing":true,
    		"serverSide":true,
    		"order":[],
    		"ajax":{
    			url: url + 'Note/tableNote',
    			type:"POST",
    			data: { csrf_token : csrf_token }
    		}	
    	});
    
        	$(document).on('submit', '#new_form_notes', function (event) {
            event.preventDefault();
            $.ajax({
    			url: url + 'Note/Create',
                type: "post",
    			dataType: "json",
    			data: new FormData(this),
                cache: false,
                contentType: false,
                processData: false
    
            }).always(function () {
    
            }).done(function (response) {
                dataTable.ajax.reload();
    			console.log(response);
    			if(response =='insertado'){
    				alert('Datos insertados')
    			}else{
    				alert(response)
    			}
    		
            }).fail(function (jqXHR, textStatus, errorThrown) {
               console.log("Ha ocurrido un error inesperado " + jqXHR + " " + textStatus + " " + errorThrown);
    		   console.warn(jqXHR.responseText)
            });
    	});
    });
    

    Controller/NoteController.php

        public function tableNote()
        {
             // check if csrf token is valid
             if (!Csrf::isTokenValid()) {
                LoginModel::logout();
                Redirect::home();
                exit();
            }else{
                $response = NoteModel::datatable();
                echo $response;
    
            }
        }
    
       public function create()
        {
            if (!Csrf::isTokenValid()) {
                LoginModel::logout();
                Redirect::home();
                exit();
            }else{
                $response = NoteModel::createNote( Request::post('note_text'));
                echo $response;
            }
          
        }
    

    Model/NoteModel.php

    public static function get_total_all_records()
        {
            $database  = DatabaseFactory::getFactory()->getConnection();
            $statement = $database->prepare("SELECT * FROM notes");
            $statement->execute();
            return $statement->rowCount();
        }
    
        public static function datatable()
        {
            
            $database = DatabaseFactory::getFactory()->getConnection();
    
            $query = '';
            $columns = array('note_id', 'note_text', 'note_id', 'note_id');
            
            $output = array();
            
            $query .= "SELECT * FROM notes ";
    
            if (isset($_POST["search"]["value"])) {
                $query .= ' WHERE note_text LIKE "%' . $_POST["search"]["value"] . '%" ';
                $query .= 'OR note_id LIKE "%' . $_POST["search"]["value"].'%" ';
            }
            if (isset($_POST["order"])) {
                $query .= 'ORDER BY ' . $columns[$_POST['order']['0']['column']] . ' ' . $_POST['order']['0']['dir'] . ' 
                ';
            } else {
                $query .= 'ORDER BY note_id DESC ';
            }
            if ($_POST["length"] != -1) {
                $query .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
            }
            $statement =  $database->prepare($query);
            $statement->execute();
            
            $result = $statement->fetchAll();
            $data = array();
            $filtered_rows = $statement->rowCount();
            foreach ($result as $row) {
             
                $sub_array = array();
                $sub_array[] = $row->note_id;
                $sub_array[] = $row->note_text;
              
                $sub_array[] = '<button type="button" name="update" id="' . $row->note_id . '" class="btn btn-warning btn-xs update">Update</button>';
    
                $sub_array[] = '<button type="button" name="delete" id="' . $row->note_id . '" class="btn btn-danger btn-xs delete">Delete</button>';
    
                $data[] = $sub_array;
            }
    
            $output = array(
                "draw"                =>    intval($_POST["draw"]),
                "recordsTotal"        =>    $filtered_rows,
                "recordsFiltered"     =>     self::get_total_all_records(),
                "data"                =>    $data
            );
    
            echo json_encode($output, true);
    
        }
    
    
    public static function createNote( $note_text )
        {
           
                $database = DatabaseFactory::getFactory()->getConnection();
    
                $sql = "INSERT INTO notes (note_text, user_id) VALUES (:note_text,  :user_id)";
                $query = $database->prepare($sql);
                $query->execute(array(
                ':note_text' => $note_text, 
                ':user_id' => Session::get('user_id')));
        
                if ($query->rowCount() == 1) {
                    $mens =  'insertado';
                }else{
                    $mens =  'sinCambios';  
                }
            
            echo $mens;
        }
    
    
    
    opened by jorge-koki 0
  • in the encryption.php file

    in the encryption.php file

    I have a quick question from the encryption.php file located in the core folder. Obviously, its a file for encryption and decryption of string data. My question lies in the decrypt($ciphertext) function.

    in that function on line 95 you have $macSize = 64; I can't understand where this variable comes from and why its exactly 64.

    also, in that same decrypt( ) function, there is on line 97: $iv_cipher = mb_substr ( $ciphertext, $macSize, NULL , '8bit' ); because of the NULL value, wont this function return an empty string? See: https://www.w3schools.com/php/func_string_substr.asp

    opened by mdk1980 1
  • A question about data sent to the view from the controllers

    A question about data sent to the view from the controllers

    In view.php (application/core/view.php) there is a foreach loop for data (an array) to be sent to the view when necessary. I can't find a reason for this code nor do I see where in view.php this information is used in any of its internal methods.

    The code in question: class: view.php method: render( )

    public function render($filename, $data = null) { if ($data) { foreach ($data as $key => $value) { $this->{$key} = $value; } }

    This foreach loop information is not used apparently in the subsequent code in view.php that displays information to the user.

    require Config::get('PATH_VIEW') . '_templates/header.php'; require Config::get('PATH_VIEW') . $filename . '.php'; require Config::get('PATH_VIEW') . '_templates/footer.php';

    heres an example. In the LoginController (application/controller/) you have a method: index() that feeds information to the view.php

    in the index() method in LoginController.php (path=application/controller/LoginController.php)

    public function index()
    {
        // if user is logged in redirect to main-page, if not show the login/index() method
        if (LoginModel :: isUserLoggedIn()) {
            Redirect::home();
        } else {
            $data = array('redirect' => Request::get('redirect') ? Request::get('redirect') : NULL);  ->  THIS LINE HERE
            $this->View->render('login/index', $data);
        }
    }
    

    The 'else' part containing $data sends an array to the render method of view.php that appears to do nothing. Im sure I'm missing something simple here. Any help would be appreciated.

    opened by mdk1980 1
Releases(v3.3.1)
  • v3.1(Mar 7, 2015)

  • v3.0.0(Mar 1, 2015)

  • v3.0.0-RC1(Jan 27, 2015)

  • v2.1.1(Jan 25, 2015)

    Final status of the "old" php-login 2.x branch. In January 2015 php-login 3.0 will be released, with a totally new architecture, lots of changes and a new name, so it's necessary to save the latest status of this project.

    You'll find the new project under https://github.com/panique/huge

    Changes to 2.1.0: I've removed the irritating link to "new" 2.1

    Source code(tar.gz)
    Source code(zip)
  • v2.1(Jan 25, 2015)

    Final status of the "old" php-login 2.x branch. In January 2015 php-login 3.0 will be released, with a totally new architecture, lots of changes and a new name, so it's necessary to save the latest status of this project.

    You'll find the new project under https://github.com/panique/huge

    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Jun 6, 2014)

    This is the 2.0.1 release of the panique/php-login. Same like 2.0 beta pre-release from December 30th of 2013, but all the smaller fixes and improvements until April 20th 2014 are included. This release has been open to public for 5 months, no bugs so far.

    There will be a 2.0.2 later in the year that contains a documentation / usage tutorial.

    Source code(tar.gz)
    Source code(zip)
  • v2.0(Jan 1, 2014)

    This repository has a longer history, from a tiny (and not very secure) SHA512 mostly frontend-inspired login script to a very popular collection of 4 similar scripts (that now have their own repositories), and with the beginning of 2014 I cleaned the entire project to make panique/php-login the new home of the most professional and most used "professional mvc version" of that script collection.

    After a total refactoring, total restructuring and lots of improvements (more secure, more documented, more commented, Composer-based, PSR-1/2 code etc.) it's time for a proper release.

    Welcome to the world, version 2.0!

    Source code(tar.gz)
    Source code(zip)
  • archive-2013(Dec 15, 2013)

    In 2013, the php-login project contained 4 different login scripts. With the beginning of 2014 the project gets a massive makeover that includes the deletion of big parts of the current codebase. For historical reasons we will keep this code into this tag, "archive-2013".

    Source code(tar.gz)
    Source code(zip)
Owner
Chris
5.000+ ★ on GitHub. PHP dev, 10+ years of experience
Chris
Confide is a authentication solution for Laravel 4

Confide (A Laravel4 Package) Confide is an authentication solution for Laravel made to cut repetitive work involving the management of users. A DRY ap

Zizaco 1.2k Dec 30, 2022
Rinvex Authy is a simple wrapper for @Authy TOTP API, the best rated Two-Factor Authentication service for consumers, simplest 2fa Rest API for developers and a strong authentication platform for the enterprise.

Rinvex Authy Rinvex Authy is a simple wrapper for Authy TOTP API, the best rated Two-Factor Authentication service for consumers, simplest 2fa Rest AP

Rinvex 34 Feb 14, 2022
It's a Laravel 8 authentication markdown that will help you to understand and grasp all the underlying functionality for Session and API Authentication

About Auth Starter It's a Laravel 8 authentication markdown that will help you to understand and grasp all the underlying functionality for Session an

Sami Alateya 10 Aug 3, 2022
phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server.

phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server.

Apereo Foundation 780 Dec 24, 2022
PHPAuth is a secure PHP Authentication class that easily integrates into any site.

PHPAuth is under going a complete rewrite to bring the code up to date, the project has been on hold for way to long time now and I decided to work on it again making sure EVERYONE can use it and not just advanced programmers.

PHPAuth 855 Jan 3, 2023
Prevents development packages from being added into require and getting into production environment.

production-dependencies-guard Prevents development packages from being added into require and getting into production environment. In practical field

Vladimir Reznichenko 88 Oct 21, 2022
User Authentication Managment With Laravel 8

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

null 17 Jul 17, 2022
Redirects any user which hasn't setup two factor authentication yet to /2fa/

force-two-factor Redirects any user which hasn't setup two factor authentication yet to /2fa/. Use together with the forked two-factor plugin at https

Aiwos 0 Dec 24, 2021
Log user authentication details and send new device notifications.

Laravel Authentication Log is a package which tracks your user's authentication information such as login/logout time, IP, Browser, Location, etc. as well as sends out notifications via mail, slack, or sms for new devices and failed logins.

John S Nwanosike 2 Mar 13, 2022
Helps you securely setup a master password and login into user accounts with it.

?? Make your Login form smart in a minute! Built with ❤️ for every smart laravel developer Helps you set a master password in .env file and login into

Iman 341 Jan 1, 2023
Jasny SSO is a relatively simply and straightforward solution for single sign on (SSO).

Single Sign-On for PHP (Ajax compatible) Jasny SSO is a relatively simply and straightforward solution for single sign on (SSO). With SSO, logging int

Arnold Daniels 1.4k Jan 6, 2023
Multi-provider authentication framework for PHP

Opauth is a multi-provider authentication framework for PHP, inspired by OmniAuth for Ruby. Opauth enables PHP applications to do user authentication

Opauth – PHP Auth Framework 1.7k Jan 1, 2023
A framework agnostic authentication & authorization system.

Sentinel Sentinel is a PHP 7.3+ framework agnostic fully-featured authentication & authorization system. It also provides additional features such as

Cartalyst 1.4k Dec 30, 2022
Authentication REST-API built with Lumen PHP Framework

Authentication REST-API built with Lumen PHP Framework Laravel Lumen is a stunningly fast PHP micro-framework for building web applications with expre

Hüseyin Yağlı 1 Oct 12, 2021
LINE strategy for Opauth, Opauth is a multi-provider authentication framework for PHP.

Opauth-LINE Opauth strategy for LINE. Implemented based on https://developers.line.me/web-api/integrating-web-login-v2 using OAuth 2.0. Opauth is a mu

Opauth – PHP Auth Framework 2 Jul 11, 2017
Slim Auth is an authorization and authentication library for the Slim Framework.

Slim Auth is an authorization and authentication library for the Slim Framework. Authentication is provided by the Zend Framework Zend\Authentication component, and authorization by the Zend Framework Zend\Permissions\Acl component.

Jeremy Kendall 246 Dec 16, 2022
A Simple method to create laravel authentication for an existing laravel project.

Laravel Simple Auth A Simple method to create laravel authentication for an existing laravel project. Indroduction Why I created this kind of package?

Dasun Tharanga 10 Dec 14, 2021
Simple PHP Google Authentication Template

php-google-auth A php google authentication page project View Demo · Report Problems About The Project This is a small and easy project that I made to

Antonio 4 Nov 21, 2021
Simple readonly LDAP authentication with Laravel 5.2

ldap-auth Very basic READ ONLY LDAP authentication driver for Laravel 5.2+ Look HERE for the package for Laravel 5.1. However, only the 5.2 Version wi

Stan 26 Jun 20, 2021