Skip to content

✨ Leaf Simple Auth

Simple auth is a module which takes away the pain involved with anything authentication related: logins, signups, updating users, tokens, ... The main focus of simple auth is to allow you do all of the above in nothing more than one line of code (unless of course you include customizations for how these features work).

You can install auth through composer or leaf cli.

composer require leafs/auth v1.1.2

or

leaf install auth@1.1.2

Note that

Leaf auth has gone through a complete rewrite. Although it works the same way, features like sessions are used a bit differently. Read the changes section below for more info.

Usage

The first thing to do is to connect to your database. Leaf Auth will need to search for users in your database to perform auth checks on.

To connect to your database, you can add your db credentials in connect or use autoConnect if you've already configured your database in your .env file.

use Leaf\Auth;

Auth::connect("host", "user", "password", "dbname");
// or
Auth::autoConnect();

Functional Mode ⚡️

Just as with other leaf modules, Leaf auth is able to extend leaf 3's functional mode to allow you easily and quickly handle authentication in your apps without having to use length namespaces and classes.

Leaf auth provides the auth function which we will be using in the below code.

Getting started:

To get started with functional mode in leaf auth, you simply need to call the auth method.

auth()->connect("127.0.0.1", "root", "", "dbName");

From there, you can do anything you want to with the auth method. Just as with the leaf core library itself, you no longer even need to initialize leaf auth.

Auth Config

Auth Config was added in v2.4.0-beta to give you more control over how leaf handles authentication in your apps. Auth has been configured perfectly for most apps, but not all use cases are the same, hence, this brilliant addition.

This also includes various configurations for doing things like:

  • Setting custom token lifetime
  • Hiding/Showing user fields
  • Adding/removing default timestamps
  • Changing the default password key
  • Setting custom password encode methods
  • Turning off password encoding totally
  • Setting custom password verify methods
  • Hiding/Showing password field
  • Adding custom validation messages
  • Turning off experimental feature warnings (NEW)
  • Configuring tokens

config

To set a config variable, you can simply call the config method.

auth()->config("item", "value");

You can also pass in an array to set multiple configs at once:

auth()->config([
  "item" => "value",
  "item2" => "value"
]);

Settings

Below is a list of all available settings.

USE_TIMESTAMPS

This determines whether Leaf should add the default created_at and updated_at timestamps on register and update. Default is true.

PASSWORD_ENCODE

This setting has gone through a lot of changes since v2.4 beta, and may not work exactly the same way. This setting is run when leaf wants to encode a password. It now uses PASSWORD_DEFAULT by defaullt for encryption.

// This turns off password encoding
auth()->config("PASSWORD_ENCODE", false);

// defult encoding (Leaf\Helpers\Password::hash)
auth()->config("PASSWORD_ENCODE", null);

// use md5. We're still keeping support for md5 :-)
auth()->config("PASSWORD_ENCODE", Password::MD5);

// use custom method
auth()->config("PASSWORD_ENCODE", function ($password) {
  return Password::hash($password);
});

PASSWORD_VERIFY

This setting is called when Leaf tries to verify a password. It works just like PASSWORD_ENCODE above.

// This turns off password encoding
auth()->config("PASSWORD_VERIFY", false);

// defult encoding (Leaf\Helpers\Password::hash)
auth()->config("PASSWORD_VERIFY", null);

// use md5. We're still keeping support for md5 :-)
auth()->config("PASSWORD_VERIFY", Password::MD5);

// use custom method
auth()->config("PASSWORD_VERIFY", function ($password) {
  return Password::verify($password);
});

PASSWORD_KEY

This allows you to change the password field name, maybe yours is passcode? This tells leaf to look for a user's password in that field. The example below tells leaf to search for passwords in the passcode column. (the default field is password)

auth()->config("PASSWORD_KEY", "passcode");

ID_KEY

ID_KEY allows you to set your primary key name. For instance, you might have used _id instead of id. This setting allows you to quickly and effectively switch your key name.

auth()->config("ID_KEY", "_id");

USE_UUID

This simply allows you to set the value for user ids on your own. This is done in order to add support for UUIDs in your registrations and not go with the default SQL increments.

auth()->config("USE_UUID", UUID::v4());

HIDE_ID

This is a boolean which determines whether to hide the id in the user object returned on login/register. Default is true.

AUTH_NO_PASS

This allows you to manually tell leaf auth that no password is required for authentication. When this is set to true, leaf auth will assume there is no password and act accordingly. If there is no password field set in the credentials passed into the login or register methods, leaf auth will automatically set this to true.

HIDE_PASSWORD

Just as the name implies, allows you to hide or show the password in the final results returned from auth. Default is true.

LOGIN_PARAMS_ERROR

This is the error to show if there's an error with any parameter which isn't the password eg: username:

auth()->config("LOGIN_PARAMS_ERROR", "Username is incorrect!");

Default is Incorrect credentials!.

LOGIN_PASSWORD_ERROR

This is the error to show if there's an error with the password.

Default is Password is incorrect!.

auth()->config("LOGIN_PASSWORD_ERROR", "Password is incorrect!");

USE_SESSION

Use session based authentication instead of the default JWT based auth. Without this setting enbled, you can't use any of the session methods below. Default is false.

SESSION_ON_REGISTER

If true, a session will be created on a successful registration, else you it'll be created on login rather. Default is false.

GUARD_LOGIN

The page route. Default is /auth/login.

GUARD_REGISTER

The register page route. Default is /auth/register.

GUARD_LOGOUT

Logout route handler. Default is /auth/logout.

GUARD_HOME

Home page route. Default is /home.

SAVE_SESSION_JWT

Add an auth token to the auth session? This allows you save a generated JWT to the session. You might want to use this if you want to extend your app into an API. Default is false.

EXPERIMENTAL_WARNINGS

This option controls whether to show/hide experimental warnings from session components. Default is true. Turning this off allows you to use guards for JWT auth.

TOKEN_LIFETIME

How long the token can be used before it expires. Default is 1 day.

TOKEN_SECRET

This is the secret key used to generate tokens for users on signup and register.

Leaf Auth Refactor 🔥

The leaf auth module has been broken up into subclasses for easier use and performance reasons. If you only use login and signup, there's no need to include a class with tons of features that you may not use.

This doesn't change the way leaf auth works as this was done for performance and maintainability reasons. You can still use the auth class just as done in Leaf 2, however, this has been optimized using static methods which means unnecessary code will not be run.

Leaf\Auth::session();

Session support

Leaf Auth Session

Session has been moved into a sub class for easier management. To use auth session methods, you now have to use the Leaf\Auth\Session class.

Leaf\Auth\Session::init();

This doesn't affect the use of the auth class, since it works just as it did in earlier versions.

Session based authentication as the name implies creates and manages a session during the authentication to manage the user's logged in state. And all of this is done in 1 or 2 lines of code to maintain the simplicity and flexibility Leaf auth has always given.

To get started with session support, just set the USE_SESSION setting to true.

auth()->config("USE_SESSION", true);

A much simpler way would be to simply call the useSession method.

auth()->useSession();

Session methods

Enabling session support allows you to use some special methods and behaviours which are not available with the regular JWT authentication.

guard

The guard method works sort of like authentication middleware. It takes in a single param, an array holding the authentication state or the type of guard to load up.

Leaf\Auth\Session::guard(["hasAuth" => true]);

// or

Leaf\Auth\Session::guard("auth");

// guest route redirects to home
// route if you're logged in
Leaf\Auth\Session::guard("guest");

This is a lot easier with functional mode

auth()->guard("guest");

The auth function

Besides returning the auth object, you can also directly run a guard on the auth method.

auth("guest");

save

This method is used to save data to the auth session.

Leaf\Auth\Session::save("rememberLogin", false);

// You can add multiple vars
Leaf\Auth\Session::save([
  "rememberLogin" => false,
  "sessionActivity" => "login"
]);

As usual, this is easier with the auth class or with functional mode

auth()->save("rememberLogin", false);

length

With length, you can get how long a user has been logged in. You can save the session time logs to your database in order to track users' login logs. The available logs are SESSION_STARTED_AT and SESSION_LAST_ACTIVITY which are automatically tracked by Leaf.

// LoginsDB is a user defined method to save a login log

// ...
LoginsDB::params(
  "logged_in_at",
  date("D, d M Y H:i:s", Leaf\Auth\Session::length()),
);

LoginsDB::save();

Or with functional mode

auth()->sessionLength();

lastActive

lastActive allows you to get how much time has passed since the last session activity.

$userLastSeen = Leaf\Auth\Session::lastActive();

refresh

As the name implies, you can refresh the session with this method. Refreshing sort of restarts the session, but you can keep the user's old session data if you wish to.

if ($newAccountAdded) {
  // will delete old session data
  Leaf\Auth\Session::refresh();
} else {
  // will keep session data
  Leaf\Auth\Session::refresh(false);
}

status

status checks whether a user session is ongoing by looking for keys specific to Leaf session auth so it doesn't confuse a Leaf auth session with user defined sessions. Returns true if a session is found and false if there's no session found.

if (Leaf\Auth\Session::status()) {
  return "logged in";
} else {
  return "guest mode";
}

or with functional mode

if (auth()->session()) {
  return "logged in";
} else {
  return "guest mode";
}

end

Of course we'll need a method to logout/end our session. This is just the method for that.

Leaf\Auth\Session::end();

Or with functional mode

auth()->endSession();

Authentication methods

login

Login is used to create a simple, secure user login. It takes in a table to search for users and a set of parameters for the login.

$user = Leaf\Auth::login("users", [
  "username" => "mychi.darko",
  "password" => md5("test")
]);

LOGIN CLASS

Leaf auth now allows you to use logins with the new Leaf\Auth\Login class. This will allows you to import only the login functionality without actually going through the whole auth class.

$user = Leaf\Auth\Login::user("users", [
  "username" => "mychi.darko",
  "password" => md5("test")
]);

You can also use functional mode:

$user = auth()->login("users", [
  "username" => "mychi.darko",
  "password" => md5("test")
]);

If the user is successfully found, the user data is returned, if not, null is returned. You can get any error by calling the errors method.

$user = auth()->login("users", [
  "username" => "mychi.darko",
  "password" => md5("test")
]); // returns null if failed

if (!$user) {
  response()->throwErr(Leaf\Auth::errors());
}

example success response: Note that the password and id fields are removed. You can control whether fields should be hidden from the returned value in the Auth settings.

[
  "user" => [
    "username" => "mychi.darko",
    "email" => "mychi@leafphp.dev",
    "created_at" => "2019-09-20 13:47:48"
  ],
  "token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzYxMzUzMjgsImlzcyI6ImxvY2FsaG9zdCIsImV4cCI6MTU3NjEzNjIyOCwidXNlcklkIjoxfQ.7FODXGGJKioGQVX4ic0DJLoMIQTVUlsd4zFAJA4DAkg"
]

session support

Login received session support which allows login to create a session instead of returning aa JWT as done by default. To get started with session, just set the USE_SESSION setting or call the init method on auth session.

Leaf\Auth\Session::init();

Leaf\Auth::login("users", [
  "username" => $username,
  "password" => $password
]);

Or with functional mode:

auth()->useSession();

auth()->login("users", [
  "username" => $username,
  "password" => $password
]);

When the login succeeds, you'll be redirected to GUARD_HOME. You can configure the GUARD_HOME route to match the needs of your app.

In case there's something wrong and Auth can't sign the user in, it returns a falsy value.

$user = auth()->login("users", [
  "username" => $username,
  "password" => $password
]);

if (!$user) {
  // you can pass the auth errors into a view
  return $blade->render("pages.auth.login", [
    "errors" => auth()->errors(),
    "username" => $username,
    "password" => $password,
  ]);
}

Password Encoding

From v2.4-beta onwards, password encoding will no longer be available on the login method, you have to configure it among the Auth settings instead.

login has a 3rd parameter which is an array of validation rules for login data. You can checkout the form module for all the validation rules.

 



$rules = ["username" => "ValidUsername"];

$user = auth()->login("users", $loginData, $rules);

To get any errors, you need to call the errors method

if (!$user) {
  response()->throwErr(auth()->errors());
}

register

Register is a simple method used to create simple, secure user registrations. This option was basicRegister in earlier versions. It takes in a table to save users, the params(array) to save.

auth()->register("users", [
  "username" => "mychi.darko",
  "email" => "mychi@leafphp.dev",
  "field" => "value"
]);

REGISTER CLASS

Leaf auth now allows you to register users with the new Leaf\Auth\Register class. This will allows you to import only the register functionality without actually going through the whole auth class.

$user = auth()->register("users", [
  "username" => "mychi.darko",
  "email" => "mychi@leafphp.dev",
  "field" => "value"
]);

If the user is successfully saved, the user data is returned, if not, false is returned. You can get any error by calling the errors method.

$user = auth()->register("users", [
  "username" => "mychi.darko",
  "email" => "mychi@leafphp.dev",
  "field" => "value"
]); // returns false if failed

if ($user == false) {
  response()->throwErr(auth()->errors());
}

Uniques

Let's say you want to check whether the username a user just entered has been taken, you'd have to write a bunch of conditional code, making the code count larger and more error prone, right?

Well, register solves this problem smoothly. register has a 3rd parameter: an array of unique values which makes sure that the same value can't be saved twice.

$db->register("users",
  ["name" => "mychi", "email" => "m@m.com", "pass" => "1234"],
  ["name", "email"]
);

So, we're telling register to alert us if someone has already registered with the name mychi or the email m@m.com. This is because we passed ["name", "email"] as the 3rd param to register

With uniques, you can cut down on your whole app: For instance, if you know the exact data you'll be receiving in your app, let's say a username, email and password from a register form, you can do something like this:

app()->post("/register", function () {
  auth()->register(
    "users",
    request()->body(),
    ["username", "email"]
  );
});

So, we pass in the entire request body, which contains the username, email and password. Simple right?

For an even better way, you can make sure that only the data you need is going into the database. You can do this to retrieve only the fields you need.

// select only the username, email and password from the request body
$data = request()->get(["username", "email", "password"]);

auth()->register("users", $data);

The password encode option here has also been removed. Use the auth config above instead. The final parameter is now the validate param which is an array of rules to test the params.

app()->post("/register", function () use($app) {
  auth()->register(
    "users",
    request()->body(),
    ["username", "email"],
    ["email" => "email"]
  );
});

register session support

Just as with login, register now integrates with session. To turn this feature on, just set the USE_SESSION setting or call the useSession method.

auth()->useSession();

auth()->register("users", $credentials, [
  "username", "email"
]);

After a successful registration, you can redirect to GUARD_HOME or rather GUARD_LOGIN if you want the user to login after registration.

// set your login route...default is /auth/login
auth()->config("GUARD_LOGIN", "/login");

// Redirect to login after auth
auth()->config("SESSION_ON_REGISTER", false);

// Login automatically after registration
auth()->config("SESSION_ON_REGISTER", true);

In case there's something wrong and Auth can't register the user, it returns a falsy value.

$user = auth()->register("users", $credentials, [
  "username", "email"
]);

if (!$user) {
  // you can pass the auth errors into a view
  return $blade->render("pages.auth.register", [
    "errors" => auth()->errors(),
    "username" => $username,
    "email" => $email,
    "password" => $password,
  ]);
}

update

There's a login method, a register method, so why not a user update method? This method takes the stress out of updating a user's information. Update takes in 5 parameters:

  • The table to look for users
  • The data to update
  • Credentials to find user by
  • Unique values (optional)
  • Validation array (optional)
// data to update
$data = $request->get(["username", "email"]);

// credentials to find user by
$where = ["id" => 2];

// unique data
$uniques = ["username", "email"];

// validation
$validation = ["username" => "ValidUsername", "email" => "email"];

$user = auth()->update("users", $data, $where, $uniques, $validation);

USER CLASS

Leaf auth now allows you to register users with the new Leaf\Auth\USER class. This will allows you to import only the update functionality without actually going through the whole auth class.

$user = Leaf\Auth\User::update("users", [
  "username" => "mychi.darko",
  "email" => "mychi@leafphp.dev",
  "field" => "value"
], ["id" => "1"]);

Something little: Uniques in update work a bit different from register, in update, Leaf tries to find another user which isn't the current user that has the same credentials. So if there's no other user with that same param value, the unique test passes. In short, the current user is excluded from the users to check for same credentials

update session support

Update also reeived session support. When a user is updated, the user is updated in the session and the updated user is also returned.

$user = auth()->update("users", $data, $where, $uniques);

user

When tokens are added inside requests, you generally have to decode the token and query your database with the id returned to get the current user. Although Leaf Auth makes it really simple, it can get even simpler; by calling a single method. It takes in one parameter, the table to look for users.

$user = auth()->user("users");
return $user["name"];

In v2.4 beta, the table is set to users by default. So you can simply do this:

$user = auth()->user();

We can catch any errors that occur, from fetching the user, working with the token...

$user = auth()->user() ?? $request->throwErr(auth()->errors());

user also takes in a second parameter, which is an array of items to hide from the user array.

$user = auth()->user("users", ["id", "password"]);

id

This is a method that decodes a token and returns the user_id field encoded in it.

$user_id = auth()->id();

Leaf Auth now uses the Leaf\Helpers\Authentication package to provide solutions for token authentication. This provides a simple way to work with manual authentication and tokens. All methods here are now available in Leaf\Auth.

$payload = auth()->validate($token);
Auth v1 has loaded