[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>
</AuthBy>
AuthBy DUO-AUTO
</AuthBy>
The handler looks like this:
<Handler Client-Identifier=TEST_CLIENT>
Identifier OITISMON
AuthBy UMN-DUO
PostAuthHook file:"%D/test_postauthhook.pl"
RejectHasReason
AuthLog myauthlog
</Handler>
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