Auth0-php regular web app + API

I’m new to auth0, so sorry if my question seams stupid!

I wish to make a single page application, that can access data from a database and some other data sources. To secure access to these data sources, my idea was to make an API that provides access to the data.

I have used the guide: “quickstart/backend/php/interactive”

Then I have made a small test application (I used the “Regular web application” demo)

github → auth0-samples/auth0-php-web-app/

I have uploaded to my webserver here: https://bom-test.bjerge.com/

I log in and get a “Access Token”, in my API at manage.auth0 / dashboard i have added my test application under “machine to machine applications” so its Authorized.

I then use “Postman” to make test connection to my api.

Using GET - https://vismaapi.bjerge.com/api/private and adding to the header a key “token” with the value of the access token I get from my test application.

But I don’t get access.

What am I doing wrong here, and do you have a better/smarter way for me to achieve what I need?

Hey @martin.bjerge ! Thanks for reaching out to us here in the Community and sorry for relatively late response!

Looking quickly at your project description, here’s my hint: In order to run a request to your API with a gained access token, please use the following Authorization header:

curl --request GET \
  --url https://{your api URL}\
  --header 'authorization: Bearer {accessToken}' \
  --header 'content-type: application/json'

So the “prefix” before the access token value itself has to be “Bearer” and not “token”.

You can read more about the grant flow recommended for regular web apps + API here (you can check how, on each step, requests looks like, also in PHP syntax).

Please let me know if I can help more! Have a good day!

1 Like

Thank you so very much for getting back to me, and trying to help :slight_smile:
But I’m sorry as i still can’t make this work…

This is my very simple API code (PHP):

<?php

  declare(strict_types=1);

  require('vendor/autoload.php');

  use Auth0\SDK\Auth0;
  use Auth0\SDK\Configuration\SdkConfiguration;

  $configuration = new SdkConfiguration(
    strategy: SdkConfiguration::STRATEGY_API,
    domain: 'dev-lhy1lkv44s5uzgen.us.auth0.com',
    clientId: 'kcHlfgahbmoGz4fj1drro8lohImDpB86',
    clientSecret: 'a7RmcOIpZwaD-dIOLufmZmnrjf_YSQ0Ual4oB_21dIRA7ODynmBGUiNzgWVwLkYk',
    audience: ['https://vismaapi.bjerge.com']
  );

  $sdk = new Auth0($configuration);

  $token = $sdk->getBearerToken(
    get: ['token'],
    server: ['Authorization']
  );

  echo "<br>Token: ";
  echo $token;
  echo "<br>";
  //print_r($token);
  //require('router.php');

(Know i chould not share all the keys, but i will rotate anyway when i have it up and running)

I then get a “Access Token” from https://bom-test.bjerge.com/, here I have the demo app running.

it’s running with these keys:

# Your Auth0 application's Client ID
AUTH0_CLIENT_ID=kcHlfgahbmoGz4fj1drro8lohImDpB86

# The URL of your Auth0 tenant domain
AUTH0_DOMAIN=dev-lhy1lkv44s5uzgen.us.auth0.com

# Your Auth0 application's Client Secret
AUTH0_CLIENT_SECRET=a7RmcOIpZwaD-dIOLufmZmnrjf_YSQ0Ual4oB_21dIRA7ODynmBGUiNzgWVwLkYk

# A long, secret value used to encrypt the session cookie
AUTH0_COOKIE_SECRET={ace44571978a72f7592ff4633d98a14695378dcd5af5eb8fb2b3591fec4fd651}
# AUTH0_AUDIENCE=ace44571978a72f7592ff4633d98a14695378dcd5af5eb8fb2b3591fec4fd651
# AUTH0_CALLBACK_URL=https://bom-test.bjerge.com/

Then i call my api, this time tryed from Python :wink:

import http.client

conn = http.client.HTTPSConnection("vismaapi.bjerge.com")

headers = {
    'content-type': "application/json",
    'authorization': "Bearer {eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYtbGh5MWxrdjQ0czV1emdlbi51cy5hdXRoMC5jb20vIn0..SprgtmYCFAUG6HEf.bkdpHYFo7ruq-CKY0VSsCa6qrTfb8awLwIMEOX8xKjOIA4Jw3vaZJqryaNZgLOCKFSeOo2KbAFs8c-AenXg5aUE3n85ChzrpjRvttjKllpWEgn_TwIIaIagMb05NTCDe7fmoXmxWf8ZNs5ZnkiWj5CWkleqFtQCRAdAVJ1YiXlh-YQqvqj99HTr8NEg4Izj9YHMUr0TBcUOrgn3XTHgpjSGdfzVvnv8QiRntCR0JcfI3B2Jpsif0QkTEKHVqjTaFhQbTZvyRoJW1HzU4oZjm0cdurr7OyJbGNhg69OEOzHEVVcBKQfg90gPobDbFZk7wCzzpgXLon3TIapeeY8B5cJnuC5Ah1PKNeLyDNpotd2dUTuScH5g.yHDK1-2V0ERM6QrUcGTiNA}"
    }

conn.request("GET", "/", headers=headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

The Token value is still empty/null!
<br>Token: <br>

Hey there!
Thanks for sharing your steps, and one quick question before digging more into it:

Are you including the curly brackets at the beginning and the end of the access token?

They shouldn’t to be included at all in the authorisation header value. Can you please try again once the curly brackets are deleted from the beginning and the end of the access token value?
Thanks!

1 Like

I have tried, with and without curly brackets, nothing worked :slight_smile:

I have also tryed using postman:

Same result.

Alrighty, thanks for the Postman request screenshot!

I decoded your access token (you can do the same here) and it looks like it has some missing parts or is malformed.

Strange thing is that your Postman request got 200 status code mining successful (mining you got access to your API).

I have to dive deeper into all your steps to understand on what point the issue occurs and how to do it properly - will update you soon.

In the meantime, could you please apply the following step of adding scopes for this API in your Auth0 tenant and let me know the result?

Scopes mean specific API endpoints with their HTTP methods, for which the access token has been requested in the previous steps.
Scopes can be defined in your Auth0 tenant under the API’s Permissions tab.

Thanks and let’s stay in touch!

1 Like

Hey there @martin.bjerge !

After digging more into it, let me please share some remarks:

  1. I’m not sure if the way you print out the $token class properties in your API code is correct (from the perspective of the auth0-php SDK).
    To exclude this as a reason of receiving null for this (which makes you assuming you didn’t get access), could you please follow the guidline more strictly, specifically:
  • To your index.php, please add:

require('router.php');

  • Create a router.php file and add:
<?php

  declare(strict_types=1);

  use Steampixel\Route;

  function routeResponse(
    array $response
  ) {
    header('Content-Type: application/json');
    print(json_encode($response, JSON_PRETTY_PRINT));
  }

  Route::add('/api/public', function() use ($token) {
    routeResponse([
      'message' => 'Hello from a public endpoint! You don\'t need to be authenticated to see this.',
      'token' => $token
    ]);
  });
  1. Once adding the above changes, can you please generate a new access token and test it again against your API (https://vismaapi.bjerge.com/api/public)?
    Access token are valid for a specified timeframe, in your case:

Please let me know if that helped or reach out with results! Thanks! :slight_smile:

1 Like

Hi, i belive i found the reson for the issue :slight_smile:

It looks like i get a Opaque tokens and not a JSON Web Token (JWT).

From this post:

To get the JWT i added this code:

        echo "<h2>Get JWT Token</h2>";

        $curl = curl_init();

        curl_setopt_array($curl, [
          CURLOPT_URL => "https://".$_ENV['AUTH0_DOMAIN']."/oauth/token",
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_ENCODING => "",
          CURLOPT_MAXREDIRS => 10,
          CURLOPT_TIMEOUT => 30,
          CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
          CURLOPT_CUSTOMREQUEST => "POST",
          CURLOPT_POSTFIELDS => "grant_type=client_credentials&client_id=".$_ENV['AUTH0_CLIENT_ID']."&client_secret=".$_ENV['AUTH0_CLIENT_SECRET']."&audience=".$_ENV['AUTH0_AUDIENCE'],
          CURLOPT_HTTPHEADER => [
            "content-type: application/x-www-form-urlencoded"
          ],
        ]);
        
        $response = curl_exec($curl);
        $err = curl_error($curl);
        
        curl_close($curl);
        
        if ($err) {
          echo "cURL Error #:" . $err;
        } else {
            $response = json_decode($response);
            echo $response->access_token;
        }

So now my full test app looks like this:

<?php

declare(strict_types=1);

use Auth0\Quickstart\Application;
use Auth0\Quickstart\Contract\QuickstartExample;
use Auth0\SDK\Auth0;
use Auth0\SDK\Configuration\SdkConfiguration;
use Steampixel\Route;


 // Set app root.
 define('APP_ROOT', realpath(__DIR__ . DIRECTORY_SEPARATOR));

 // The following globals don't get set during tests: apply some safe defaults.
 if (! isset($_SERVER['SERVER_PORT'])) {
     $_SERVER['SERVER_PORT'] = 80;
 }
 
 if (! isset($_SERVER['SERVER_NAME'])) {
     $_SERVER['SERVER_NAME'] = '127.0.0.1';
 }
 
 if (! isset($_SERVER['REQUEST_URI'])) {
     $_SERVER['REQUEST_URI'] = '/';
 }
 
// Import the files necessary for our Quickstart Application.
foreach ([
    'vendor/autoload.php', // Composer autoloader, for our dependencies, such as the SDK itself.

    // These classes are application boilerplate and not directly relevant to SDK usage:
    //'src/ApplicationRouter.php',
    //'src/ApplicationTemplates.php',
    //'src/ApplicationErrorHandler.php',

    // Import our Application class, where our app logic resides, and where we'll make our SDK calls.
    //'src/Application.php',
] as $import) {
    require_once join(DIRECTORY_SEPARATOR, [APP_ROOT, $import]);
}

// Load configuration from .env file in project root.
(Dotenv\Dotenv::createImmutable(APP_ROOT))->load();

// Now instantiate the Auth0 class with our configuration:
$auth0 = new \Auth0\SDK\Auth0([
    'domain' => $_ENV['AUTH0_DOMAIN'],
    'clientId' => $_ENV['AUTH0_CLIENT_ID'],
    'clientSecret' => $_ENV['AUTH0_CLIENT_SECRET'],
    'cookieSecret' => $_ENV['AUTH0_COOKIE_SECRET']
]);
//     'audience' => $_ENV['AUTH0_AUDIENCE']


// Define route constants:
define('ROUTE_URL_INDEX', rtrim($_ENV['AUTH0_BASE_URL'], '/'));
define('ROUTE_URL_LOGIN', ROUTE_URL_INDEX . '/login');
define('ROUTE_URL_CALLBACK', ROUTE_URL_INDEX . '/callback');
define('ROUTE_URL_LOGOUT', ROUTE_URL_INDEX . '/logout');


Route::add('/', function() use ($auth0) {
    $session = $auth0->getCredentials();
  
    if ($session === null) {
        // The user isn't logged in.
        echo '<p>Please <a href="/login">log in</a>.</p>';
        return;
    } else {
        // The user is logged in.
        echo "<h2>Session data ouput</h2>";
        echo '<pre>';
        print_r($session->user);
        echo '</pre>';
        // AccessToken
        echo '<pre>';
        print_r($session->accessToken);
        echo '</pre>';
        
        echo "<h2>Get JWT Token</h2>";

        $curl = curl_init();

        curl_setopt_array($curl, [
          CURLOPT_URL => "https://".$_ENV['AUTH0_DOMAIN']."/oauth/token",
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_ENCODING => "",
          CURLOPT_MAXREDIRS => 10,
          CURLOPT_TIMEOUT => 30,
          CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
          CURLOPT_CUSTOMREQUEST => "POST",
          CURLOPT_POSTFIELDS => "grant_type=client_credentials&client_id=".$_ENV['AUTH0_CLIENT_ID']."&client_secret=".$_ENV['AUTH0_CLIENT_SECRET']."&audience=".$_ENV['AUTH0_AUDIENCE'],
          CURLOPT_HTTPHEADER => [
            "content-type: application/x-www-form-urlencoded"
          ],
        ]);
        
        $response = curl_exec($curl);
        $err = curl_error($curl);
        
        curl_close($curl);
        
        if ($err) {
          echo "cURL Error #:" . $err;
        } else {
            $response = json_decode($response);
            echo $response->access_token;
        }

        echo "<h2>Access API</h2>";
        $curl = curl_init();

        curl_setopt_array($curl, array(
          CURLOPT_URL => "https://vismaapi.bjerge.com/api/private",
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_ENCODING => "",
          CURLOPT_MAXREDIRS => 10,
          CURLOPT_TIMEOUT => 30,
          CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
          CURLOPT_CUSTOMREQUEST => "GET",
          CURLOPT_HTTPHEADER => array(
            "authorization: Bearer $response->access_token"
          ),
        ));
        
        $response = curl_exec($curl);
        $err = curl_error($curl);
        
        curl_close($curl);
        
        if ($err) {
          echo "cURL Error #:" . $err;
        } else {
          echo $response;
        }


        echo '<p>You can now <a href="/logout">log out</a>.</p>';
    }
  });

Route::add('/login', function() use ($auth0) {
    // It's a good idea to reset user sessions each time they go to login to avoid "invalid state" errors, should they hit network issues or other problems that interrupt a previous login process:
    $auth0->clear();

    // Finally, set up the local application session, and redirect the user to the Auth0 Universal Login Page to authenticate.
    header("Location: " . $auth0->login(ROUTE_URL_CALLBACK));
    exit;
});

Route::add('/callback', function() use ($auth0) {
    // Have the SDK complete the authentication flow:
    $auth0->exchange(ROUTE_URL_CALLBACK);

    // Finally, redirect our end user back to the / index route, to display their user profile:
    header("Location: " . ROUTE_URL_INDEX);
    exit;
});


Route::add('/logout', function() use ($auth0) {
    // Clear the user's local session with our app, then redirect them to the Auth0 logout endpoint to clear their Auth0 session.
    header("Location: " . $auth0->logout(ROUTE_URL_INDEX));
    exit;
});

// This tells our router that we've finished configuring our routes, and we're ready to begin routing incoming HTTP requests:
Route::run('/');
3 Likes

Now i have it up and running, and i have placed a copy of my sample code here:

3 Likes

It’s awesome to have you in our Community Martin @martin.bjerge ! Thanks a lot for your contribution!

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.