DZone
Security Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Security Zone > Building an App With Nette and Adding Authentication, Part 2

Building an App With Nette and Adding Authentication, Part 2

In this article, a web developer uses a freely available tool to add authentication to a web application, using PHP to implement our security layer.

Prosper Otemuyiwa user avatar by
Prosper Otemuyiwa
·
Oct. 16, 17 · Security Zone · Tutorial
Like (2)
Save
Tweet
2.43K Views

Join the DZone community and get the full member experience.

Join For Free

Welcome back! If you missed Part 1 in which we built a web app using Nette, check it out here. 

Setting Up Authentication With Auth0

Auth0 issues JSON Web Tokens on every login for your users. This means that you can have a solid identity infrastructure, including single sign-on, user management, support for social identity providers (Facebook, GitHub, Twitter, etc.), enterprise identity providers (Active Directory, LDAP, SAML, etc.) and your own database of users with just a few lines of code.

We can easily set up authentication in our Nette apps by using Auth0. If you don't already have an Auth0 account, sign up for one now for free.

  • Navigate to the Auth0 management dashboard.
  • Create a new client and select the type of app as Regular Web Applications.
  • Take note of the client_id, domain, and secret. You'll need it soon.

Step 1: Install and Configure Auth0 PHP Package

Go ahead and install the official Auth0 PHP Plugin via composer.

composer require auth0/auth0-php

Step 2: Register Auth0 as a Nette Service

Head over to app/config/config.neon and add the following under services::

auth0: Auth0\SDK\Auth0([
    'domain' : '{AUTH0_TENANT_DOMAIN}',
    'client_id' : '{AUTH0_REGULAR_WEBSITE_CLIENT_ID}',
    'client_secret' : '{AUTH0_REGULAR_WEBSITE_CLIENT_SECRET}',
    'redirect_uri' : 'http://localhost:8000/callback',
    'persist_user' : false,
    'store': false
    'debug' : true
  ])

We need to create a new presenter, AuthenticationPresenter to handle our authentication logic.

app/presenters/AuthenticationPresenter.php

<?php

namespace App\Presenters;

use \Tracy\Debugger;
use \Nette\Http\IResponse;
use \Nette\Application\UI\Presenter;
use \Nette\Application\BadRequestException;
use \Nette\Security\AuthenticationException;

class AuthenticationPresenter extends Presenter {

  /** @var \Auth0\SDK\Auth0 @inject */
  public $auth0;

  public function actionLogin() {
    $this->auth0->login();
  }

  public function actionLogout() {
    $this->auth0->logout();
    $this->getUser()->logout();

    $this->redirect('Homepage:');
  }

  public function actionCallback($code) {
    try {
      $this->getUser()->login($code);

      $this->redirect('Homepage:');
    } catch (AuthenticationException $e) {
      Debugger::log($e, Debugger::ERROR);
      throw new ForbiddenRequestException('User not authenticated', IResponse::S403_FORBIDDEN, $e);
    }
  }

}

In the code above, you can see that the Auth0 service is being injected into the presenter using the @inject annotation. The actionLogin method is responsible for invoking the login function that will redirect the user to the Auth0 hosted login page.

The actionLogout method is responsible for clearing the sessions and any Auth0 data stored in the app. It logs the user out and redirects back to the home page.

The actionCallback method is responsible for handling the authentication flow. When the authentication is successful from Auth0, it performs a client credential exchange and returns an authorization code.

Step 3: Configure Auth0 Authenticator

Head over to app/config/config.neon and add the following under services::

services:
  auth0Authenticator: App\Model\Auth0Authenticator

Now, create a model/Auth0Authenticator.php file inside the app directory.

Add code to the file like this:

<?php

namespace App\Model;

use \Tracy\Debugger;
use \Auth0\SDK\Auth0;
use \Nette\Security\Identity;
use \Nette\Security\IIdentity;
use \Nette\Security\IAuthenticator;
use \Nette\Security\AuthenticationException;

class Auth0Authenticator implements IAuthenticator {

  /** @var \Auth0\SDK\Auth0 */
  private $auth0;

  public function __construct(Auth0 $auth0) {
    $this->auth0 = $auth0;
  }

  /**
   *  @param $args[0] Authorization Code
   *  @throws AuthenticationException
   */
  public function authenticate(array $args) : IIdentity {
    if (sizeof($args) > 0 && !empty($args[0])) {
      $code = $args[0];

      if ($this->auth0->exchange()) {
        return new Identity($this->auth0->getUser()['email'], NULL, $this->auth0->getUser());
      } else {
        throw new AuthenticationException('Auth0 code not exchanged successfully; user not authenticated.');
      }
    } else {
      throw new AuthenticationException('Auth0 code not provided; user not authenticated.');
    }
  }

}

This is where the credentials exchange happen, and the user info is gotten from Auth0 and injected into Nette via the Identity class.

Step 4: Configure Routing

The default login and logout routes are /authentication/login, and /authentication/logout respectively. We'll change them to /login and /logout respectively.

Open up app/router/RouterFactory.php and add the following routes:

...
$router[] = new Route('login', 'Authentication:login');
$router[] = new Route('logout', 'Authentication:logout');
$router[] = new Route('callback', 'Authentication:callback');
$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');

We also added the callback route.

Note: Head over to your Auth0 client and configure the callback route in Allowed Callback URLs.

Add Callback Route

Step 5: Configure The View

Head over to app/presenters/templates/Homepage/default.latte and replace everything with the code below:

{block content}
    <h1 n:block="title"></h1>

    <div class="container">
      <div class="row">
          <div class="col-md-10 col-md-offset-1">
            {if $user->isLoggedIn()}
            <div class="panel panel-info">
              <div class="panel-heading">You are now logged in, {$user->getIdentity()->nickname} </div>
            </div>
            {/if}
            <div class="panel panel-success">
              <div class="panel-heading">List of Game of Thrones Characters</div>
              {if $user->isLoggedIn()}
                <table class="table">
                    <tr>
                        <th>Character</th>
                        <th>Real Name</th>
                    </tr>
                    {foreach $characters as $key => $value}
                      <tr>
                        <td>{$key}</td><td>{$value}</td>
                      </tr>
                    {/foreach}
                </table>
              {/if}
            </div>
            {if !$user->isLoggedIn()}
              <a href="{link Authentication:login}" class="btn btn-info"> You need to login to see the list ���� >></a>
            {/if}
            {if $user->isLoggedIn()}
              <a href="{link Authentication:logout}" class="btn btn-info"> Logout >></a>
            {/if}
          </div>
      </div>
    </div>
{/block}

In the code above, we have some variables and function call:

  • $user->isLoggedIn(): The $user variable is an object that is injected into the templates by default from Nette presenters and components. It represents the user. There are methods that can be called on it such as isLoggedIn, login, logout, etc. Here, we use to determine if the user is logged in or not.
  • $user->getIdentity()->nickname: The $user->getIdentity() function call is used to get the identity of the user. Identity represents a set of user information, as returned by the authenticator in use. In our app, we used a custom authenticator, auth0Authenticator. And that gives us the full range of user information that Auth0 returns. Therefore, we can access every Auth0 user attribute like so:
$user->getIdentity()->nickname // returns user name
$user->getIdentity()->email // returns user email

Note: Check out Nette's Access control for a deeper understanding of how the user object works.

Step 6: Run Your App

Now that everything is in place, go ahead and run your app.

Homepage

Auth0 Hosted Login

User is logged in

Wrapping Up

Well done! You have just built your first app with Nette. It focuses on simplicity, clarity and getting work done. As we saw in this tutorial, you can easily add authentication to your Nette apps.

This tutorial is designed to help you get started on building and adding authentication to your own apps with the Nette framework. You can leverage the knowledge gained here to build bigger and better apps.

Please, let me know if you have any questions or observations in the comment section. 

app authentication

Published at DZone with permission of Prosper Otemuyiwa, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Making Your SSR Sites 42x Faster With Redis Cache
  • Image Classification Using SingleStore DB, Keras, and Tensorflow
  • Cloud-Based Integrations vs. On-Premise Models
  • How to Test JavaScript Code in a Browser

Comments

Security Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo