Skip to content

Commit a14ed22

Browse files
committed
ensure backwards compatibility for multi-value ID token "aud" validation
ensure backwards compatibility with versions <2.4.16.x when a JSON array of string values is provided in the "aud" claim of the ID token; required by (at least) Oracle IDCS see #1272 and #1273; thanks @lufik and @tydalforce add OIDCIDTokenAudValues configuration primitive that allows for explicit (and exhaustive) configuration of the list of accepted values in the "aud" claim of the ID token e.g. as required for passing FAPI 2 conformance testing bump to 2.4.16.5rc0 Signed-off-by: Hans Zandbelt <[email protected]>
1 parent 38bbedf commit a14ed22

File tree

13 files changed

+185
-42
lines changed

13 files changed

+185
-42
lines changed

ChangeLog

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
10/04/2024
2+
- ensure backwards compatibility with versions <2.4.16.x when a JSON array of string values
3+
is provided in the "aud" claim of the ID token; required by (at least) Oracle IDCS
4+
see #1272 and #1273; thanks @lufik and @tydalforce
5+
- add OIDCIDTokenAudValues configuration primitive that allows for explicit (and exhaustive)
6+
configuration of the list of accepted values in the "aud" claim of the ID token
7+
e.g. as required for passing FAPI 2 conformance testing
8+
- bump to 2.4.16.5rc0
9+
110
09/29/2024
211
- release 2.4.16.4
312

auth_openidc.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,12 @@
347347
# NB: this can be overridden on a per-OP basis in the .conf file using the key: id_token_encrypted_response_enc
348348
#OIDCIDTokenEncryptedResponseEnc [A128CBC-HS256|A256CBC-HS512|A256GCM]
349349

350+
# The accepted value(s) of the "aud" claim in the ID token, restricted to only those values that have been defined here.
351+
# The convienience value "@" can be used to refer to the configured client id (i.e. in case of dynamic client registration).
352+
# When not defined the default is to accept any list of values (or a single string value) that includes value of OIDCClientID.
353+
# NB: this can be overridden on a per-OP basis in the .conf file using the key: id_token_aud_values with the value set to a JSON array of strings.
354+
#OIDCIDTokenAudValues <value>+
355+
350356
# The algorithm that the OP should use to sign the UserInfo response
351357
# When not defined the default (by spec) is that the OP does not sign the response.
352358
# (ES??? algorithms only supported when using OpenSSL >= 1.0)

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
AC_INIT([mod_auth_openidc],[2.4.16.4],[[email protected]])
1+
AC_INIT([mod_auth_openidc],[2.4.16.5rc0],[[email protected]])
22

33
AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
44

src/cfg/cfg.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@
5252
#include "session.h"
5353
#include "util.h"
5454

55+
const char *oidc_cfg_string_list_add(apr_pool_t *pool, apr_array_header_t **list, const char *arg) {
56+
if (*list == NULL)
57+
*list = apr_array_make(pool, 1, sizeof(const char *));
58+
APR_ARRAY_PUSH(*list, const char *) = arg;
59+
return NULL;
60+
}
61+
5562
#define OIDC_DEFAULT_ACTION_ON_USERINFO_ERROR OIDC_ON_ERROR_502
5663
OIDC_CFG_MEMBER_FUNC_TYPE_GET(action_on_userinfo_error, oidc_on_error_action_t, OIDC_DEFAULT_ACTION_ON_USERINFO_ERROR)
5764

src/cfg/cfg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ void *oidc_cfg_server_merge(apr_pool_t *pool, void *BASE, void *ADD);
186186
int oidc_cfg_post_config(oidc_cfg_t *cfg, server_rec *s);
187187
void oidc_cfg_child_init(apr_pool_t *pool, oidc_cfg_t *cfg, server_rec *s);
188188
void oidc_cfg_cleanup_child(oidc_cfg_t *cfg, server_rec *s);
189+
const char *oidc_cfg_string_list_add(apr_pool_t *pool, apr_array_header_t **list, const char *arg);
189190

190191
#define OIDC_CFG_MEMBER_FUNC_NAME(member, type, method) oidc_##type##_##member##_##method
191192

src/cfg/cmds.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,11 @@ const command_rec oidc_cfg_cmds[] = {
465465
OIDCIDTokenEncryptedResponseEnc,
466466
id_token_encrypted_response_enc,
467467
"The algorithm that the OP should use to encrypt to the id_token with the Content Encryption Key (used only in dynamic client registration); must be one of [A128CBC-HS256|A256CBC-HS512|A256GCM]"),
468+
OIDC_CFG_CMD_PROVIDER(
469+
AP_INIT_ITERATE,
470+
OIDCIDTokenAudValues,
471+
id_token_aud_values,
472+
"Accepted \"aud\" claim values in the ID token."),
468473
OIDC_CFG_CMD_PROVIDER(
469474
AP_INIT_TAKE1,
470475
OIDCUserInfoSignedResponseAlg,

src/cfg/dir.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,14 @@ const char *oidc_cmd_dir_accept_oauth_token_in_set(cmd_parms *cmd, void *m, cons
244244
/*
245245
* specify cookies names to pass/strip
246246
*/
247-
static const char *oidc_cfg_dir_cookie_names_set(apr_pool_t *pool, apr_array_header_t **cookie_names, const char *arg) {
248-
if (*cookie_names == NULL)
249-
*cookie_names = apr_array_make(pool, 3, sizeof(const char *));
250-
APR_ARRAY_PUSH(*cookie_names, const char *) = arg;
251-
return NULL;
252-
}
253-
254247
const char *oidc_cmd_dir_strip_cookies_set(cmd_parms *cmd, void *m, const char *arg) {
255248
oidc_dir_cfg_t *dir_cfg = (oidc_dir_cfg_t *)m;
256-
return oidc_cfg_dir_cookie_names_set(cmd->pool, &dir_cfg->strip_cookies, arg);
249+
return oidc_cfg_string_list_add(cmd->pool, &dir_cfg->strip_cookies, arg);
257250
}
258251

259252
const char *oidc_cmd_dir_pass_cookies_set(cmd_parms *cmd, void *m, const char *arg) {
260253
oidc_dir_cfg_t *dir_cfg = (oidc_dir_cfg_t *)m;
261-
return oidc_cfg_dir_cookie_names_set(cmd->pool, &dir_cfg->pass_cookies, arg);
254+
return oidc_cfg_string_list_add(cmd->pool, &dir_cfg->pass_cookies, arg);
262255
}
263256

264257
#define OIDC_CFG_DIR_MEMBER_FUNC_GET(member, type, def_val, unset_val) \

src/cfg/provider.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct oidc_provider_t {
8989
char *id_token_signed_response_alg;
9090
char *id_token_encrypted_response_alg;
9191
char *id_token_encrypted_response_enc;
92+
apr_array_header_t *id_token_aud_values;
9293
char *userinfo_signed_response_alg;
9394
char *userinfo_encrypted_response_alg;
9495
char *userinfo_encrypted_response_enc;
@@ -240,6 +241,28 @@ OIDC_PROVIDER_TYPE_MEMBER_FUNCS_PASSPHRASE(token_endpoint_tls_client_key_pwd)
240241
OIDC_PROVIDER_MEMBER_FUNCS_KEYS(verify_public_keys)
241242
OIDC_PROVIDER_MEMBER_FUNCS_KEYS(client_keys)
242243

244+
/*
245+
* string list
246+
*/
247+
248+
#define OIDC_PROVIDER_MEMBER_FUNCS_STR_LIST(member) \
249+
\
250+
const char *oidc_cfg_provider_##member##_set_str_list(apr_pool_t *pool, oidc_provider_t *provider, \
251+
apr_array_header_t *arg) { \
252+
provider->member = arg; \
253+
return NULL; \
254+
} \
255+
\
256+
const char *oidc_cfg_provider_##member##_set(apr_pool_t *pool, oidc_provider_t *provider, const char *arg) { \
257+
return oidc_cfg_string_list_add(pool, &provider->member, arg); \
258+
} \
259+
OIDC_PROVIDER_MEMBER_FUNCS_TYPE_DEF(member, const apr_array_header_t *, NULL)
260+
261+
/*
262+
* id token aud values
263+
*/
264+
OIDC_PROVIDER_MEMBER_FUNCS_STR_LIST(id_token_aud_values)
265+
243266
/*
244267
* PKCE
245268
*/
@@ -701,6 +724,8 @@ static void oidc_cfg_provider_init(oidc_provider_t *provider) {
701724
provider->request_object = NULL;
702725

703726
provider->response_require_iss = OIDC_CONFIG_POS_INT_UNSET;
727+
728+
provider->id_token_aud_values = NULL;
704729
}
705730

706731
void oidc_cfg_provider_merge(apr_pool_t *pool, oidc_provider_t *dst, const oidc_provider_t *base,
@@ -812,6 +837,9 @@ void oidc_cfg_provider_merge(apr_pool_t *pool, oidc_provider_t *dst, const oidc_
812837

813838
dst->response_require_iss = add->response_require_iss != OIDC_CONFIG_POS_INT_UNSET ? add->response_require_iss
814839
: base->response_require_iss;
840+
841+
dst->id_token_aud_values =
842+
add->id_token_aud_values != NULL ? add->id_token_aud_values : base->id_token_aud_values;
815843
}
816844

817845
oidc_provider_t *oidc_cfg_provider_create(apr_pool_t *pool) {

src/cfg/provider.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ typedef struct oidc_jwks_uri_t {
122122
#define OIDCIDTokenSignedResponseAlg "OIDCIDTokenSignedResponseAlg"
123123
#define OIDCIDTokenEncryptedResponseAlg "OIDCIDTokenEncryptedResponseAlg"
124124
#define OIDCIDTokenEncryptedResponseEnc "OIDCIDTokenEncryptedResponseEnc"
125+
#define OIDCIDTokenAudValues "OIDCIDTokenAudValues"
125126
#define OIDCUserInfoSignedResponseAlg "OIDCUserInfoSignedResponseAlg"
126127
#define OIDCUserInfoEncryptedResponseAlg "OIDCUserInfoEncryptedResponseAlg"
127128
#define OIDCUserInfoEncryptedResponseEnc "OIDCUserInfoEncryptedResponseEnc"
@@ -178,6 +179,11 @@ typedef struct oidc_jwks_uri_t {
178179
OIDC_CFG_PROVIDER_MEMBER_FUNCS_TYPE_DECL(member, type) \
179180
void OIDC_CFG_MEMBER_FUNC_NAME(member, cfg_provider, int_set)(oidc_provider_t * provider, type arg);
180181

182+
#define OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_LIST_DECL(member) \
183+
OIDC_CFG_PROVIDER_MEMBER_FUNCS_TYPE_DECL(member, const apr_array_header_t *) \
184+
const char *OIDC_CFG_MEMBER_FUNC_NAME(member, cfg_provider, set_str_list)(apr_pool_t *, oidc_provider_t *, \
185+
apr_array_header_t *);
186+
181187
OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_DECL(metadata_url)
182188
OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_DECL(issuer)
183189
OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_DECL(authorization_endpoint_url);
@@ -212,6 +218,9 @@ OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_DECL(userinfo_encrypted_response_alg)
212218
OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_DECL(userinfo_encrypted_response_enc)
213219
OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_DECL(request_object)
214220

221+
// string list
222+
OIDC_CFG_PROVIDER_MEMBER_FUNCS_STR_LIST_DECL(id_token_aud_values)
223+
215224
// keys
216225
OIDC_CFG_PROVIDER_MEMBER_FUNCS_KEYS_DECL(verify_public_keys)
217226
OIDC_CFG_PROVIDER_MEMBER_FUNCS_KEYS_DECL(client_keys)

src/metadata.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
#define OIDC_METADATA_ID_TOKEN_SIGNED_RESPONSE_ALG "id_token_signed_response_alg"
8686
#define OIDC_METADATA_ID_TOKEN_ENCRYPTED_RESPONSE_ALG "id_token_encrypted_response_alg"
8787
#define OIDC_METADATA_ID_TOKEN_ENCRYPTED_RESPONSE_ENC "id_token_encrypted_response_enc"
88+
#define OIDC_METADATA_ID_TOKEN_AUD_VALUES "id_token_aud_values"
8889
#define OIDC_METADATA_USERINFO_SIGNED_RESPONSE_ALG "userinfo_signed_response_alg"
8990
#define OIDC_METADATA_USERINFO_ENCRYPTED_RESPONSE_ALG "userinfo_encrypted_response_alg"
9091
#define OIDC_METADATA_USERINFO_ENCRYPTED_RESPONSE_ENC "userinfo_encrypted_response_enc"
@@ -1228,7 +1229,7 @@ apr_byte_t oidc_metadata_conf_parse(request_rec *r, oidc_cfg_t *cfg, json_t *j_c
12281229
const char *rv = NULL;
12291230
char *value = NULL;
12301231
int ivalue = OIDC_CONFIG_POS_INT_UNSET;
1231-
apr_array_header_t *keys = NULL;
1232+
apr_array_header_t *keys = NULL, *auds = NULL;
12321233

12331234
oidc_util_json_object_get_string(r->pool, j_conf, OIDC_METADATA_CLIENT_JWKS_URI, &value,
12341235
oidc_cfg_provider_client_jwks_uri_get(oidc_cfg_provider_get(cfg)));
@@ -1263,6 +1264,14 @@ apr_byte_t oidc_metadata_conf_parse(request_rec *r, oidc_cfg_t *cfg, json_t *j_c
12631264
oidc_cfg_provider_id_token_encrypted_response_enc_get(oidc_cfg_provider_get(cfg)));
12641265
OIDC_METADATA_PROVIDER_SET(id_token_encrypted_response_enc, value, rv)
12651266

1267+
oidc_util_json_object_get_string_array(r->pool, j_conf, OIDC_METADATA_ID_TOKEN_AUD_VALUES, &auds,
1268+
oidc_cfg_provider_id_token_aud_values_get(oidc_cfg_provider_get(cfg)));
1269+
if (auds != NULL) {
1270+
rv = oidc_cfg_provider_id_token_aud_values_set_str_list(r->pool, provider, auds);
1271+
if (rv != NULL)
1272+
oidc_error(r, "oidc_cfg_provider_aud_values_set: %s", rv);
1273+
}
1274+
12661275
/* get the (optional) signing & encryption settings for the userinfo response */
12671276
oidc_util_json_object_get_string(
12681277
r->pool, j_conf, OIDC_METADATA_USERINFO_SIGNED_RESPONSE_ALG, &value,

0 commit comments

Comments
 (0)