Laravel bindings for popular Northwestern SOA services.

v2.0.1 2019-06-13 13:04 UTC


This package provides simple classes for accessing popular SOA services from Laravel applications.

Service Prerequisites
WebSSO None
DirectorySearch Data steward approval, Apigee API key
EventHub Queues, Apigee API Key


You can install the package via composer:

composer require northwestern-sysdev/laravel-soa

Publish the config file:

php artisan vendor:publish --provider="Northwestern\SysDev\SOA\Providers\NuSoaServiceProvider"

And finally, add the options to your .env file (and don't forget to update .env.example for the rest of your team!) for the services you want to use:

# DirectorySearch

# EventHub


The API objects should be injected by the Laravel service container. This ensures the configuration is injected into the objects for you:


namespace App\Http\Controllers;

use Northwestern\SysDev\SOA\WebSSO;

class MyController extends Controllers
    protected $sso;

    public function __construct(WebSSO $sso)
        $this->sso = $sso;


If you are ever in a spot where injection is unavailable, you can always call resolve yourself. This is particularly handy in the tinker console:

$pub = resolve(Northwestern\SysDev\SOA\WebSSO::class);

For troubleshooting, each API has a getLastError() method. dd()ing the API object should give you everything you'll need, including the request body and URL.


The webSSO API bindings will resolve the value of an openAMssoToken cookie into a NetID.

This is merely an API binding; if you want a pre-made workflow for logging in, check out the northwestern-sysdev/laravel-websso package.


namespace App\Http\Controllers;

use Northwestern\SysDev\SOA\WebSSO;

class MyController extends Controllers
    public function login(Request $request, WebSSO $sso)
        // Note that $request->cookie() won't work here.
        // It requires that all cookies be set by Laravel & encrypted with the app's key.
        $token = $_COOKIE['openAMssoToken'];

        $netid = $sso->getNetID($token);
        if ($netid == false) {
            // Error

        dd($netid); // netID as a string with no frills


The DirectorySearch endpoint requires an Apigee API key, as well as approval from relevant data stewards. For more information requesting access, check out the documents on the API portal.

Once you get your key, add it to the .env file as the DIRECTORY_SEARCH_API_KEY property. By default, the production service will be used, but you can define DIRECTORY_SEARCH_URL if you want to use dev or QA.


namespace App\Http\Controllers;

use Northwestern\SysDev\SOA\DirectorySearch;

class MyController extends Controllers
    public function login(Request $request, DirectorySearch $directory)
        // Defaults to the expanded version of the API call
        $info = $directory->lookupByNetId('nie7321');
        if ($info == false) {


        // There are other lookup methods available. Anywhere 'basic' is specified, you may also use 'public' or 'expanded'.
        $info = $directory->lookupByNetId('nie7321', 'basic');

        $info = $directory->lookup('1234567', 'emplid', 'basic');
        $info = $directory->lookup('1234567', 'hremplid', 'basic');
        $info = $directory->lookup('1234567', 'sesemplid', 'basic');
        $info = $directory->lookup('1234567', 'barcode', 'basic');
        $info = $directory->lookup('', 'mail', 'basic');
        $info = $directory->lookup('', 'studentemail', 'basic');

Refer to the Directory Search API docs for more information about what fields you will receive.


The EventHub SDK comes from northwestern-sysdev/event-hub-php-sdk. Please review its documentation for details on using it.

This package takes care of setting the library up for you and Laravel-izing it.

There are three key .env settings:

Setting Purpose
EVENT_HUB_BASE_URL The Apigee base URL, e.g.
EVENT_HUB_HMAC_VERIFICATION_SHARED_SECRET Only applicable if using webhook delivery for incoming messages. Set this to a random string, e.g. base64_encode(random_bytes(32))

A number of other settings are available to control the HMAC security options, but they are set to reasonable defaults. See the config/nusoa.php file if you are interested in these.


namespace App\Http\Controllers;

use Northwestern\SysDev\SOA\EventHub;

class MyController extends Controllers
    public function save(Request $request, EventHub\Topic $api)
        // Save some kind of Very Important Business Object to the DB...
        // . . .

        // And tell everyone it has been updated!
        $message_id = $api->writeJsonMessage('sysdev.a-topic-name', [
            'application_id' => $model->id,

There are also some Laravel-specific features added: an eventhub_hmac middleware that you can apply to a route/controller, some useful artisan commands, and an easy way to deploy your desired webhook configuration.

Webhook Route Registration

The most straightforward way to consume messages is by registering your routes as webhook endpoints.


// An example `routes/web.php`

Route::get('/eventhub/get-an-event', function () {
    return view('welcome');

When you make changes, run php artisan eventhub:webhook:configure. It will read through your routes and (re)configure all of your webhooks.

If you are using the HMAC middleware & have the settings for it in your .env (see below), your secret will be sent to EventHub. If you prefer another authentication type (or additional -- you can use all three), you can specify more options that'll be passed through to the webhook POST/PATCH call:

// See the EventHub webhook API docs to figure out what to pass for HTTP basic auth or API key auth!

$route->eventHubWebhook('', [
    'securityTypes' => ['APIKEY'],
    'webhookSecurity' => [
            'securityType' => 'APIKEY',
            'topicName' => '',
            'apiKey' => 'my top secret API key',
            'headerName' => 'x-api-key',

If you delete a registration, the eventhub:webhook:configure command will ask you if you'd like to delete the webhook config.

eventhub_hmac Middleware

To use the middleware, set EVENT_HUB_HMAC_VERIFICATION_SHARED_SECRET in your .env, and then apply it to a route or controller:


namespace App\Http\Controllers;

class MyController extends Controllers
    public function __construct()

All incoming requests will require a header with a valid, message-specific signature calculated based on the message and the secret shared with EventHub. This signature should be good enough to serve as the sole authentication method, but you can apply an API key or HTTP basic auth middleware as well.

EventHub Artisan Commands

The following artisan commands will be available when you install this package.

You can run these with php artisan <command>.

Command Purpose
eventhub:queue:status Show all the queues you can read from & some statistics
eventhub:topic:status Show all the topics you can write to & who is subscribed
eventhub:webhook:status Show all your configured webhooks
eventhub:webhook:toggle pause Pause all webhooks. Optionally, you can pass a list of queue names to pause just those.
eventhub:webhook:toggle unpause Unpause all webhooks. Optionally, you can pass a list of queue names to unpause just those.
eventhub:webhook:configure Publishes the webhook delivery routes configured in your route files with EventHub

Comprehensive Webhook Example

Putting everything together:

// routes/api.php or whatever

Route::middleware(['eventhub_hmac'])->prefix('eventhub')->group(function () {
    Route::post('consume-queue-a', 'ConsumeController@a')->eventHubWebhook('sysdev.queue.a');
    Route::post('consume-queue-b', 'ConsumeController@b')->eventHubWebhook('sysdev.queue.b');

Then on your console:

$ php artisan eventhub:webhook:configure
| Queue                             | Endpoint                                      | Active |
| sysdev.queue.a                    | http://localhost/api/eventhub/consume-queue-a | Active |
| sysdev.queue.b                    | http://localhost/api/eventhub/consume-queue-b | Active |

In the dev & test environments, you should have permission to write messages to the queues you're subscribed to via POST /v1/event-hub/queue/your-queue-name, so to verify your webhooks are running, open your php artisan tinker console:

>>> $q_api->sendTestJsonMessage('sysdev.queue.a', ['application_id' => 123])
=> "ID:052d83908c43-35873-1545317905819-1:1:3:1:1"

The test message should be delivered to your app almost immediately.


If you'd like to contribute to the library, you are welcome to submit a pull request!

My ideal architecture (going forward 😰) is to write plain-old PHP bindings (so folks can use them in non-Laravel apps) and then have the NuSoaServiceProvider inject config & add any other Laravel-specific enhancements.

If there is a service on the API Registry that you'd like SysDev to add support for, please go ahead and open an issue requesting it.