Authentication Help -

Hi folks,

I’m building an intranet application which will sit behind an existing SiteMinder implementation. I am hoping to simply check that the REMOTE_USER environment variable is set and if it is use that to authenticate against the Users table. If it isn’t, it’ll redirect to an auto-add controller which will create the new user, but I’m currently only worried about checking the variable and authorizing users that already exist in the table.

I currently have the app up and running locally using the standard Authentication/Authorization plugins as outlined in the CMS tutorial, and am now looking to convert it to using the environment variable rather than email/password; I have configured Apache to hard-set that variable for testing.

I am looking for advice on how to proceed. I am thinking that I need to implement Authentication.Callback something like:

$authenticationService->loadIdentifier('Authentication.Callback', [
        'callback' => ???
]);

But am unclear as to how to create a valid callback. Would someone be willing to point me in the right direction?

I wonder if you could use the Token Authenticator. It checks a single value against your db and it sounds like that might match your situation.

1 Like

Thank you very much for the suggestion! I did not mention in my post that I have, actually, already tried to use the Token Authenticator with some success:

$authenticationService->loadAuthenticator('Authentication.Token', [
            'queryParam' => 'idir',
            'header' => 'Authorization'
]);
$authenticationService->loadIdentifier('Authentication.Token', [
            'tokenField' => 'idir'
]);

This does indeed “work” but only if I include ?idir=tokenusername in every request.

Might there be some documentation somewhere that would illustrate how to use an environment variable ($_SERVER[‘REMOTE_USER’]) in place of the GET parameter?

Gratefully yours,

@allankh

Well, the Authentication middleware will try all configured authenticators until it finds success or runs out of options.

There is a Session authenticator that is used to support the normal username/password login. Perhaps you could get your token into the session and have that as a second checkpoint.

I think the Session authenticator normally uses username/password field checks just like the Form authenticator. But you can set what fields it looks for in the Session. There may be a solution there.

Here are the docs. It looks like retargeting ‘field’ will do it. And set ‘identify’ to false so it doesn’t try to reverify on the db (which would user Form authenticator rules).

Here is what is going on in the background:

There’s nothing stopping you from writing your own custom authenticator, if nothing pre-made fits the bill.

Apologies for the delayed response here. I really appreciate the input! I’ve been able to hack the token authenticator to do what I want, and will be implementing a custom authenticator to make it real. Hurray!

Hello again. As I mentioned, I’ve gone the custom authenticator/identifier route, but so far I’ve really only implemented that by manually adding the files in the vendor/cakephp/authentication/… folder(s). This does work for testing, but as the vendor folder lives outside my repository, it’s obviously not the correct way of implementing this. Could someone point me in the right direction on how to proceed? Do I need to write a plugin?

I haven’t tried this out specifically, but here is the general idea (used in many places in Cake).

Consider this code from Application.php getAuthenticationService() (the place where you should be configuring all this stuff)

Each load*Thing*() call takes a name arg and optionally a className config key.

If there is no className key, the system will try to create the object named by name from some expected directory/namespace.

If there IS a className key, the name will become the alias the object is known by and the system will try to make the object className from the expected directory/namespace.

The dot notation in my example code is Cakes way of indicating the class is part of a plugin and should be found in the plugin’s namespace.

So. Your job is to build your class in the proper directory in your app’s namespace and identify it in the loadX() call.

1 Like