Skip to content

Commit

Permalink
configure the DPoP API with OIDCDPoPMode instead of OIDCInfoHook
Browse files Browse the repository at this point in the history
Signed-off-by: Hans Zandbelt <[email protected]>
  • Loading branch information
zandbelt committed Jun 17, 2024
1 parent 1ca9658 commit 28557c1
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 25 deletions.
2 changes: 1 addition & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
08/08/2024
06/08/2024
- support DPoP nonces to the userinfo endpoint

06/07/2024
Expand Down
8 changes: 5 additions & 3 deletions auth_openidc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,10 @@
# required: a DPoP token is requested from the OP and we'll fail if the returned token type is not DPoP
# When not defined "off" is used.
# NB: this can be overridden on a per-OP basis in the .conf file using the key: dpop_mode
#OIDCDPoPMode [ off | optional | required]
# The 2nd parameter is used to optionally enable an API for creating DPoP proofs on:
# <redirect_uri>?dpop=<access_token>&url=<url>[&method=<method][&nonce=<nonce>]
# When not defined "off" is used.
#OIDCDPoPMode [off|optional|required] [on|off]

# (used only in dynamic client registration)
# Define the Client JWKs URL (e.g. https://localhost/protected/?jwks=rsa)") that will be
Expand Down Expand Up @@ -1035,11 +1038,10 @@
# timeout (int) : the session inactivity timeout (Unix timestamp in seconds)
# remote_user (string) : the remote user name
# session (object) : (for debugging) mod_auth_openidc specific session data such as "remote user", "session expiry", "session id" and a "state" object
# dpop : enable API for creating DPoP proofs <redirect_uri>?dpop=<access_token>&url=<url>[&method=<method][&nonce=<nonce>]
# Note that when using ProxyPass / you may have to add a proxy exception for the Redirect URI
# for this to work, e.g. ProxyPass /redirect_uri !
# When not defined the session hook will not return any data but a HTTP 404
#OIDCInfoHook [iat|access_token|access_token_expires|id_token|id_token_hint|userinfo|refresh_token|exp|timeout|remote_user|session|dpop]+
#OIDCInfoHook [iat|access_token|access_token_expires|id_token|id_token_hint|userinfo|refresh_token|exp|timeout|remote_user|session]+

# Specify metrics that you wish to collect and keep in shared memory for retrieval.
# Supported metrics classes are:
Expand Down
26 changes: 12 additions & 14 deletions src/cfg/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,19 +325,11 @@ OIDC_CFG_MEMBER_FUNC_GET(filter_claims_expr, oidc_apr_expr_t *)
*/
const char *oidc_cmd_info_hook_data_set(cmd_parms *cmd, void *m, const char *arg) {
oidc_cfg_t *cfg = (oidc_cfg_t *)ap_get_module_config(cmd->server->module_config, &auth_openidc_module);
static const char *options[] = {OIDC_HOOK_INFO_TIMESTAMP,
OIDC_HOOK_INFO_ACCES_TOKEN,
OIDC_HOOK_INFO_ACCES_TOKEN_EXP,
OIDC_HOOK_INFO_ID_TOKEN_HINT,
OIDC_HOOK_INFO_ID_TOKEN,
OIDC_HOOK_INFO_USER_INFO,
OIDC_HOOK_INFO_REFRESH_TOKEN,
OIDC_HOOK_INFO_SESSION_EXP,
OIDC_HOOK_INFO_SESSION_TIMEOUT,
OIDC_HOOK_INFO_SESSION_REMOTE_USER,
OIDC_HOOK_INFO_SESSION,
OIDC_HOOK_INFO_DPOP,
NULL};
static const char *options[] = {
OIDC_HOOK_INFO_TIMESTAMP, OIDC_HOOK_INFO_ACCES_TOKEN, OIDC_HOOK_INFO_ACCES_TOKEN_EXP,
OIDC_HOOK_INFO_ID_TOKEN_HINT, OIDC_HOOK_INFO_ID_TOKEN, OIDC_HOOK_INFO_USER_INFO,
OIDC_HOOK_INFO_REFRESH_TOKEN, OIDC_HOOK_INFO_SESSION_EXP, OIDC_HOOK_INFO_SESSION_TIMEOUT,
OIDC_HOOK_INFO_SESSION_REMOTE_USER, OIDC_HOOK_INFO_SESSION, NULL};
const char *rv = oidc_cfg_parse_is_valid_option(cmd->pool, arg, options);
if (rv != NULL)
return OIDC_CONFIG_DIR_RV(cmd, rv);
Expand Down Expand Up @@ -381,7 +373,10 @@ const char *oidc_cmd_trace_parent_set(cmd_parms *cmd, void *struct_ptr, const ch
}

#define OIDC_DEFAULT_TRACE_PARENT OIDC_TRACE_PARENT_OFF
OIDC_CFG_MEMBER_FUNC_TYPE_GET(trace_parent, oidc_trace_parent_t, OIDC_TRACE_PARENT_OFF)
OIDC_CFG_MEMBER_FUNC_TYPE_GET(trace_parent, oidc_trace_parent_t, OIDC_DEFAULT_TRACE_PARENT)

#define OIDC_DEFAULT_DPOP_API_ENABLED 0
OIDC_CFG_MEMBER_FUNC_TYPE_GET(dpop_api_enabled, int, OIDC_DEFAULT_DPOP_API_ENABLED)

const char *oidc_cmd_claim_prefix_set(cmd_parms *cmd, void *struct_ptr, const char *args) {
oidc_cfg_t *cfg = (oidc_cfg_t *)ap_get_module_config(cmd->server->module_config, &auth_openidc_module);
Expand Down Expand Up @@ -676,6 +671,7 @@ void *oidc_cfg_server_create(apr_pool_t *pool, server_rec *svr) {
c->metrics_hook_data = NULL;
c->metrics_path = NULL;
c->trace_parent = OIDC_CONFIG_POS_INT_UNSET;
c->dpop_api_enabled = OIDC_CONFIG_POS_INT_UNSET;

c->black_listed_claims = NULL;
c->white_listed_claims = NULL;
Expand Down Expand Up @@ -816,6 +812,8 @@ void *oidc_cfg_server_merge(apr_pool_t *pool, void *BASE, void *ADD) {
c->metrics_hook_data = add->metrics_hook_data != NULL ? add->metrics_hook_data : base->metrics_hook_data;
c->metrics_path = add->metrics_path != NULL ? add->metrics_path : base->metrics_path;
c->trace_parent = add->trace_parent != OIDC_CONFIG_POS_INT_UNSET ? add->trace_parent : base->trace_parent;
c->dpop_api_enabled =
add->dpop_api_enabled != OIDC_CONFIG_POS_INT_UNSET ? add->dpop_api_enabled : base->dpop_api_enabled;

c->black_listed_claims =
add->black_listed_claims != NULL ? add->black_listed_claims : base->black_listed_claims;
Expand Down
2 changes: 1 addition & 1 deletion src/cfg/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ typedef enum {
#define OIDC_HOOK_INFO_SESSION_TIMEOUT "timeout"
#define OIDC_HOOK_INFO_SESSION_REMOTE_USER "remote_user"
#define OIDC_HOOK_INFO_REFRESH_TOKEN "refresh_token"
#define OIDC_HOOK_INFO_DPOP "dpop"

#define OIDC_HTML_ERROR_TEMPLATE_DEPRECATED "deprecated"

Expand Down Expand Up @@ -237,6 +236,7 @@ OIDC_CFG_MEMBER_FUNCS_DECL(redirect_urls_allowed, apr_hash_t *)
OIDC_CFG_MEMBER_FUNCS_DECL(ca_bundle_path, const char *)
OIDC_CFG_MEMBER_FUNCS_DECL(logout_x_frame_options, const char *)
OIDC_CFG_MEMBER_FUNCS_DECL(x_forwarded_headers, oidc_hdr_x_forwarded_t)
OIDC_CFG_MEMBER_FUNCS_DECL(dpop_api_enabled, int)

// 2 args
OIDC_CFG_MEMBER_FUNCS_DECL(post_preserve_templates, const char *, const char *)
Expand Down
1 change: 1 addition & 0 deletions src/cfg/cfg_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ struct oidc_cfg_t {

apr_hash_t *metrics_hook_data;
char *metrics_path;
int dpop_api_enabled;

/* directory that holds the provider & client metadata files */
char *metadata_dir;
Expand Down
2 changes: 1 addition & 1 deletion src/cfg/cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ const command_rec oidc_cfg_cmds[] = {
pkce,
"The RFC 7636 PCKE mode used; must be one of \"plain\" or \"S256\""),
OIDC_CFG_CMD_PROVIDER(
AP_INIT_TAKE1,
AP_INIT_TAKE12,
OIDCDPoPMode,
dpop_mode,
"The RFC 9449 DPoP mode used; must be one of \"off\", \"optional\" or \"required\""),
Expand Down
27 changes: 25 additions & 2 deletions src/cfg/provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,31 @@ static const char *oidc_cfg_provider_parse_dop_method(apr_pool_t *pool, const ch
}

#define OIDC_DEFAULT_DPOP_MODE OIDC_DPOP_MODE_OFF
OIDC_PROVIDER_MEMBER_FUNCS_STR_INT(dpop_mode, oidc_cfg_provider_parse_dop_method, oidc_dpop_mode_t,
OIDC_DEFAULT_DPOP_MODE)

OIDC_PROVIDER_MEMBER_GET_INT_DEF(dpop_mode, oidc_dpop_mode_t, OIDC_DEFAULT_DPOP_MODE)

void oidc_cfg_provider_dpop_mode_int_set(oidc_provider_t *provider, oidc_dpop_mode_t arg) {
provider->dpop_mode = arg;
}

const char *oidc_cfg_provider_dpop_mode_set(apr_pool_t *pool, oidc_provider_t *provider, const char *arg) {
const char *rv = NULL;
oidc_dpop_mode_t v;
rv = oidc_cfg_provider_parse_dop_method(pool, arg, &v);
if (rv == NULL)
provider->dpop_mode = v;
else
provider->dpop_mode = OIDC_DEFAULT_DPOP_MODE;
return rv;
}

const char *oidc_cmd_provider_dpop_mode_set(cmd_parms *cmd, void *ptr, const char *arg1, const char *arg2) {
oidc_cfg_t *cfg = (oidc_cfg_t *)ap_get_module_config(cmd->server->module_config, &auth_openidc_module);
const char *rv = oidc_cfg_provider_dpop_mode_set(cmd->pool, cfg->provider, arg1);
if ((rv == NULL) && (arg2))
rv = oidc_cfg_parse_boolean(cmd->pool, arg2, &cfg->dpop_api_enabled);
return OIDC_CONFIG_DIR_RV(cmd, rv);
}

OIDC_PROVIDER_MEMBER_FUNCS_STR(issuer, NULL)
OIDC_PROVIDER_MEMBER_FUNCS_URL(authorization_endpoint_url)
Expand Down
3 changes: 2 additions & 1 deletion src/cfg/provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,12 @@ OIDC_CFG_PROVIDER_MEMBER_FUNCS_INT_DECL(session_max_duration)
OIDC_CFG_PROVIDER_MEMBER_FUNCS_INT_DECL(response_require_iss)
// ints with 2 args
OIDC_CFG_PROVIDER_MEMBER_FUNCS_INT_DECL(userinfo_refresh_interval, const char *)
OIDC_CFG_PROVIDER_MEMBER_FUNCS_TYPE_DECL(dpop_mode, oidc_dpop_mode_t, const char *)
void OIDC_CFG_MEMBER_FUNC_NAME(dpop_mode, cfg_provider, int_set)(oidc_provider_t *provider, oidc_dpop_mode_t arg);

// for metadata.c
OIDC_CFG_PROVIDER_MEMBER_FUNCS_INT_INT_DECL(userinfo_token_method, oidc_userinfo_token_method_t)
OIDC_CFG_PROVIDER_MEMBER_FUNCS_INT_INT_DECL(auth_request_method, oidc_auth_request_method_t)
OIDC_CFG_PROVIDER_MEMBER_FUNCS_INT_INT_DECL(dpop_mode, oidc_dpop_mode_t)

// types
OIDC_CFG_PROVIDER_MEMBER_FUNCS_TYPE_DECL(pkce, const oidc_proto_pkce_t *)
Expand Down
4 changes: 2 additions & 2 deletions src/handle/dpop.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ int oidc_dpop_request(request_rec *r, oidc_cfg_t *c) {
remote_ip = r->connection->remote_ip;
#endif

if (apr_hash_get(oidc_cfg_info_hook_data_get(c), OIDC_HOOK_INFO_DPOP, APR_HASH_KEY_STRING) == NULL) {
oidc_error(r, "DPoP hook called but \"dpop\" is not enabled in %s", OIDCInfoHook);
if (!oidc_cfg_dpop_api_enabled_get(c)) {
oidc_error(r, "DPoP hook called but the DPoP API is not enabled in %s", OIDCDPoPMode);
goto end;
}

Expand Down

0 comments on commit 28557c1

Please sign in to comment.