Skip to content

Commit 3f12c92

Browse files
committed
3.5.0dev: implement OAuth2Require with liboauth2_nginx >= 1.6.3
see #7; thanks @smanolache Signed-off-by: Hans Zandbelt <[email protected]>
1 parent f51ec07 commit 3f12c92

File tree

5 files changed

+35
-238
lines changed

5 files changed

+35
-238
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@
2525
/config.sub~
2626
/configure~
2727
/install-sh~
28+
/autom4te.cache/

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
06/20/2024
2+
- implement OAuth2Require with liboauth2_nginx >= 1.6.3
3+
- bump to 3.5.0dev
4+
15
06/18/2024
26
- fix variable colision between requests; closes #8; see #7; thanks @smanolache
37

Makefile.am

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ AM_LDFLAGS = --coverage
99

1010
LDADD = $(CODE_COVERAGE_LIBS)
1111

12-
lib_LTLIBRARIES = @[email protected]
12+
pkglib_LTLIBRARIES = @[email protected]
13+
pkglibdir = $(libdir)/nginx/modules
1314

1415
@PACKAGE_NAME@_la_CFLAGS = @OAUTH2_CFLAGS@ @OAUTH2_NGINX_CFLAGS@ @NGINX_CFLAGS@
1516
@PACKAGE_NAME@_la_LIBADD = @OAUTH2_LIBS@ @OAUTH2_NGINX_LIBS@ @NGINX_LIBS@
@@ -22,10 +23,3 @@ lib_LTLIBRARIES = @[email protected]
2223

2324
clang-format:
2425
clang-format -style=file -i `find . -name *.[ch]`
25-
26-
install:
27-
${INSTALL} -d $(DESTDIR)/usr/local/nginx/modules/
28-
${INSTALL} -p -m 755 .libs/@[email protected] $(DESTDIR)/usr/local/nginx/modules/@[email protected]
29-
30-
uninstall:
31-
rm -f $(DESTDIR)/usr/local/nginx/modules/@[email protected]

configure.ac

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
AC_INIT([ngx_oauth2_module],[3.4.0],[[email protected]])
1+
AC_INIT([ngx_oauth2_module],[3.5.0dev],[[email protected]])
22

33
AM_INIT_AUTOMAKE([foreign no-define subdir-objects])
44
AC_CONFIG_MACRO_DIRS([m4])
@@ -25,11 +25,11 @@ AM_CONDITIONAL(HAVE_NGINX, [test x"$have_nginx" = "xyes"])
2525
AC_SUBST(NGINX_CFLAGS)
2626
AC_SUBST(NGINX_LIBS)
2727

28-
PKG_CHECK_MODULES(OAUTH2, [liboauth2 >= 1.6.2])
28+
PKG_CHECK_MODULES(OAUTH2, [liboauth2 >= 1.6.3])
2929
AC_SUBST(OAUTH2_CFLAGS)
3030
AC_SUBST(OAUTH2_LIBS)
3131

32-
PKG_CHECK_MODULES(OAUTH2_NGINX, [liboauth2_nginx >= 1.6.2])
32+
PKG_CHECK_MODULES(OAUTH2_NGINX, [liboauth2_nginx >= 1.6.3])
3333
AC_SUBST(OAUTH2_NGINX_CFLAGS)
3434
AC_SUBST(OAUTH2_NGINX_LIBS)
3535

src/ngx_oauth2_module.c

Lines changed: 25 additions & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,11 @@
3131
#include <oauth2/oauth2.h>
3232
#include <oauth2/version.h>
3333

34-
typedef struct ngx_oauth2_claims_hash_s {
35-
ngx_hash_keys_arrays_t keys;
36-
ngx_hash_t h;
37-
} ngx_oauth2_claims_hash_t;
38-
3934
typedef struct ngx_oauth2_cfg_t {
4035
ngx_http_complex_value_t source_token;
4136
oauth2_cfg_token_verify_t *verify;
4237
ngx_conf_t *cf;
38+
ngx_array_t *requirements;
4339
// TODO:
4440
oauth2_log_t *log;
4541
} ngx_oauth2_cfg_t;
@@ -59,6 +55,7 @@ static void *ngx_oauth2_create_loc_conf(ngx_conf_t *cf)
5955
cfg = ngx_pcalloc(cf->pool, sizeof(ngx_oauth2_cfg_t));
6056
cfg->log = NULL;
6157
cfg->cf = cf;
58+
cfg->requirements = NULL;
6259
cfg->verify = NULL;
6360
cfg->source_token.flushes = NULL;
6461
cfg->source_token.lengths = NULL;
@@ -88,39 +85,18 @@ static char *ngx_oauth2_merge_loc_conf(ngx_conf_t *cf, void *parent,
8885
ngx_oauth2_cfg_t *cfg = child;
8986

9087
cfg->cf = cf;
88+
if (cfg->requirements == NULL)
89+
/* no requirements were set in the child, copy those of the
90+
* parent; if the child has its own requirements then do not
91+
* override them with the parent's */
92+
cfg->requirements = prev->requirements;
9193
cfg->verify = cfg->verify
9294
? oauth2_cfg_token_verify_clone(NULL, cfg->verify)
9395
: oauth2_cfg_token_verify_clone(NULL, prev->verify);
9496

9597
return NGX_CONF_OK;
9698
}
9799

98-
static inline ngx_str_t chr_to_ngx_str(ngx_pool_t *p, const char *k)
99-
{
100-
ngx_str_t in = {strlen(k), (u_char *)k};
101-
ngx_str_t out = {in.len, ngx_pstrdup(p, &in)};
102-
return out;
103-
}
104-
105-
static inline char *ngx_str_to_chr(ngx_pool_t *p, const ngx_str_t *str)
106-
{
107-
char *s = ngx_pnalloc(p, str->len + 1);
108-
if (s) {
109-
memcpy(s, str->data, str->len);
110-
s[str->len] = '\0';
111-
}
112-
return s;
113-
}
114-
115-
static inline char *chr_to_chr(ngx_pool_t *p, const char *str)
116-
{
117-
ngx_str_t s = {strlen(str), (u_char *)str};
118-
return ngx_str_to_chr(p, &s);
119-
}
120-
121-
static char *ngx_oauth2_set_claim(ngx_conf_t *cf, ngx_command_t *cmd,
122-
void *conf);
123-
124100
// ngx_oauth2_cfg_set_token_verify
125101
OAUTH2_NGINX_CFG_FUNC_START(oauth2, ngx_oauth2_cfg_t, token_verify)
126102
int rc = NGX_OK;
@@ -140,7 +116,7 @@ if (rc != NGX_OK) {
140116
"expression %.*s",
141117
rc, (int)value[1].len, value[1].data);
142118
ngx_str_t msg = {n, (u_char *)&buf[0]};
143-
char *s = ngx_str_to_chr(cf->pool, &msg);
119+
char *s = oauth2_nginx_str2chr(cf->pool, &msg);
144120
return s ? s : NGX_CONF_ERROR;
145121
}
146122

@@ -161,17 +137,27 @@ oauth2_mem_free(v2);
161137
oauth2_mem_free(v1);
162138
OAUTH2_NGINX_CFG_FUNC_END(cf, rv)
163139

140+
OAUTH2_NGINX_CFG_FUNC_RET1(oauth2, ngx_oauth2_cfg_t, require,
141+
nginx_oauth2_set_require, requirements)
142+
164143
OAUTH2_NGINX_CFG_FUNC_ARGS1(oauth2, ngx_oauth2_cfg_t, passphrase,
165144
oauth2_crypto_passphrase_set, NULL)
166145
OAUTH2_NGINX_CFG_FUNC_ARGS2(oauth2, ngx_oauth2_cfg_t, cache,
167146
oauth2_cfg_set_cache, NULL)
168147

148+
ngx_module_t ngx_oauth2_module;
149+
OAUTH2_NGINX_CMD_SET_IMPL(oauth2, claim)
150+
169151
static ngx_command_t ngx_oauth2_commands[] = {
170152
OAUTH2_NGINX_CMD(1, oauth2, "OAuth2CryptoPassphrase", passphrase),
171153
OAUTH2_NGINX_CMD(12, oauth2, "OAuth2Cache", cache),
172154
OAUTH2_NGINX_CMD(3 | NGX_CONF_TAKE4, oauth2, "OAuth2TokenVerify",
173155
token_verify),
174-
OAUTH2_NGINX_CMD(2, oauth2, "OAuth2Claim", claim), ngx_null_command};
156+
OAUTH2_NGINX_CMD(123 | NGX_CONF_TAKE4 | NGX_CONF_TAKE5 | NGX_CONF_TAKE6 |
157+
NGX_CONF_TAKE7,
158+
oauth2, "OAuth2Require", require),
159+
OAUTH2_NGINX_CMD(2, oauth2, "OAuth2Claim", claim),
160+
ngx_null_command};
175161

176162
static ngx_int_t ngx_oauth2_post_config(ngx_conf_t *cf);
177163

@@ -241,199 +227,9 @@ static ngx_int_t ngx_oauth2_post_config(ngx_conf_t *cf)
241227
return rv;
242228
}
243229

244-
static ngx_int_t ngx_oauth2_claim_variable(ngx_http_request_t *r,
245-
ngx_http_variable_value_t *v,
246-
uintptr_t data)
247-
{
248-
ngx_oauth2_claims_hash_t *claims = NULL;
249-
const char *value = NULL;
250-
251-
ngx_str_t key = {strlen((const char *)data), (u_char *)data};
252-
253-
claims = (ngx_oauth2_claims_hash_t *)ngx_http_get_module_ctx(
254-
r, ngx_oauth2_module);
255-
if (!claims) {
256-
v->not_found = 1;
257-
return NGX_OK;
258-
}
259-
260-
value = (const char *)ngx_hash_find(
261-
&claims->h, ngx_hash_key(key.data, key.len), key.data, key.len);
262-
if (value) {
263-
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
264-
"ngx_oauth2_claim_variable: %V=%s", &key, value);
265-
v->data = (u_char *)value;
266-
v->len = strlen(value);
267-
v->no_cacheable = 1;
268-
v->not_found = 0;
269-
} else {
270-
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
271-
"ngx_oauth2_claim_variable: %V=(null)", &key);
272-
v->not_found = 1;
273-
}
274-
275-
return NGX_OK;
276-
}
277-
278-
static char *ngx_oauth2_set_claim(ngx_conf_t *cf, ngx_command_t *cmd,
279-
void *conf)
280-
{
281-
ngx_str_t *value;
282-
ngx_http_variable_t *v;
283-
284-
value = cf->args->elts;
285-
286-
if (value[2].len <= 1 || value[2].data[0] != '$') {
287-
static const size_t MAX_BUF = 128;
288-
char buf[MAX_BUF];
289-
int n = snprintf(buf, sizeof(buf), "Invalid variable name %.*s",
290-
(int)value[2].len, value[2].data);
291-
ngx_str_t msg = {n, (u_char *)&buf[0]};
292-
char *s = ngx_str_to_chr(cf->pool, &msg);
293-
return s ? s : NGX_CONF_ERROR;
294-
}
295-
296-
value[2].len--;
297-
value[2].data++;
298-
299-
v = ngx_http_add_variable(cf, &value[2], NGX_HTTP_VAR_CHANGEABLE);
300-
if (!v) {
301-
ngx_str_t msg = ngx_string("ngx_http_add_variable failed");
302-
char *rv = ngx_str_to_chr(cf->pool, &msg);
303-
return rv ? rv : NGX_CONF_ERROR;
304-
}
305-
306-
v->get_handler = ngx_oauth2_claim_variable;
307-
char *claim = ngx_str_to_chr(cf->pool, &value[1]);
308-
if (!claim) {
309-
ngx_str_t msg = ngx_string("Out of memory");
310-
char *rv = ngx_str_to_chr(cf->pool, &msg);
311-
return rv ? rv : NGX_CONF_ERROR;
312-
}
313-
v->data = (uintptr_t)claim;
314-
315-
return NGX_CONF_OK;
316-
}
317-
318-
static ngx_int_t ngx_set_target_variable(ngx_oauth2_claims_hash_t *claims,
319-
oauth2_nginx_request_context_t *ctx,
320-
const char *k, const char *v)
321-
{
322-
ngx_str_t key = chr_to_ngx_str(claims->keys.pool, k);
323-
if (!key.data)
324-
return NGX_ERROR;
325-
326-
const char *value = chr_to_chr(claims->keys.pool, v);
327-
if (!value)
328-
return NGX_ERROR;
329-
330-
return ngx_hash_add_key(&claims->keys, &key, (char *)value,
331-
NGX_HASH_READONLY_KEY);
332-
}
333-
334-
static ngx_int_t ngx_oauth2_init_keys(ngx_pool_t *pool,
335-
ngx_oauth2_claims_hash_t *claims)
336-
{
337-
claims->keys.pool = pool;
338-
claims->keys.temp_pool = pool;
339-
340-
return ngx_hash_keys_array_init(&claims->keys, NGX_HASH_SMALL);
341-
}
342-
343-
static ngx_int_t ngx_oauth2_init_hash(ngx_pool_t *pool,
344-
ngx_oauth2_claims_hash_t *claims)
345-
{
346-
ngx_hash_init_t init;
347-
348-
init.hash = &claims->h;
349-
init.key = ngx_hash_key;
350-
init.max_size = 64;
351-
init.bucket_size = ngx_align(64, ngx_cacheline_size);
352-
init.name = "claims";
353-
init.pool = pool;
354-
init.temp_pool = pool;
355-
356-
return ngx_hash_init(&init, claims->keys.keys.elts,
357-
claims->keys.keys.nelts);
358-
}
359-
360-
// TODO: generalize/callback part of this (at least the looping and encoding is
361-
// generic)
362-
static ngx_int_t ngx_set_target_variables(ngx_http_request_t *r,
363-
oauth2_nginx_request_context_t *ctx,
364-
json_t *json_token)
365-
{
366-
void *iter = NULL;
367-
const char *key = NULL;
368-
json_t *value = NULL;
369-
ngx_oauth2_claims_hash_t *claims = NULL;
370-
int rc = NGX_OK;
371-
372-
claims = (ngx_oauth2_claims_hash_t *)ngx_http_get_module_ctx(
373-
r, ngx_oauth2_module);
374-
if (!claims) {
375-
claims = ngx_palloc(r->pool, sizeof(*claims));
376-
if (!claims) {
377-
ngx_log_error(NGX_LOG_ERR, r->connection->log,
378-
NGX_ENOMEM,
379-
"ngx_set_target_variables: "
380-
"error allocating claims hash");
381-
return NGX_ERROR;
382-
}
383-
384-
rc = ngx_oauth2_init_keys(r->pool, claims);
385-
if (NGX_OK != rc) {
386-
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
387-
"ngx_set_target_variables: error %d "
388-
"initializing hash keys",
389-
rc);
390-
return rc;
391-
}
392-
393-
ngx_http_set_ctx(r, claims, ngx_oauth2_module);
394-
}
395-
396-
iter = json_object_iter(json_token);
397-
while (iter) {
398-
key = json_object_iter_key(iter);
399-
value = json_object_iter_value(iter);
400-
if (json_is_string(value)) {
401-
rc = ngx_set_target_variable(claims, ctx, key,
402-
json_string_value(value));
403-
} else {
404-
const char *val = oauth2_json_encode(ctx->log, value,
405-
JSON_ENCODE_ANY);
406-
rc = ngx_set_target_variable(claims, ctx, key, val);
407-
oauth2_mem_free((char *)val);
408-
}
409-
410-
if (NGX_OK != rc) {
411-
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
412-
"ngx_set_target_variables: error %d "
413-
"setting value of key %s in claims hash",
414-
rc, key);
415-
return rc;
416-
}
417-
418-
iter = json_object_iter_next(json_token, iter);
419-
}
420-
421-
rc = ngx_oauth2_init_hash(r->pool, claims);
422-
if (NGX_OK != rc) {
423-
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
424-
"ngx_set_target_variables: error %d initializing "
425-
"claims hash",
426-
rc);
427-
return rc;
428-
}
429-
430-
return NGX_OK;
431-
}
432-
433230
static ngx_int_t ngx_oauth2_handler(ngx_http_request_t *r)
434231
{
435232
ngx_int_t rv = NGX_DECLINED;
436-
// bool rc = false;
437233
oauth2_nginx_request_context_t *ctx = NULL;
438234
ngx_oauth2_cfg_t *cfg = NULL;
439235
ngx_str_t ngx_source_token;
@@ -466,9 +262,6 @@ static ngx_int_t ngx_oauth2_handler(ngx_http_request_t *r)
466262
return NGX_ERROR;
467263
}
468264

469-
// TODO: if we have a verify post config, call it here
470-
// ...
471-
472265
ngx_str_null(&ngx_source_token);
473266
rv = ngx_http_complex_value(r, &cfg->source_token, &ngx_source_token);
474267
if (rv != NGX_OK) {
@@ -503,7 +296,12 @@ static ngx_int_t ngx_oauth2_handler(ngx_http_request_t *r)
503296

504297
oauth2_debug(ctx->log, "json_payload=%p", json_payload);
505298

506-
rv = ngx_set_target_variables(r, ctx, json_payload);
299+
rv = oauth2_nginx_set_target_variables(ngx_oauth2_module, ctx,
300+
json_payload);
301+
if (rv != NGX_OK)
302+
goto end;
303+
304+
rv = nginx_oauth2_check_requirements(ctx, cfg->requirements);
507305

508306
end:
509307

0 commit comments

Comments
 (0)