Skip to content

Commit 6ccbb9f

Browse files
authored
Merge pull request #1 from penumbra23/feature/rs256-key-file
Add loading RS256 key from file
2 parents 891467e + 83f839f commit 6ccbb9f

File tree

5 files changed

+100
-39
lines changed

5 files changed

+100
-39
lines changed

Dockerfile

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,9 @@ RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.n
1515
yum -y install pcre-devel pcre zlib-devel openssl-devel wget cmake check-devel check && \
1616
yum -y install nginx-$NGINX_VERSION
1717

18-
# for compiling for rh-nginx110
19-
# yum -y install libxml2 libxslt libxml2-devel libxslt-devel gd gd-devel perl-ExtUtils-Embed
20-
2118
# for compiling for epel7
2219
RUN yum -y install libxml2 libxslt libxml2-devel libxslt-devel gd gd-devel perl-ExtUtils-Embed geoip geoip-devel google-perftools google-perftools-devel
2320

24-
# Jansson requires new cmake
25-
RUN yum -y install cmake3 && \
26-
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake 10 \
27-
--slave /usr/local/bin/ctest ctest /usr/bin/ctest \
28-
--slave /usr/local/bin/cpack cpack /usr/bin/cpack \
29-
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake \
30-
--family cmake && \
31-
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \
32-
--slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \
33-
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
34-
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
35-
--family cmake
36-
3721
RUN mkdir -p /root/dl
3822
WORKDIR /root/dl
3923

@@ -85,19 +69,12 @@ RUN wget http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz && \
8569
rm nginx-$NGINX_VERSION.tar.gz && \
8670
ln -sf nginx-$NGINX_VERSION nginx && \
8771
cd /root/dl/nginx && \
88-
./configure --add-dynamic-module=../ngx-http-auth-jwt-module --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic -std=gnu99' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' && \
72+
./configure --add-dynamic-module=../ngx-http-auth-jwt-module --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Werror=unused-variable -Wno-unused-variable -Wno-error=unused-but-set-variable -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic -std=gnu99' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' && \
8973
make modules && \
9074
cp /root/dl/nginx/objs/ngx_http_auth_jwt_module.so /usr/lib64/nginx/modules/.
9175

9276
# Get nginx ready to run
9377
COPY resources/nginx.conf /etc/nginx/nginx.conf
94-
COPY resources/test-jwt-nginx.conf /etc/nginx/conf.d/test-jwt-nginx.conf
95-
RUN rm -rf /usr/share/nginx/html
96-
RUN cp -r /root/dl/nginx/html /usr/share/nginx
97-
RUN cp -r /usr/share/nginx/html /usr/share/nginx/secure
98-
RUN cp -r /usr/share/nginx/html /usr/share/nginx/secure-rs256
99-
RUN cp -r /usr/share/nginx/html /usr/share/nginx/secure-auth-header
100-
RUN cp -r /usr/share/nginx/html /usr/share/nginx/secure-no-redirect
10178

10279
ENTRYPOINT ["/usr/sbin/nginx"]
10380

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ auth_jwt_loginurl "https://yourdomain.com/loginpage";
4545
auth_jwt_enabled on;
4646
auth_jwt_algorithm HS256; # or RS256
4747
auth_jwt_validate_email on; # or off
48+
auth_jwt_use_keyfile off; # or on
49+
auth_jwt_keyfile_path "/app/pub_key";
4850
```
4951

5052
The default algorithm is 'HS256', for symmetric key validation. When using HS256, the value for `auth_jwt_key` should be specified in binhex format. It is recommended to use at least 256 bits of data (32 pairs of hex characters or 64 characters in total) as in the example above. Note that using more than 512 bits will not increase the security. For key guidelines please see NIST Special Publication 800-107 Recommendation for Applications Using Approved Hash Algorithms, Section 5.3.2 The HMAC Key.
5153

52-
The configuration also supports the `auth_jwt_algorithm` 'RS256', for RSA 256-bit public key validation. If using "auth_jwt_algorithm RS256;", then the `auth_jwt_key` field must be set to your public key.
54+
The configuration also supports the `auth_jwt_algorithm` 'RS256', for RSA 256-bit public key validation. If using "auth_jwt_algorithm RS256;", then the `auth_jwt_key` field must be set to your public key **OR** `auth_jwt_use_keyfile` should be set to `on` with the `auth_jwt_keyfile_path` set to the public key path (which defaults to `"/app/pub_key"`).
5355
That is the public key, rather than a PEM certificate. I.e.:
5456

5557
```
@@ -64,6 +66,13 @@ oQIDAQAB
6466
-----END PUBLIC KEY-----";
6567
```
6668

69+
**OR**
70+
71+
```
72+
auth_jwt_use_keyfile on;
73+
auth_jwt_keyfile_path "/etc/nginx/pub_key.pem";
74+
```
75+
6776
A typical use would be to specify the key and loginurl on the main level
6877
and then only turn on the locations that you want to secure (not the login page).
6978
Unauthorized requests are given 302 "Moved Temporarily" responses with a ___location of the specified loginurl.

config

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
ngx_addon_name=ngx_http_auth_jwt_module
2-
32
ngx_module_type=HTTP
43
ngx_module_name=ngx_http_auth_jwt_module
54
ngx_module_srcs="$ngx_addon_dir/src/ngx_http_auth_jwt_binary_converters.c $ngx_addon_dir/src/ngx_http_auth_jwt_header_processing.c $ngx_addon_dir/src/ngx_http_auth_jwt_string.c $ngx_addon_dir/src/ngx_http_auth_jwt_module.c"
65
ngx_module_libs="-ljansson -ljwt"
7-
8-
. auto/module
6+
. auto/module

resources/test-jwt-nginx.conf

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ server {
22
auth_jwt_key "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF";
33
auth_jwt_loginurl "https://teslagov.com";
44
auth_jwt_enabled off;
5-
auth_jwt_redirect on;
5+
auth_jwt_redirect off;
66

77
listen 8000;
88
server_name localhost;
@@ -29,21 +29,30 @@ server {
2929

3030
___location ~ ^/secure-rs256/ {
3131
auth_jwt_enabled on;
32-
auth_jwt_validation_type COOKIE=rampartjwt;
32+
auth_jwt_validation_type AUTHORIZATION;
3333
auth_jwt_algorithm RS256;
3434
auth_jwt_key "-----BEGIN PUBLIC KEY-----
35-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwtpMAM4l1H995oqlqdMh
36-
uqNuffp4+4aUCwuFE9B5s9MJr63gyf8jW0oDr7Mb1Xb8y9iGkWfhouZqNJbMFry+
37-
iBs+z2TtJF06vbHQZzajDsdux3XVfXv9v6dDIImyU24MsGNkpNt0GISaaiqv51NM
38-
ZQX0miOXXWdkQvWTZFXhmsFCmJLE67oQFSar4hzfAaCulaMD+b3Mcsjlh0yvSq7g
39-
6swiIasEU3qNLKaJAZEzfywroVYr3BwM1IiVbQeKgIkyPS/85M4Y6Ss/T+OWi1Oe
40-
K49NdYBvFP+hNVEoeZzJz5K/nd6C35IX0t2bN5CVXchUFmaUMYk2iPdhXdsC720t
41-
BwIDAQAB
35+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoDssqQi9TL79UPYaWqEr
36+
W11InyFvIUjhOYlTv4N/1AqOBRSCOLyGrm3MI/ngqxD2MEcBYwko7SWX0TR2WJsE
37+
kFv0V+107lmALMLBBrBzBIkmxUsBUwgwbn5639k8p/zXELsBOqTQ4bdLK+cpsEUE
38+
ECZU4kNcWm7c/VNEhf0SbgYoco6IGPBR7SrhWfbFSwCbbzdYMQE39kAOExSZgEav
39+
7oMbjK82ciDWrxtl+adNIPCDAA8tv0//YuxARSDnXXUKybagooYFwLs8RhIH4WRo
40+
ZhHrF0zHJrYCR/QoHF5Q96iDHJ/gBAUAhB76w+65IrzPQHbsCC/9VJAm+DPmEcZq
41+
jwIDAQAB
4242
-----END PUBLIC KEY-----";
4343
root /usr/share/nginx;
4444
index index.html index.htm;
4545
}
4646

47+
___location ~ ^/secure-rs256-file/ {
48+
auth_jwt_enabled on;
49+
auth_jwt_validation_type AUTHORIZATION;
50+
auth_jwt_algorithm RS256;
51+
auth_jwt_use_keyfile on;
52+
root /usr/share/nginx;
53+
index index.html index.htm;
54+
}
55+
4756
___location / {
4857
root /usr/share/nginx/html;
4958
index index.html index.htm;

src/ngx_http_auth_jwt_module.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@
1818
#include "ngx_http_auth_jwt_binary_converters.h"
1919
#include "ngx_http_auth_jwt_string.h"
2020

21+
#include <stdio.h>
22+
23+
const char* KEY_FILE_PATH = "/app/pub_key";
24+
2125
typedef struct {
2226
ngx_str_t auth_jwt_loginurl;
2327
ngx_str_t auth_jwt_key;
2428
ngx_flag_t auth_jwt_enabled;
2529
ngx_flag_t auth_jwt_redirect;
2630
ngx_str_t auth_jwt_validation_type;
2731
ngx_str_t auth_jwt_algorithm;
32+
ngx_flag_t auth_jwt_use_keyfile;
33+
ngx_str_t auth_jwt_keyfile_path;
2834
ngx_flag_t auth_jwt_validate_email;
2935

3036
} ngx_http_auth_jwt_loc_conf_t;
@@ -58,6 +64,20 @@ static ngx_command_t ngx_http_auth_jwt_commands[] = {
5864
offsetof(ngx_http_auth_jwt_loc_conf_t, auth_jwt_enabled),
5965
NULL },
6066

67+
{ ngx_string("auth_jwt_use_keyfile"),
68+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
69+
ngx_conf_set_flag_slot,
70+
NGX_HTTP_LOC_CONF_OFFSET,
71+
offsetof(ngx_http_auth_jwt_loc_conf_t, auth_jwt_use_keyfile),
72+
NULL },
73+
74+
{ ngx_string("auth_jwt_keyfile_path"),
75+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
76+
ngx_conf_set_str_slot,
77+
NGX_HTTP_LOC_CONF_OFFSET,
78+
offsetof(ngx_http_auth_jwt_loc_conf_t, auth_jwt_keyfile_path),
79+
NULL },
80+
6181
{ ngx_string("auth_jwt_redirect"),
6282
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
6383
ngx_conf_set_flag_slot,
@@ -129,6 +149,8 @@ static ngx_int_t ngx_http_auth_jwt_handler(ngx_http_request_t *r)
129149
char* return_url;
130150
ngx_http_auth_jwt_loc_conf_t *jwtcf;
131151
u_char *keyBinary;
152+
// For clearing it later on
153+
char* pub_key = NULL;
132154
jwt_t *jwt = NULL;
133155
int jwtParseReturnCode;
134156
jwt_alg_t alg;
@@ -177,8 +199,45 @@ static ngx_int_t ngx_http_auth_jwt_handler(ngx_http_request_t *r)
177199
else if ( auth_jwt_algorithm.len == sizeof("RS256") - 1 && ngx_strncmp(auth_jwt_algorithm.data, "RS256", sizeof("RS256") - 1) == 0 )
178200
{
179201
// in this case, 'Binary' is a misnomer, as it is the public key string itself
180-
keyBinary = jwtcf->auth_jwt_key.data;
181-
keylen = jwtcf->auth_jwt_key.len;
202+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to find a jwt");
203+
if (jwtcf->auth_jwt_use_keyfile == 1)
204+
{
205+
FILE *file = fopen((const char*)jwtcf->auth_jwt_keyfile_path.data, "rb");
206+
207+
// Check if file exists or is correctly opened
208+
if (file == NULL)
209+
{
210+
char err[100];
211+
strcpy(err, "failed to open pub key file: ");
212+
strcat(err, KEY_FILE_PATH);
213+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, err);
214+
goto redirect;
215+
}
216+
217+
// Read file length
218+
fseek(file, 0, SEEK_END);
219+
long key_size = ftell(file);
220+
fseek(file, 0, SEEK_SET);
221+
222+
if (key_size == 0)
223+
{
224+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid key file size, check the key file");
225+
goto redirect;
226+
}
227+
228+
// Read pub key
229+
pub_key = malloc(key_size + 1);
230+
size_t bytes_read = fread(pub_key, 1, key_size, file);
231+
fclose(file);
232+
233+
keyBinary = (u_char*)pub_key;
234+
keylen = (int)key_size;
235+
}
236+
else
237+
{
238+
keyBinary = jwtcf->auth_jwt_key.data;
239+
keylen = jwtcf->auth_jwt_key.len;
240+
}
182241
}
183242
else
184243
{
@@ -239,6 +298,8 @@ static ngx_int_t ngx_http_auth_jwt_handler(ngx_http_request_t *r)
239298

240299
jwt_free(jwt);
241300

301+
if (pub_key == NULL) free(pub_key);
302+
242303
return NGX_OK;
243304

244305
redirect:
@@ -374,6 +435,7 @@ ngx_http_auth_jwt_create_loc_conf(ngx_conf_t *cf)
374435
conf->auth_jwt_enabled = (ngx_flag_t) -1;
375436
conf->auth_jwt_redirect = (ngx_flag_t) -1;
376437
conf->auth_jwt_validate_email = (ngx_flag_t) -1;
438+
conf->auth_jwt_use_keyfile = (ngx_flag_t) -1;
377439

378440
ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0, "Created Location Configuration");
379441

@@ -391,6 +453,7 @@ ngx_http_auth_jwt_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
391453
ngx_conf_merge_str_value(conf->auth_jwt_key, prev->auth_jwt_key, "");
392454
ngx_conf_merge_str_value(conf->auth_jwt_validation_type, prev->auth_jwt_validation_type, "");
393455
ngx_conf_merge_str_value(conf->auth_jwt_algorithm, prev->auth_jwt_algorithm, "HS256");
456+
ngx_conf_merge_str_value(conf->auth_jwt_keyfile_path, prev->auth_jwt_keyfile_path, KEY_FILE_PATH);
394457
ngx_conf_merge_off_value(conf->auth_jwt_validate_email, prev->auth_jwt_validate_email, 1);
395458

396459
if (conf->auth_jwt_enabled == ((ngx_flag_t) -1))
@@ -403,6 +466,11 @@ ngx_http_auth_jwt_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
403466
conf->auth_jwt_redirect = (prev->auth_jwt_redirect == ((ngx_flag_t) -1)) ? 0 : prev->auth_jwt_redirect;
404467
}
405468

469+
if (conf->auth_jwt_use_keyfile == ((ngx_flag_t) -1))
470+
{
471+
conf->auth_jwt_use_keyfile = (prev->auth_jwt_use_keyfile == ((ngx_flag_t) -1)) ? 0 : prev->auth_jwt_use_keyfile;
472+
}
473+
406474
return NGX_CONF_OK;
407475
}
408476

0 commit comments

Comments
 (0)