11<?php
22require_once ("apiresp.inc " );
3+ require_once ("php-jwt/src/JWT.php " );
4+ require_once ("php-jwt/src/ExpiredException.php " );
5+ require_once ("php-jwt/src/SignatureInvalidException.php " );
6+ require_once ("php-jwt/src/BeforeValidException.php " );
37require_once ("config.inc " );
48require_once ("util.inc " );
59require_once ("interfaces.inc " );
@@ -9,6 +13,11 @@ require_once("filter.inc");
913require_once ("shaper.inc " );
1014require_once ("auth.inc " );
1115require_once ("functions.inc " );
16+ use Firebase \JWT \JWT ;
17+ use Firebase \JWT \ExpiredException ;
18+ use Firebase \JWT \SignatureInvalidException ;
19+ use Firebase \JWT \BeforeValidException ;
20+
1221
1322// HEADERS--------------------------------------------------------------------------------------------------------------
1423header ("Content-Type: application/json " , true );
@@ -104,6 +113,44 @@ function api_generate_token($username) {
104113 return $ key_new ;
105114}
106115
116+ // Creates JWT server key if one does not exist, or optionally allows rotation of the JWT server key
117+ function api_create_jwt_server_key ($ rotate =false ) {
118+ global $ config ;
119+ $ pkg_index = get_api_configuration ()[0 ]; // Save our current API configs pkg index
120+ $ api_config = get_api_configuration ()[1 ]; // Save our current API config
121+ # Create a new server key if one is not set
122+ if (empty ($ api_config ["server_key " ]) or $ rotate === true ) {
123+ $ config ["installedpackages " ]["package " ][$ pkg_index ]["conf " ]["server_key " ] = bin2hex (random_bytes (32 ));
124+ write_config ();
125+ }
126+ }
127+
128+ // Creates a JWT to use for JWT authentication
129+ function api_create_jwt ($ data ) {
130+ global $ config ;
131+ $ api_config = get_api_configuration ()[1 ]; // Save our current API config
132+ $ token_exp = $ api_config ["jwt_exp " ]; // Expire token in one hours
133+ api_create_jwt_server_key (); // Ensure we have a JWT server key
134+ $ payload = array (
135+ "iss " => $ config ["system " ]["hostname " ],
136+ "exp " => time () + $ token_exp ,
137+ "nbf " => time (),
138+ "data " => $ data
139+ );
140+ return JWT ::encode ($ payload , $ api_config ["server_key " ]);
141+ }
142+
143+ // Decodes a JWT
144+ function api_decode_jwt ($ token ) {
145+ $ key = get_api_configuration ()[1 ]["server_key " ]; // Save our current server key
146+ try {
147+ $ decoded = (array ) JWT ::decode ($ token , $ key , array ('HS256 ' ));
148+ } catch (Exception $ e ) {
149+ $ decoded = false ;
150+ }
151+ return $ decoded ;
152+ }
153+
107154// Get our API token ID for a given username
108155function api_get_existing_tokens ($ username ) {
109156 // Local variables
@@ -143,6 +190,23 @@ function api_authenticate() {
143190 $ authenticated = false ;
144191 $ api_config = get_api_configuration ()[1 ];
145192 $ users = index_users ();
193+
194+ // Check for JWT in Authorization header if authmode is set to JWT
195+ if ($ api_config ["authmode " ] === "jwt " ) {
196+ $ auth_header = explode (" " , $ _SERVER ["HTTP_AUTHORIZATION " ]);
197+ $ token_type = $ auth_header [0 ];
198+ $ token = $ auth_header [1 ];
199+ $ decoded_jwt = api_decode_jwt ($ token );
200+
201+ // Check that our JWT from our Authorization header is valid
202+ if ($ token_type === "Bearer " and $ decoded_jwt !== false ) {
203+ unset($ _SESSION ["Username " ]);
204+ $ client_id = $ decoded_jwt ["data " ];
205+ $ _SESSION ["Username " ] = $ client_id ;
206+ $ authenticated = true ;
207+ }
208+ }
209+
146210 // Format our client ID and token based on our configured auth mode
147211 if ($ api_config ["authmode " ] === "base64 " ) {
148212 $ client_id = base64_decode ($ client_id );
@@ -312,7 +376,7 @@ function api_whitelist_check() {
312376 } elseif ($ srv_ip === $ if_info ["ipaddrv6 " ]) {
313377 $ allowed = true ;
314378 break ;
315- } elseif ($ srv_ip === "127.0.0.1 " and $ wif === "localhost " ) {
379+ } elseif (in_array ( $ srv_ip, [ " ::1 " , "127.0.0.1 " , " localhost " ]) and $ wif === "localhost " ) {
316380 $ allowed = true ;
317381 break ;
318382 }elseif ($ wif === "any " ) {
@@ -326,7 +390,7 @@ function api_whitelist_check() {
326390 $ api_resp = array ("status " => "forbidden " , "code " => 403 , "return " => 6 );
327391 $ api_resp ["message " ] = $ err_lib [$ api_resp ["return " ]];
328392 http_response_code (403 );
329- echo json_encode ($ api_resp );
393+ echo json_encode ($ api_resp ). PHP_EOL ;
330394 die;
331395 }
332396}
0 commit comments