Skip to content

Commit 6537014

Browse files
committed
add NGINX functions for setting claim variables in the request context
see OpenIDC/ngx_oauth2_module#7; thanks @@smanolache and @pladen; bump to 1.6.3dev Signed-off-by: Hans Zandbelt <[email protected]>
1 parent 1c9bbeb commit 6537014

File tree

7 files changed

+304
-3
lines changed

7 files changed

+304
-3
lines changed

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ reporting bugs, providing fixes, suggesting useful features or other:
1313
Robert Title <https://github.com/rtitle>
1414
may-day <https://github.com/may-day>
1515
Pavel Anpin <https://github.com/anpin>
16+
smanolache <https://github.com/smanolache>
17+
pladen <https://github.com/pladen>

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
06/19/2024
2+
- add NGINX macros/functions for setting claim variables in the request context
3+
see OpenIDC/ngx_oauth2_module#7; thanks @@smanolache and @pladen
4+
- bump to 1.6.3dev
5+
.
16
06/05/2024
27
- release 1.6.2
38

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
AC_INIT([liboauth2],[1.6.2],[[email protected]])
1+
AC_INIT([liboauth2],[1.6.3dev],[[email protected]])
22

33
AM_INIT_AUTOMAKE([foreign no-define subdir-objects])
44
AC_CONFIG_MACRO_DIR([m4])

include/oauth2/nginx.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,37 @@ ngx_int_t oauth2_nginx_http_response_set(oauth2_log_t *log,
140140
oauth2_http_response_t *response,
141141
ngx_http_request_t *r);
142142

143+
//
144+
145+
char *oauth2_nginx_str2chr(ngx_pool_t *p, const ngx_str_t *str);
146+
147+
#define OAUTH2_NGINX_CMD_SET_IMPL(module, primitive) \
148+
static ngx_int_t ngx_##module##_##primitive##_variable( \
149+
ngx_http_request_t *r, ngx_http_variable_value_t *v, \
150+
uintptr_t data) \
151+
{ \
152+
return oauth2_nginx_##primitive##_variable( \
153+
ngx_##module##_module, r, v, data); \
154+
} \
155+
\
156+
static char *ngx_##module##_set_##primitive( \
157+
ngx_conf_t *cf, ngx_command_t *cmd, void *conf) \
158+
{ \
159+
return oauth2_nginx_set_##primitive( \
160+
ngx_##module##_module, \
161+
ngx_##module##_##primitive##_variable, cf, cmd, conf); \
162+
}
163+
164+
ngx_int_t oauth2_nginx_claim_variable(ngx_module_t module,
165+
ngx_http_request_t *r,
166+
ngx_http_variable_value_t *v,
167+
uintptr_t data);
168+
char *oauth2_nginx_set_claim(ngx_module_t module,
169+
ngx_http_get_variable_pt handler, ngx_conf_t *cf,
170+
ngx_command_t *cmd, void *conf);
171+
172+
ngx_int_t oauth2_nginx_set_target_variables(ngx_module_t module,
173+
oauth2_nginx_request_context_t *ctx,
174+
json_t *json_token);
175+
143176
#endif /* _OAUTH2_NGINX_H_ */

src/server/nginx.c

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,217 @@ ngx_int_t oauth2_nginx_http_response_set(oauth2_log_t *log,
344344

345345
return nrc;
346346
}
347+
348+
typedef struct oauth2_nginx_claim_hash_t {
349+
ngx_hash_keys_arrays_t keys;
350+
ngx_hash_t h;
351+
} oauth2_nginx_claim_hash_t;
352+
353+
static inline ngx_str_t oauth2_nginx_chr2str(ngx_pool_t *p, const char *k)
354+
{
355+
ngx_str_t in = {strlen(k), (u_char *)k};
356+
ngx_str_t out = {in.len, ngx_pstrdup(p, &in)};
357+
return out;
358+
}
359+
360+
char *oauth2_nginx_str2chr(ngx_pool_t *p, const ngx_str_t *str)
361+
{
362+
char *s = ngx_pnalloc(p, str->len + 1);
363+
if (s != NULL) {
364+
memcpy(s, str->data, str->len);
365+
s[str->len] = '\0';
366+
}
367+
return s;
368+
}
369+
370+
static inline char *oauth2_nginx_chr2chr(ngx_pool_t *p, const char *str)
371+
{
372+
ngx_str_t s = {strlen(str), (u_char *)str};
373+
return oauth2_nginx_str2chr(p, &s);
374+
}
375+
376+
ngx_int_t oauth2_nginx_claim_variable(ngx_module_t module,
377+
ngx_http_request_t *r,
378+
ngx_http_variable_value_t *v,
379+
uintptr_t data)
380+
{
381+
oauth2_nginx_claim_hash_t *claims = NULL;
382+
const char *value = NULL;
383+
ngx_str_t key = {strlen((const char *)data), (u_char *)data};
384+
385+
claims =
386+
(oauth2_nginx_claim_hash_t *)ngx_http_get_module_ctx(r, module);
387+
388+
if (claims == NULL) {
389+
v->not_found = 1;
390+
return NGX_OK;
391+
}
392+
393+
value = (const char *)ngx_hash_find(
394+
&claims->h, ngx_hash_key(key.data, key.len), key.data, key.len);
395+
396+
if (value != NULL) {
397+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
398+
"oauth2_nginx_claim_variable: %V=%s", &key,
399+
value);
400+
v->data = (u_char *)value;
401+
v->len = strlen(value);
402+
v->no_cacheable = 1;
403+
v->not_found = 0;
404+
} else {
405+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
406+
"oauth2_nginx_claim_variable: %V=(null)", &key);
407+
v->not_found = 1;
408+
}
409+
410+
return NGX_OK;
411+
}
412+
413+
static const size_t MAX_BUF = 128;
414+
415+
char *oauth2_nginx_set_claim(ngx_module_t module,
416+
ngx_http_get_variable_pt handler, ngx_conf_t *cf,
417+
ngx_command_t *cmd, void *conf)
418+
{
419+
ngx_http_variable_t *v;
420+
char buf[MAX_BUF];
421+
int n = 0;
422+
char *s = NULL;
423+
ngx_str_t *value = cf->args->elts;
424+
425+
if (value[2].len <= 1 || value[2].data[0] != '$') {
426+
n = snprintf(buf, sizeof(buf), "Invalid variable name %.*s",
427+
(int)value[2].len, value[2].data);
428+
ngx_str_t msg = {n, (u_char *)&buf[0]};
429+
s = oauth2_nginx_str2chr(cf->pool, &msg);
430+
return s ? s : NGX_CONF_ERROR;
431+
}
432+
433+
value[2].len--;
434+
value[2].data++;
435+
436+
v = ngx_http_add_variable(cf, &value[2], NGX_HTTP_VAR_CHANGEABLE);
437+
if (!v) {
438+
ngx_str_t msg = ngx_string("ngx_http_add_variable failed");
439+
s = oauth2_nginx_str2chr(cf->pool, &msg);
440+
return s ? s : NGX_CONF_ERROR;
441+
}
442+
443+
v->get_handler = handler;
444+
char *claim = oauth2_nginx_str2chr(cf->pool, &value[1]);
445+
if (!claim) {
446+
ngx_str_t msg = ngx_string("Out of memory");
447+
s = oauth2_nginx_str2chr(cf->pool, &msg);
448+
return s ? s : NGX_CONF_ERROR;
449+
}
450+
v->data = (uintptr_t)claim;
451+
452+
return NGX_CONF_OK;
453+
}
454+
455+
static ngx_int_t ngx_set_target_variable(oauth2_nginx_claim_hash_t *claims,
456+
oauth2_nginx_request_context_t *ctx,
457+
const char *k, const char *v)
458+
{
459+
ngx_str_t key = oauth2_nginx_chr2str(claims->keys.pool, k);
460+
if (key.data == NULL)
461+
return NGX_ERROR;
462+
const char *value = oauth2_nginx_chr2chr(claims->keys.pool, v);
463+
if (value == NULL)
464+
return NGX_ERROR;
465+
return ngx_hash_add_key(&claims->keys, &key, (char *)value,
466+
NGX_HASH_READONLY_KEY);
467+
}
468+
469+
static ngx_int_t ngx_oauth2_init_keys(ngx_pool_t *pool,
470+
oauth2_nginx_claim_hash_t *claims)
471+
{
472+
claims->keys.pool = pool;
473+
claims->keys.temp_pool = pool;
474+
return ngx_hash_keys_array_init(&claims->keys, NGX_HASH_SMALL);
475+
}
476+
477+
static ngx_int_t ngx_oauth2_init_hash(ngx_pool_t *pool,
478+
oauth2_nginx_claim_hash_t *claims)
479+
{
480+
ngx_hash_init_t init;
481+
init.hash = &claims->h;
482+
init.key = ngx_hash_key;
483+
init.max_size = 64;
484+
init.bucket_size = ngx_align(64, ngx_cacheline_size);
485+
init.name = "claims";
486+
init.pool = pool;
487+
init.temp_pool = pool;
488+
return ngx_hash_init(&init, claims->keys.keys.elts,
489+
claims->keys.keys.nelts);
490+
}
491+
492+
ngx_int_t oauth2_nginx_set_target_variables(ngx_module_t module,
493+
oauth2_nginx_request_context_t *ctx,
494+
json_t *json_token)
495+
{
496+
void *iter = NULL;
497+
const char *key = NULL, *val = NULL;
498+
json_t *value = NULL;
499+
oauth2_nginx_claim_hash_t *claims = NULL;
500+
int rc = NGX_OK;
501+
502+
claims = (oauth2_nginx_claim_hash_t *)ngx_http_get_module_ctx(ctx->r,
503+
module);
504+
505+
if (claims == NULL) {
506+
507+
claims = ngx_palloc(ctx->r->pool, sizeof(*claims));
508+
509+
if (claims == NULL) {
510+
oauth2_error(ctx->log, "error allocating claims hash");
511+
return NGX_ERROR;
512+
}
513+
514+
rc = ngx_oauth2_init_keys(ctx->r->pool, claims);
515+
516+
if (rc != NGX_OK) {
517+
oauth2_error(ctx->log,
518+
"error %d initializing hash keys", rc);
519+
return rc;
520+
}
521+
522+
ngx_http_set_ctx(ctx->r, claims, module);
523+
}
524+
525+
iter = json_object_iter(json_token);
526+
while (iter) {
527+
528+
key = json_object_iter_key(iter);
529+
value = json_object_iter_value(iter);
530+
531+
if (json_is_string(value)) {
532+
rc = ngx_set_target_variable(claims, ctx, key,
533+
json_string_value(value));
534+
} else {
535+
val = oauth2_json_encode(ctx->log, value,
536+
JSON_ENCODE_ANY);
537+
rc = ngx_set_target_variable(claims, ctx, key, val);
538+
oauth2_mem_free((char *)val);
539+
}
540+
541+
if (rc != NGX_OK) {
542+
oauth2_error(
543+
ctx->log,
544+
"error %d setting value of key %s in claims hash",
545+
rc, key);
546+
return rc;
547+
}
548+
549+
iter = json_object_iter_next(json_token, iter);
550+
}
551+
552+
rc = ngx_oauth2_init_hash(ctx->r->pool, claims);
553+
554+
if (rc != NGX_OK) {
555+
oauth2_error(ctx->log, "error %d initializing claims hash", rc);
556+
return rc;
557+
}
558+
559+
return NGX_OK;
560+
}

test/check_cache.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,7 @@ START_TEST(test_cache_redis)
205205
char *rv = NULL;
206206

207207
//&password=foobared
208-
rv = oauth2_cfg_set_cache(_log, NULL, "redis",
209-
"name=redis");
208+
rv = oauth2_cfg_set_cache(_log, NULL, "redis", "name=redis");
210209
ck_assert_ptr_eq(rv, NULL);
211210
c = oauth2_cache_obtain(_log, "redis");
212211
ck_assert_ptr_ne(c, NULL);

test/server_stubs.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ void *ngx_palloc(ngx_pool_t *pool, size_t size)
149149
return p;
150150
}
151151

152+
void *ngx_pnalloc(ngx_pool_t *pool, size_t size)
153+
{
154+
void *p = (void *)oauth2_mem_alloc(size);
155+
return p;
156+
}
157+
152158
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p)
153159
{
154160
oauth2_mem_free(p);
@@ -200,4 +206,46 @@ ngx_uint_t ngx_hash_strlow(u_char *dst, u_char *src, size_t n)
200206
return 0;
201207
}
202208

209+
ngx_uint_t ngx_cacheline_size = 64;
210+
211+
ngx_uint_t ngx_hash_key(u_char *data, size_t len)
212+
{
213+
return (ngx_uint_t)(*data);
214+
}
215+
216+
u_char *ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
217+
{
218+
u_char *dst = ngx_pnalloc(pool, src->len);
219+
memcpy(dst, src->data, src->len);
220+
return dst;
221+
}
222+
223+
ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
224+
ngx_uint_t nelts)
225+
{
226+
return 0;
227+
}
228+
229+
ngx_int_t ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
230+
{
231+
return 0;
232+
}
233+
234+
ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key,
235+
void *value, ngx_uint_t flags)
236+
{
237+
return 0;
238+
}
239+
240+
void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len)
241+
{
242+
return NULL;
243+
}
244+
245+
ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name,
246+
ngx_uint_t flags)
247+
{
248+
return NULL;
249+
}
250+
203251
#endif

0 commit comments

Comments
 (0)