JSON webtokens are a means to generate access tokens containing user data. A valid token gives access to a site as an alternative to sessions and cookies. In a regular application a user is granted access to an application with a valid user/password combination. User data are then stored on the server as a session and the ID of the session is sent as a header back to the browser to be stored as a cookie. In the next request the browser takes the ID from the cookie and sends it in the header back to the server. If the server can match this ID with a session already stored the user is automatically validated and the user data stored in the session re-used.

Webtokens are relevant if a user is already authenticated for one site but requires authorisation to another one. In this sense it is not at all a replacement for session/cookies.  The challenge now is to safely transfer user data to this site.

In the Orinoco demo site (JWT branch) the JwtController has a regular authAction with one difference: instead of creating a session after a successful authentication it returns an encoded JSON string.

This string was generated by firebase/php-jwt and looks like this one:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE0OTEyNTEwMzQsImp0aSI6IlVXTnhTb0xjXC9NUG93NVllbFZUZGw1Q08waXI0RG4yUVcxMDJGRHVMelhFPSIsImlzcyI6Im9yaW5vY28iLCJuYmYiOjE0OTEyNTEwNDQsImV4cCI6MTQ5MTI1MTEwNCwiZGF0YSI6eyJ1c2VySWQiOjIsInVzZXJOYW1lIjoicmlrIn19.GBDMPwh2M0eWIimFyodbMDEkTIG4vXBt_wP2_q3IVqAYZPfJIZwJbAxnlF9TMvjvUpK3mr_hH8Of2g-1UYd-ug

It consists of three parts, the header, the payload and the signature.  These strings are based on a data array, for example:

$data = Array
(
    [iat] => 1491254619
    [jti] => ZmMZxmfTGP6WDM9fOcNtl3BNEpF2ubJUPbXrZiHCObE=
    [iss] => orinoco
    [nbf] => 1491254629
    [exp] => 1491254689
    [data] => Array
        (
            [userId] => 2
            [userName] => me
        )

)

with iat the issued at timestamp, iss the servername and respectively bbf and exp the notbefore and expire timestamps. The data section contains the so-called claims. The header section contains the signing algoritm.

The $jwt token is then generated as

$secretKey = $this->config['jwt_secret'];
            $jwt = JWT::encode(
                    $data, $secretKey, 'HS512'
            );

Note that any number of users can be supplied with tokens with a single secret key.

The second action method in the JwtController can be used to receive the token as part of the header, decode it and return the decoded content. The principle can be tested with a REST client such as Chrome Postman.

This involves a GET request to http://127.0.0.1/jwt/data 1] with a specific header set: the key is set to “Authorization” and the value is set to

Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE0OTEyNTEwMzQsImp0aSI6IlVXTnhTb0xjXC9NUG93NVllbFZUZGw1Q08waXI0RG4yUVcxMDJGRHVMelhFPSIsImlzcyI6Im9yaW5vY28iLCJuYmYiOjE0OTEyNTEwNDQsImV4cCI6MTQ5MTI1MTEwNCwiZGF0YSI6eyJ1c2VySWQiOjIsInVzZXJOYW1lIjoicmlrIn19.GBDMPwh2M0eWIimFyodbMDEkTIG4vXBt_wP2_q3IVqAYZPfJIZwJbAxnlF9TMvjvUpK3mr_hH8Of2g-1UYd-ug

The example response is

{"success":true,"data":{"iat":1491249688,"jti":"To8GUPVhXKuXx309e81+boMGso8euO7boDr4k5aeMcA=","iss":"orinoco","nbf":1491249698,"exp":1491249758,"data":{"userId":2,"userName":"me"}}}

In this configuration the expiration time is set to 50 seconds, the response then is

{"success":false,"message":"Expired token"}

See for the commits here and here.

==Links==

1] Chrome does not just like that recognise multiple hosts in the httpd-vhosts.conf in a typical Xampp setting, so maybe the relevant virtualhost directive must be moved up.

Advertisements