[RADIATOR] PostAuthHook with asynchronous modules like AuthDUO

Christopher Bongaarts cab at umn.edu
Fri Jul 26 18:14:39 UTC 2019

We're implementing some additional authorization checks in some of our 
Handlers by using PostAuthHook to perform the checks and update the 
return status accordingly.  These checks are using LDAP attributes 
returned from the auth check (using AuthAttrDef to make them available 
to the hooks).

This works fine for LDAP by itself, as it is synchronous. However, when 
we try to add them to a more complex setup like using LDAP with Duo, the 
results are a little odd.

Here is the AuthBy we use to check LDAP plus Duo (modeled on the example 
in goodies):

<AuthBy GROUP>
         Identifier UMN-DUO

         # the authbys implement the following logic:
         # try LDAP with full password
         # if successful
         #    try duo with no parameters (full auto)
         # else
         #    try LDAP with password up to final comma
         #    if successful
         #       try duo with parameter after final comma
         #    endif
         # endif
         # keep in mind that AuthBy RADIUS and DUO
         # only return REJECT or IGNORE since they
         # run asynchronously

         AuthByPolicy ContinueWhileAccept
         <AuthBy GROUP>
             AuthByPolicy ContinueUntilAccept
             AuthBy UMNPASSWORD
             <AuthBy GROUP>
                 AuthByPolicy ContinueWhileAccept
                 AuthBy UMNPASSWORD-SPLIT
                 AuthBy DUO-SPLIT
         AuthBy DUO-AUTO

The handler looks like this:

<Handler Client-Identifier=TEST_CLIENT>
         Identifier OITISMON
         AuthBy UMN-DUO
         PostAuthHook file:"%D/test_postauthhook.pl"
         AuthLog myauthlog

This provides the relatively standard Duo login flow of entering 
username/password, then Duo triggers a push notification, and when the 
push is accepted, sends an Access-Accept.  This looks fine to the user 
when the hook allows the user.

The actual order of events looks like this:

- The LDAP (UMNPASSWORD) AuthBy is invoked and succeeds.
- The DUO-AUTO AuthBy is invoked.  This generates a push to Duo (API 
call), and returns IGNORE.
- At this point the UMN-DUO AuthBy completes (due to the IGNORE).
- The PostAuthHook is called, which leaves the result as IGNORE on 
success, or REJECTs on failure.
- If the hook suceeded, at some point the Duo API call completes, and 
AuthDUO sends an Access-Accept reply.
- If the hook fails, it sends an Access-Reject immediately to the 
client; however, when the API call completes, it sends an Access-Accept.

This last point troubles me a bit; it seems like if something happened 
so the Access-Reject got lost, a user could be granted access when the 
hook would have denied them.

I can see a couple ways to work around this:

- Use a PostProcessingHook instead of PostAuthHook to implement the 
authorization check.  I *think* it's possible to change the result at 
that point in the process.
- Have AuthDUO (or Handler->handleResult()) call the PostAuthHook a 
second time; possibly skip the hook if result is IGNORE
- Do the checks in AuthLDAP2's PostSearchHook

This message is a sort of combination request for advice on the above 
approaches (or other suggestions) and suggestion for enhancement that 
would potentially apply to other async auth methods.

%%  Christopher A. Bongaarts   %%  cab at umn.edu          %%
%%  OIT - Identity Management  %%  http://umn.edu/~cab  %%
%%  University of Minnesota    %%  +1 (612) 625-1809    %%

More information about the radiator mailing list