@@ -26,7 +26,7 @@ typedef struct
2626{
2727  ngx_str_t  loginurl ;
2828  ngx_str_t  key ;
29-   ngx_flag_t   enabled ;
29+   ngx_http_complex_value_t   * enabled ;
3030  ngx_flag_t  redirect ;
3131  ngx_str_t  jwt_location ;
3232  ngx_str_t  algorithm ;
@@ -83,8 +83,8 @@ static ngx_command_t auth_jwt_directives[] = {
8383     NULL },
8484
8585    {ngx_string ("auth_jwt_enabled" ),
86-      NGX_HTTP_MAIN_CONF  | NGX_HTTP_SRV_CONF  | NGX_HTTP_LOC_CONF  | NGX_CONF_FLAG ,
87-      ngx_conf_set_flag_slot ,
86+      NGX_HTTP_MAIN_CONF  | NGX_HTTP_SRV_CONF  | NGX_HTTP_LOC_CONF  | NGX_CONF_TAKE1 ,
87+      ngx_http_set_complex_value_slot ,
8888     NGX_HTTP_LOC_CONF_OFFSET ,
8989     offsetof(auth_jwt_conf_t , enabled ),
9090     NULL },
@@ -207,9 +207,7 @@ static void *create_conf(ngx_conf_t *cf)
207207  else 
208208  {
209209    // ngx_str_t fields are initialized by the ngx_palloc call above -- only need to init flags and arrays here 
210-     conf -> enabled  =  NGX_CONF_UNSET ;
211-     conf -> redirect  =  NGX_CONF_UNSET ;
212-     conf -> validate_sub  =  NGX_CONF_UNSET ;
210+     conf -> enabled  =  NULL ;
213211    conf -> redirect  =  NGX_CONF_UNSET ;
214212    conf -> validate_sub  =  NGX_CONF_UNSET ;
215213    conf -> extract_var_claims  =  NULL ;
@@ -236,20 +234,12 @@ static char *merge_conf(ngx_conf_t *cf, void *parent, void *child)
236234  merge_array (cf -> pool , & conf -> extract_request_claims , prev -> extract_request_claims , sizeof (ngx_str_t ));
237235  merge_array (cf -> pool , & conf -> extract_response_claims , prev -> extract_response_claims , sizeof (ngx_str_t ));
238236
239-   if  (conf -> enabled  ==  NGX_CONF_UNSET )
240-   {
241-     conf -> enabled  =  prev -> enabled  ==  NGX_CONF_UNSET  ? 0  : prev -> enabled ;
242-   }
243- 
244-   if  (conf -> redirect  ==  NGX_CONF_UNSET )
245-   {
246-     conf -> redirect  =  prev -> redirect  ==  NGX_CONF_UNSET  ? 0  : prev -> redirect ;
237+   if  (conf -> enabled  ==  NULL ) {
238+     conf -> enabled  =  prev -> enabled ;
247239  }
248240
249-   if  (conf -> use_keyfile  ==  NGX_CONF_UNSET )
250-   {
251-     conf -> use_keyfile  =  prev -> use_keyfile  ==  NGX_CONF_UNSET  ? 0  : prev -> use_keyfile ;
252-   }
241+   ngx_conf_merge_off_value (conf -> redirect , prev -> redirect , 0 );
242+   ngx_conf_merge_off_value (conf -> use_keyfile , prev -> use_keyfile , 0 );
253243
254244  // If the usage of the keyfile is specified, check if the key_path is also configured 
255245  if  (conf -> use_keyfile  ==  1 )
@@ -461,109 +451,138 @@ static auth_jwt_ctx_t *get_or_init_jwt_module_ctx(ngx_http_request_t *r, auth_jw
461451static  auth_jwt_ctx_t  * get_request_jwt_ctx (ngx_http_request_t  * r )
462452{
463453  auth_jwt_conf_t  * jwtcf  =  ngx_http_get_module_loc_conf (r , ngx_http_auth_jwt_module );
454+   ngx_int_t  enabled  =  1 ;
464455
465-   if  (!jwtcf -> enabled )
466-   {
467-     return  NULL ;
456+   if  (jwtcf -> enabled  !=  NULL ) {
457+     ngx_str_t  cv ;
458+     if  (ngx_http_complex_value (r , jwtcf -> enabled , & cv ) ==  NGX_OK  &&  cv .len  >  0 ) {
459+       if  (ngx_strncmp (cv .data , "off" , 3 ) ==  0 ) {
460+         enabled  =  0 ;
461+       }
462+     }
468463  }
469464
470-   auth_jwt_ctx_t  * ctx  =  get_or_init_jwt_module_ctx (r , jwtcf );
471- 
472-   if  (ctx  ==  NULL )
473-   {
465+   if  (!enabled ) {
474466    return  NULL ;
475467  }
476-   else  if  (ctx -> validation_status  !=  NGX_AGAIN )
477-   {
478-     // we already validated and extacted everything we care about, so we just return the already-complete context 
479-     return  ctx ;
480-   }
481- 
482-   char  * jwtPtr  =  get_jwt (r , jwtcf -> jwt_location );
468+   else  {
469+     auth_jwt_ctx_t  * ctx  =  get_or_init_jwt_module_ctx (r , jwtcf );
483470
484-   if  (jwtPtr  ==  NULL )
485-   {
486-     ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "failed to find a JWT" );
487-     ctx -> validation_status  =  NGX_ERROR ;
488-     return  ctx ;
489-   }
490-   else 
491-   {
492-     ngx_str_t  algorithm  =  jwtcf -> algorithm ;
493-     int  keyLength ;
494-     u_char  * key ;
495-     jwt_t  * jwt  =  NULL ;
496- 
497-     if  (algorithm .len  ==  0  ||  (algorithm .len  ==  5  &&  ngx_strncmp (algorithm .data , "HS" , 2 ) ==  0 ))
471+     if  (ctx  ==  NULL ) {
472+       return  NULL ;
473+     }
474+     else  if  (ctx -> validation_status  !=  NGX_AGAIN )
498475    {
499-       keyLength  =  jwtcf -> key .len  / 2 ;
500-       key  =  ngx_palloc (r -> pool , keyLength );
476+       // we already validated and extacted everything we care about, so we just return the already-complete context 
477+       return  ctx ;
478+     }
479+     else  {
480+       char  * jwtPtr  =  get_jwt (r , jwtcf -> jwt_location );
501481
502-       if  (0   !=   hex_to_binary (( char   * ) jwtcf -> key . data ,  key ,  jwtcf -> key . len ) )
482+       if  (jwtPtr   ==   NULL )
503483      {
504-         ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "failed to turn hex key into binary " );
484+         ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "failed to find a JWT " );
505485        ctx -> validation_status  =  NGX_ERROR ;
486+ 
506487        return  ctx ;
507488      }
508-     }
509-     else  if  (algorithm .len  ==  5  &&  (ngx_strncmp (algorithm .data , "RS" , 2 ) ==  0  ||  ngx_strncmp (algorithm .data , "ES" , 2 ) ==  0 ))
510-     {
511-       if  (jwtcf -> use_keyfile  ==  1 )
512-       {
513-         keyLength  =  jwtcf -> _keyfile .len ;
514-         key  =  (u_char  * )jwtcf -> _keyfile .data ;
515-       }
516489      else 
517490      {
518-         keyLength  =  jwtcf -> key .len ;
519-         key  =  jwtcf -> key .data ;
520-       }
521-     }
522-     else 
523-     {
524-       ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "unsupported algorithm %s" , algorithm );
525-       ctx -> validation_status  =  NGX_ERROR ;
526-       return  ctx ;
527-     }
491+         ngx_str_t  algorithm  =  jwtcf -> algorithm ;
492+         int  keyLength ;
493+         u_char  * key ;
494+         jwt_t  * jwt  =  NULL ;
528495
529-     if  (jwt_decode (& jwt , jwtPtr , key , keyLength ) !=  0  ||  !jwt )
530-     {
531-       ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "failed to parse JWT" );
532-       ctx -> validation_status  =  NGX_ERROR ;
533-     }
534-     else  if  (validate_alg (jwtcf , jwt ) !=  0 )
535-     {
536-       ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "invalid algorithm specified" );
537-       ctx -> validation_status  =  NGX_ERROR ;
538-     }
539-     else  if  (validate_exp (jwtcf , jwt ) !=  0 )
540-     {
541-       ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "the JWT has expired" );
542-       ctx -> validation_status  =  NGX_ERROR ;
543-     }
544-     else  if  (validate_sub (jwtcf , jwt ) !=  0 )
545-     {
546-       ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "the JWT does not contain a subject" );
547-       ctx -> validation_status  =  NGX_ERROR ;
548-     }
549-     else 
550-     {
551-       extract_request_claims (r , jwtcf , jwt );
552-       extract_response_claims (r , jwtcf , jwt );
553-       ctx -> validation_status  =  extract_var_claims (r , jwtcf , jwt , ctx );
554-     }
496+         if  (algorithm .len  ==  0  ||  (algorithm .len  ==  5  &&  ngx_strncmp (algorithm .data , "HS" , 2 ) ==  0 ))
497+         {
498+           keyLength  =  jwtcf -> key .len  / 2 ;
499+           key  =  ngx_palloc (r -> pool , keyLength );
555500
556-     jwt_free (jwt );
557-     return  ctx ;
501+           if  (0  !=  hex_to_binary ((char  * )jwtcf -> key .data , key , jwtcf -> key .len ))
502+           {
503+             ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "failed to turn hex key into binary" );
504+             ctx -> validation_status  =  NGX_ERROR ;
505+ 
506+             return  ctx ;
507+           }
508+         }
509+         else  if  (algorithm .len  ==  5  &&  (ngx_strncmp (algorithm .data , "RS" , 2 ) ==  0  ||  ngx_strncmp (algorithm .data , "ES" , 2 ) ==  0 ))
510+         {
511+           if  (jwtcf -> use_keyfile  ==  1 )
512+           {
513+             keyLength  =  jwtcf -> _keyfile .len ;
514+             key  =  (u_char  * )jwtcf -> _keyfile .data ;
515+           }
516+           else 
517+           {
518+             keyLength  =  jwtcf -> key .len ;
519+             key  =  jwtcf -> key .data ;
520+           }
521+         }
522+         else 
523+         {
524+           ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "unsupported algorithm %s" , algorithm );
525+           ctx -> validation_status  =  NGX_ERROR ;
526+ 
527+           return  ctx ;
528+         }
529+ 
530+         if  (jwt_decode (& jwt , jwtPtr , key , keyLength ) !=  0  ||  !jwt )
531+         {
532+           ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "failed to parse JWT" );
533+           ctx -> validation_status  =  NGX_ERROR ;
534+         }
535+         else  if  (validate_alg (jwtcf , jwt ) !=  0 )
536+         {
537+           ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "invalid algorithm specified" );
538+           ctx -> validation_status  =  NGX_ERROR ;
539+         }
540+         else  if  (validate_exp (jwtcf , jwt ) !=  0 )
541+         {
542+           ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "the JWT has expired" );
543+           ctx -> validation_status  =  NGX_ERROR ;
544+         }
545+         else  if  (validate_sub (jwtcf , jwt ) !=  0 )
546+         {
547+           ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "the JWT does not contain a subject" );
548+           ctx -> validation_status  =  NGX_ERROR ;
549+         }
550+         else 
551+         {
552+           extract_request_claims (r , jwtcf , jwt );
553+           extract_response_claims (r , jwtcf , jwt );
554+           ctx -> validation_status  =  extract_var_claims (r , jwtcf , jwt , ctx );
555+         }
556+ 
557+         jwt_free (jwt );
558+ 
559+         return  ctx ;
560+       }
561+     }
558562  }
559563}
560564
561565static  ngx_int_t  handle_request (ngx_http_request_t  * r )
562566{
563567  auth_jwt_conf_t  * jwtcf  =  ngx_http_get_module_loc_conf (r , ngx_http_auth_jwt_module );
568+ 
569+   // Only activate JWT logic if key or keyfile_path is set 
570+   if  (jwtcf -> key .len  ==  0  &&  jwtcf -> keyfile_path .len  ==  0 ) {
571+     return  NGX_DECLINED ;
572+   }
573+ 
564574  auth_jwt_ctx_t  * ctx  =  get_request_jwt_ctx (r );
565575
566-   if  (!jwtcf -> enabled )
576+   ngx_int_t  enabled  =  1 ;
577+   if  (jwtcf -> enabled  !=  NULL ) {
578+     ngx_str_t  cv ;
579+     if  (ngx_http_complex_value (r , jwtcf -> enabled , & cv ) ==  NGX_OK  &&  cv .len  >  0 ) {
580+       if  (ngx_strncmp (cv .data , "off" , 3 ) ==  0 ) {
581+         enabled  =  0 ;
582+       }
583+     }
584+   }
585+   if  (!enabled )
567586  {
568587    return  NGX_DECLINED ;
569588  }
0 commit comments