Download the PHP package aura/auth without Composer
On this page you can find all versions of the php package aura/auth. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Package auth
Short Description Provides a unified interface to authenticate a user with local or remote authentication systems.
License BSD-2-Clause
Homepage https://github.com/auraphp/Aura.Auth
Informations about the package auth
Aura.Auth
Provides authentication functionality and session tracking using various adapters; currently supported adapters are:
- Apache htpasswd files
- SQL tables via the PDO extension
- IMAP/POP/NNTP via the imap extension
- LDAP and Active Directory via the ldap extension
- OAuth via customized adapters
Note that the purpose of this package is only to authenticate user credentials. It does not currently, and probably will not in the future, handle user account creation and management. That is more properly the domain of application-level functionality, or at least a separate Aura bundle.
Foreword
Installation
This library requires PHP 7.2 or later, and has no userland dependencies.
It is installable and autoloadable via Composer as aura/auth.
Alternatively, download a release or clone this repository, then require or include its autoload.php file.
Quality
To run the unit tests at the command line, issue composer install
and then vendor/bin/phpunit
at the package root. This requires Composer to be available as composer
.
This library attempts to comply with PSR-1, PSR-2, and PSR-4. If you notice compliance oversights, please send a patch via pull request.
Community
To ask questions, provide feedback, or otherwise communicate with the Aura community, please join our Google Group, follow @auraphp on Twitter, or chat with us on #auraphp on Freenode.
Getting Started
Instantiation
To track authentication state and related information, create an Auth object using the AuthFactory.
You can retrieve authentication information using the following methods on the Auth instance:
-
getUserName()
: returns the authenticated username string -
getUserData()
: returns the array of optional arbitrary user data -
getFirstActive()
: returns the Unix time of first activity (login) -
getLastActive()
: return the Unix time of most-recent activity (generally that of the current request) -
getStatus()
: returns the current authentication status constant. These constants are:-
Status::ANON
-- anonymous/unauthenticated -
Status::IDLE
-- the authenticated session has been idle for too long -
Status::EXPIRED
-- the authenticated session has lasted for too long in total Status::VALID
-- authenticated and valid
-
isAnon()
,isIdle()
,isExpired()
,isValid()
: these return true or false, based on the current authentication status.
You can also use the set*()
variations of the get*()
methods above to force the Auth object to whatever values you like. However, because the values are stored in a $_SESSION
segment, the values will not be retained if a session is not running.
To retain values in a session, you can start a session by force with session_start()
on your own. Alternatively, it would be better to use one of the Aura.Auth package services to handle authentication and session-state management for you.
Services
This package comes with three services for dealing with authentication phases:
-
LoginService to log in and start (or resume) a session,
-
LogoutService to log out and remove the username and user data in the session (note that this does not destroy the session), and
- ResumeService to resume a previously-started session.
You can create each by using the AuthFactory. For now, we will look at how to force login and logout; later, we will show how to have the service use a credential adapter.
Forcing Login
You can force the Auth object to a logged-in state by calling the LoginService forceLogin()
method with a user name and optional arbitrary user data.
Using forceLogin()
has these side effects:
-
it starts a new session if one has not already been started, or resumes a previous session if one exists
- it regenerates the session ID
The specified user name and user data will be stored in a $_SESSION
segment, along with an authentication status of Status::VALID
.
Note that forceLogin()
does not check any credential sources. You as the application owner are forcing the Auth object to a logged-in state.
Forcing Logout
You can force the Auth object to a logged-out state by calling the LogoutService forceLogout()
method.
Using forceLogout()
has these side effects:
-
it clears any existing username and user data from the
$_SESSION
segment - it regenerates the session ID
Note that forceLogout()
does not check any credential sources. You as the application owner are forcing the Auth object to a logged-out state.
Note also that this does not destroy the session. This is because you may have other things you need in the session memory, such as flash messages.
Resuming A Session
When a PHP request ends, PHP saves the $_SESSION
data for you. However, on the next request, PHP does not automatically start a new session for you, so $_SESSION
is not automatically available.
You could start a new session yourself to repopulate $_SESSION
, but that will incur a performance overhead if you don't actually need the session data. Similarly, there may be no need to start a session when there was no session previously (and thus no data to repopulate into $_SESSION
). What we need is a way to start a session if one was started previously, but avoid starting a session if none was started previously.
The ResumeService exists to address this problem. When you call the resume()
method on the ResumeService, it examines $_COOKIE
to see if a session cookie is present:
-
If the cookie is not present, it will not start a session, and return to the calling code. This avoids starting a session when there is no
$_SESSION
data to be populated. -
If the cookie is present, the ResumeService will start a session, thereby repopulating
$_SESSION
. Then it will update the authentication status depending on how long the session has been in place:-
If the session has been idle for too long (i.e., too much time has passed since the last request), the ResumeService will log the user out automatically and return to the calling code.
-
If the session has expired (i.e., the total logged-in time has been too long), the ResumeService will likewise log the user out automatically and return to the calling code.
- Otherwise, the ResumeService will update the last-active time on the Auth object and return to the calling code.
-
Generally, you will want to invoke the ResumeService at the beginning of your application cycle, so that the session data becomes available at the earliest opportunity.
Adapters
Forcing the Auth object to a particular state is fine for when you want to exercise manual control over the authentication status, user name, user data, and other information. However, it is more often the case that you will want to check user credential input (username and password) against a credential store. This is where the Adapter classes come in.
To use an Adapter with a Service, you first need to create the Adapter, then pass it to the AuthFactory new*Service()
method.
Htpasswd Adapter
Instantiation
To create an adapter for Apache htpasswd files, call the AuthFactory newHtpasswdAdapter()
method and pass the file path of the Apache htpasswd file.
This will automatically use the HtpasswdVerifier to check DES, MD5, and SHA passwords from the htpasswd file on a per-user basis.
Service Integration
You can then pass the Adapter to each Service factory method like so:
To attempt a user login, pass an array with username
and password
elements to the LoginService login()
method along with the Auth object:
For more on LoginService idioms, please see the Service Idioms section. (The LogoutService and ResumeService do not need credential information.)
IMAP/POP/NNTP Adapter
Instantiation
To create an adapter for IMAP/POP/NNTP servers, call the AuthFactory newImapAdapter()
method and pass the mailbox specification string, along with any appropriate option constants:
N.b.: See the imap_open() documentation for more variations on mailbox specification strings.
Service Integration
You can then pass the Adapter to each Service factory method like so:
To attempt a user login, pass an array with username
and password
elements to the LoginService login()
method along with the Auth object:
For more on LoginService idioms, please see the Service Idioms section. (The LogoutService and ResumeService do not need credential information.)
LDAP Adapter
Instantiation
To create an adapter for LDAP and Active Directory servers, call the AuthFactory newLdapAdapter()
method and pass the server name with a distinguished name (DN) format string:
N.b.: The username will be escaped and then passed to the DN format string via sprintf(). The completed DN will be used for binding to the server after connection.
Service Integration
You can then pass the Adapter to each Service factory method like so:
To attempt a user login, pass an array with username
and password
elements to the LoginService login()
method along with the Auth object:
For more on LoginService idioms, please see the Service Idioms section. (The LogoutService and ResumeService do not need credential information.)
PDO Adapter
Instantiation
To create an adapter for PDO connections to SQL tables, call the AuthFactory newPdoAdapter()
method and pass these parameters in order:
-
a PDO connection instance
-
a indication of how passwords are hashed in the database:
-
if a
PASSWORD_*
constant from PHP 5.5 and up, it is treated aspassword_hash()
algorithm for a PasswordVerifier instance (this is the preferred method) -
if a string, it is treated as a
hash()
algorithm for a HashVerifier instance - otherwise, it is expected to be an implementation of VerifierInterface
-
-
an array of column names: the first element is the username column, the second element is the hashed-password column, and additional columns are used as extra user information to be selected and returned from the database
-
a
FROM
specification string to indicate one or more table names, with any otherJOIN
clauses you wish to add - an optional
WHERE
condition string; use this to add extra conditions to theSELECT
statement built by the adapter
Here is a legacy example where passwords are MD5 hashed in an accounts table:
Here is a modern, more complex example that uses bcrypt instead of md5, retrieves extra user information columns from joined tables, and filters for active accounts:
(The additional information columns will be retained in the session data after successful authentication.)
Service Integration
You can then pass the Adapter to each Service factory method like so:
To attempt a user login, pass an array with username
and password
elements to the LoginService login()
method along with the Auth object:
For more on LoginService idioms, please see the Service Idioms section. (The LogoutService and ResumeService do not need credential information.)
Custom Adapters
Although this package comes with multiple Adapter classes, it may be that none of them fit your needs.
You may wish to extend one of the existing adapters to add login/logout/resume behaviors. Alternatively, you can create an Adapter of your own by implementing the AdapterInterface on a class of your choosing:
You can then pass an instance of the custom adapter when creating services through the AuthFactory methods:
OAuth Adapters
Should you desire to handle your authentication through a 3rd party service that uses OAuth 2.0, you'll need to write an adapter that implements and provide your own implementation for fetching the access token and user information. Your implementation can be something you've written yourself or it can be an existing OAuth2 client.
The following example will demonstrate how you'd go about creating this adapter using the PHP League's OAuth2 Client. We'll also be using Github as the service provider for this example.
As you can see in the code, your adapter will be accepting a client as a parameter and using that client to fulfill the \Aura\Auth\Adapter\AdapterInterface contract. This adapter would be commonly used in an OAuth2 Callback process. Essentially, once you provide your credentials and authenticate with the 3rd Party service (in this case Github), you will be redirected back to a script on your server where you'll have to verify that you sent the request by sending an verification code back to the service. This is why it's a good idea to use a good OAuth2 client in lieu of writing your own. Below is an example of what this OAuth2 callback code might look like.
The fact that not every 3rd Party Service returns data the same way means it's not reasonable for Aura to try to handle every different data set out of the box. By writing this little bit of code, you can easily implement Aura Auth for your 3rd Party OAuth2 services.
Service Idioms
Resuming A Session
This is an example of the code needed to resume a pre-existing session. Note that the echo
statements are intended to explain the different resulting states of the resume()
call, and may be replaced by whatever logic you feel is appropriate. For example, you may wish to redirect to a login page when a session has idled or expired.
N.b.: Instead of creating the Auth and ResumeService objects by hand, you may wish to use a dependency injection container such as Aura.Di to retain them for shared use throughout your application.
Logging In
This is an example of the code needed to effect a login. Note that the echo
and $log
statements are intended to explain the different resulting states of the login()
call, and may be replaced by whatever logic you feel is appropriate; in particular, you should probably not expose the exact nature of the failure, to help mitigate brute-force attempts.
N.b.: Instead of creating the Auth and LoginService objects by hand, you may wish to use a dependency injection container such as Aura.Di to retain them for shared use throughout your application.
Alternatively, you may wish to use credentials from the HTTP Authorization: Basic
headers instead of using $_POST
or other form-related inputs. On Apache mod_php
you might use the auto-populated $_SERVER['PHP_AUTH_*']
values:
On other servers you may need to extract the credentials from the Authorization: Basic
header itself:
Logging Out
This is an example of the code needed to effect a logout. Note that the echo
statements are intended to explain the different resulting states of the logout()
call, and may be replaced by whatever logic you feel is appropriate.
N.b.: Instead of creating the Auth and LogoutService objects by hand, you may wish to use a dependency injection container such as Aura.Di to retain them for shared use throughout your application.
Custom Services
You are not restricted to the login, logout, and resume services provided by this package. However, if you build a service of your own, or if you extend one of the provided services, you will have to instantiate that customized service object manually, instead of using the AuthFactory. This can be tedious but is not difficult, especially when using a dependency injection container system such as Aura.Di.
Session Management
The Service objects use a Session object to start sessions and regenerate session IDs. (Note that they do not destroy sessions.) The Session object uses the native PHP session_*()
functions to manage sessions.
Custom Sessions
If you wish to use an alternative means of managing sessions, implement the SessionInterface on an object of your choice. One way to do this is by by wrapping a framework-specific session object and proxying the SessionInterface methods to the wrapped object:
Then pass that custom session object to the AuthFactory instantiation:
The factory will pass your custom session object wherever it is needed.
Working Without Sessions
In some situations, such as with APIs where credentials are provided with every request, it may be beneficial to avoid sessions altogether. In this case, pass a NullSession and NullSegment to the AuthFactory:
With the NullSession, no session will ever be started, and no session ID will be created or regenerated. Likewise, no session will ever be resumed, because it will never have been saved at the end of the previous request. Finally, PHP will never create a session cookie to send in the response.
Similarly, the NullSegment retains authentication information in an object property instead of in a $_SESSION
segment. Unlike the normal Segment, which only retains data when $_SESSION
is present, the NullSegment will always retain data that is set into it. When the request is over, all information retained in the NullSegment will disappear.
When using the NullSession and NullSegment, you will have to check credentials via the LoginService login()
or forceLogin()
method on each request, which in turn will retain the authentication information in the Segment. In an API situation this is often preferable to managing an ongoing session.
N.b. In an API situation, the credentials may be an API token, or passed as HTTP basic or digest authentication headers. Pass these to the adapter of your choice.
DI Configuration
Here are some hints regarding configuration of Aura.Auth via Aura.Di.