[RADIATOR] MapResponseHook sample (Was: Re: (no subject))

Heikki Vatiainen hvn at open.com.au
Thu May 25 14:29:23 UTC 2023


On 23.5.2023 0.19, Heikki Vatiainen via radiator wrote:
> On 22.5.2023 9.37, Greg Haverkamp via radiator wrote:

>> I get a JSON response that looks something like this:
>> {
>> "version": "LinOTP 2.11.2",
>> "jsonrpc": "2.0802",
>> "result": {
>>    "status": true,
>>    "value": false
>> },
>> "id": 0
>> }
>>
> 
> I can create an example of how to access the contents of the "result" 
> key. The default is to create a Perl hash for the keys but more complex 
> structures require more configuration.

Here's a configuration snippet followed by a hook. Trace 5 and Debug are 
set because they allow logging the requests and responses sent over HTTP(S).

The RestAuthReplyDef parameters use values set by the hook. The first 
ones that use Auth-Type check item, trigger failure if "result" is not 
present in the JSON reply or one of "status" or "value" is false. This 
means the above JSON response triggers a failure.

The RestAuthReplyDef parameters that add X-Result-Status and 
X-Result-Value to request show how to something to the current request 
based on the JSON response.


Trace 5

<AuthBy REST>
       # Config parameters ...
       Debug

       # Call the hook code in this file.
       MapResponseHook file:"%D/rest-map-hook.pl"

       # How to handle a response from the server.
       #
       # With Auth-Type check items you can trigger reject here.
       RestAuthReplyDef auth_type_result, Auth-Type, check
       RestAuthReplyDef auth_type_status, Auth-Type, check
       RestAuthReplyDef auth_type_value,  Auth-Type, check

       # As an alternative, you can store the values in request or
       # reply and process them later.
       RestAuthReplyDef result_status, X-Result-Status, request
       RestAuthReplyDef result_value,  X-Result-Value,  request

       # Log the Radius request to show the new X-Result- attributes.
       PostAuthHook sub { my $p = ${$_[0]}; main::log($main::LOG_DEBUG, 
"Request after AuthBy\n" . $p->dump(), $p); }
</AuthBy>



A rest-map-hook.pl sample is below. It first calls log to show how the 
default JSON to Perl mapping was done. It then makes additional keys 
available for the RestAuthReplyDef configuration parameters to use. Note 
that if a key, for example 'auth_type_result', is not present, the 
RestAuthReplyDef is skipped.

The log() calls are simply to aid debugging so that it's easier to see 
how JSON responses map to Perl data structures by default and ensure 
that the changes done within the hook are correct. With a hook, any 
complex JSON responses can be processed because the hook sees them in 
Perl mapped format.


use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;

sub {
     main::log($main::LOG_DEBUG, "Default processed response\n" . 
Dumper(@_));

     # $response_hash does not directly contain the mapped JSON
     # response. To update values RestAuthReplyDef configuration
     # parameter uses, modify 'server_response' within $response_hash.
     my $response_hash = $_[0];
     my $server_response = $response_hash->{server_response};

     # Successful reply must have 'result'.
     if ($server_response->{result})
     {
         # Trigger reject if 'status' or 'value' within 'result' is
         # false. Requires Auth-Type check item in the configuration.
         $server_response->{auth_type_status} = 'Reject:Status is false' 
if !$server_response->{result}->{status};
         $server_response->{auth_type_value}  = 'Reject:Value is false' 
if !$server_response->{result}->{value};

         # 'status' and 'value' are JSON booleans that are mapped to
         # Perl objects. Convert them to plain numeric zero or one.
         $server_response->{result_status} = 
$server_response->{result}->{status} ? 1 : 0;
         $server_response->{result_value}  = 
$server_response->{result}->{value}  ? 1 : 0;
     }
     else
     {
         # Trigger reject if there's no JSON object named 'result'
         $server_response->{auth_type_result} = 'Reject:No result in reply';
     }

     # Log the mapping to show the new keys 'result_value' and
     # 'result_status' and optionally 'auth_type' is 'status' within
     # 'result' was not true.
     main::log($main::LOG_DEBUG, "Updated processed response\n" . 
Dumper(@_));

     return;
}



Here's a snippet from Radiator log. Note that JSON booleans map to Perl 
objects. Therefore the 'result_status' and 'result_value' are made to 
simple zero and one which are easy to compare. A string comparison 
against an object is unlikely to produce expected results. The zero and 
one values are shown in the message logged from PostAuthHook as values 
of X-Result-Value and X-Result-Status. A PostAuthHook, AuthLog, a 
subsequent AuthBy etc. can later use them as required.


Thu May 25 17:14:02 2023 330808: DEBUG: AuthREST 'rest-authby' 
'127.0.0.1 port 8888' received HTTP response:
HTTP/1.1 200 OK
Date: Mon, 23 May 2021 22:38:34 GMT
Content-Type: application/json
Content-Length: 112
Last-Modified: Wed, 08 Jan 2021 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Accept-Ranges: bytes
Connection: close

{
"version": "LinOTP 2.11.2",
"jsonrpc": "2.0802",
"result": {
    "status": true,
    "value": false
},
"id": 0
}
Thu May 25 17:14:02 2023 331130: DEBUG: HTTPClientConnection 
'127.0.0.1-8888' Stream disconnected from 127.0.0.1 (127.0.0.1 port 8888)
Thu May 25 17:14:02 2023 331674: DEBUG: Default processed response
$VAR1 = {
           'server_response' => {
                                  'id' => 0,
                                  'jsonrpc' => '2.0802',
                                  'result' => {
                                                'status' => bless( 
do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
                                                'value' => bless( 
do{\(my $o = 0)}, 'JSON::PP::Boolean' )
                                              },
                                  'version' => 'LinOTP 2.11.2'
                                },
           'status_line' => '200 OK'
         };

Thu May 25 17:14:02 2023 331964: DEBUG: Updated processed response
$VAR1 = {
           'server_response' => {
                                  'auth_type_value' => 'Reject:Value is 
false',
                                  'id' => 0,
                                  'jsonrpc' => '2.0802',
                                  'result' => {
                                                'status' => bless( 
do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
                                                'value' => bless( 
do{\(my $o = 0)}, 'JSON::PP::Boolean' )
                                              },
                                  'result_status' => 1,
                                  'result_value' => 0,
                                  'version' => 'LinOTP 2.11.2'
                                },
           'status_line' => '200 OK'
         };

Thu May 25 17:14:02 2023 332250: DEBUG: Handling with Radius::AuthREST: 
rest-authby
Thu May 25 17:14:02 2023 332642: DEBUG: Radius::AuthREST looks for match 
with 'mikem' [mikem]
Thu May 25 17:14:02 2023 332882: DEBUG: Radius::AuthREST 
REJECT_IMMEDIATE: Value is false: 'mikem' [mikem]
Thu May 25 17:14:02 2023 333270: DEBUG: Request after AuthBy
Code:       Access-Request
Identifier: 117
Authentic:  <11>Im<168>#<202><149><243>$N><217><131>P-<197>
Attributes:
         User-Name = "mikem"
         Service-Type = Framed-User
         NAS-IP-Address = 203.63.154.1
         NAS-Identifier = "203.63.154.1"
         NAS-Port = 1234
         Called-Station-Id = "123456789"
         Calling-Station-Id = "987654321"
         NAS-Port-Type = Async
         User-Password = 
<138><237><247><10>)<203>g<127><235>I<194><129>D<133>YX
         X-Result-Status = 1
         X-Result-Value = 0

Thu May 25 17:14:02 2023 333467: DEBUG: AuthBy REST result: 
REJECT_IMMEDIATE, Value is false
Thu May 25 17:14:02 2023 333761: INFO: Access rejected for mikem: Value 
is false




I'll add the above to goodies.

Thanks,
Heikki

-- 
Heikki Vatiainen
OSC, makers of Radiator
Visit radiatorsoftware.com for Radiator AAA server software


More information about the radiator mailing list