Skip to content

Commit

Permalink
Merge pull request #476 from bcingram/validate_issuer
Browse files Browse the repository at this point in the history
Added OIDCValidateIssuer configuration setting to allow for Azure AD multi-tenant
  • Loading branch information
zandbelt committed May 13, 2020
2 parents 9f1881f + 067e716 commit 3d2d697
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 4 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ reporting bugs, providing fixes, suggesting useful features or other:
Paolo Battino
absynth76 <https://github.com/absynth76>
Aaron Jones <https://github.com/wwaaron>
Bryan Ingram <https://github/bcingram>
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
05/11/2020
- added OIDCValidateIssuer to allow for disabling of issuer matching. helps to support multi-tenant applications.

05/02/2020
- when stripping cookies, add a space between cookies in the resulting header (required by RFC 6265)
- move oidc_parse_config inside MODULE_MAGIC_NUMBER_MAJOR to make sure the module compiles with Apache 2.0
Expand Down
5 changes: 5 additions & 0 deletions auth_openidc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@
# NB: this can be overridden on a per-OP basis in the .conf file using the key: ssl_validate_server
#OIDCSSLValidateServer [On|Off]

# Require configured issuer to match the issuer returned in id_token.
# (Disable to support Azure AD multi-tenant applications.)
# When not defined, the default value is "On".
#OIDCValidateIssuer [On|Off]

# The refresh interval in seconds for the claims obtained from the userinfo endpoint
# When not defined the default is 0, i.e. the claims are retrieved only at session creation time.
# NB: this can be overridden on a per-OP basis in the .conf file using the key: userinfo_refresh_interval
Expand Down
28 changes: 28 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@

/* validate SSL server certificates by default */
#define OIDC_DEFAULT_SSL_VALIDATE_SERVER 1
/* validate issuer by default */
#define OIDC_DEFAULT_VALIDATE_ISSUER 1
/* default scope requested from the OP */
#define OIDC_DEFAULT_SCOPE "openid"
/* default claim delimiter for multi-valued claims passed in a HTTP header */
Expand Down Expand Up @@ -197,6 +199,7 @@
#define OIDCUserInfoTokenMethod "OIDCUserInfoTokenMethod"
#define OIDCTokenBindingPolicy "OIDCTokenBindingPolicy"
#define OIDCSSLValidateServer "OIDCSSLValidateServer"
#define OIDCValidateIssuer "OIDCValidateIssuer"
#define OIDCClientName "OIDCClientName"
#define OIDCClientContact "OIDCClientContact"
#define OIDCScope "OIDCScope"
Expand Down Expand Up @@ -468,6 +471,20 @@ static const char *oidc_set_ssl_validate_slot(cmd_parms *cmd, void *struct_ptr,
return OIDC_CONFIG_DIR_RV(cmd, rv);
}

/*
* set validate issuer slot
*/
static const char *oidc_set_validate_issuer_slot(cmd_parms *cmd, void *struct_ptr,
const char *arg) {
oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
cmd->server->module_config, &auth_openidc_module);
int b = 0;
const char *rv = oidc_parse_boolean(cmd->pool, arg, &b);
if (rv == NULL)
rv = ap_set_flag_slot(cmd, cfg, b);
return OIDC_CONFIG_DIR_RV(cmd, rv);
}

/*
* return the right token endpoint authentication method validation function, based on whether private keys are set
*/
Expand Down Expand Up @@ -1144,6 +1161,7 @@ void oidc_cfg_provider_init(oidc_provider_t *provider) {
provider->backchannel_logout_supported = OIDC_CONFIG_POS_INT_UNSET;

provider->ssl_validate_server = OIDC_DEFAULT_SSL_VALIDATE_SERVER;
provider->validate_issuer = OIDC_DEFAULT_VALIDATE_ISSUER;
provider->client_name = OIDC_DEFAULT_CLIENT_NAME;
provider->client_contact = NULL;
provider->registration_token = NULL;
Expand Down Expand Up @@ -1387,6 +1405,11 @@ void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) {
!= OIDC_DEFAULT_SSL_VALIDATE_SERVER ?
add->provider.ssl_validate_server :
base->provider.ssl_validate_server;
c->provider.validate_issuer =
add->provider.validate_issuer
!= OIDC_DEFAULT_VALIDATE_ISSUER ?
add->provider.validate_issuer :
base->provider.validate_issuer;
c->provider.client_name =
apr_strnatcmp(add->provider.client_name, OIDC_DEFAULT_CLIENT_NAME)
!= 0 ?
Expand Down Expand Up @@ -2691,6 +2714,11 @@ const command_rec oidc_config_cmds[] = {
(void*)APR_OFFSETOF(oidc_cfg, provider.ssl_validate_server),
RSRC_CONF,
"Require validation of the OpenID Connect OP SSL server certificate for successful authentication (On or Off)"),
AP_INIT_TAKE1(OIDCValidateIssuer,
oidc_set_validate_issuer_slot,
(void*)APR_OFFSETOF(oidc_cfg, provider.validate_issuer),
RSRC_CONF,
"Require validation of token issuer for successful authentication (On or Off)"),
AP_INIT_TAKE1(OIDCClientName,
oidc_set_string_slot,
(void *) APR_OFFSETOF(oidc_cfg, provider.client_name),
Expand Down
4 changes: 4 additions & 0 deletions src/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
#define OIDC_METADATA_POST_LOGOUT_REDIRECT_URIS "post_logout_redirect_uris"
#define OIDC_METADATA_IDTOKEN_BINDING_CNF "id_token_token_binding_cnf"
#define OIDC_METADATA_SSL_VALIDATE_SERVER "ssl_validate_server"
#define OIDC_METADATA_VALIDATE_ISSUER "validate_issuer"
#define OIDC_METADATA_SCOPE "scope"
#define OIDC_METADATA_JWKS_REFRESH_INTERVAL "jwks_refresh_interval"
#define OIDC_METADATA_IDTOKEN_IAT_SLACK "idtoken_iat_slack"
Expand Down Expand Up @@ -1235,6 +1236,9 @@ apr_byte_t oidc_metadata_conf_parse(request_rec *r, oidc_cfg *cfg,
oidc_metadata_parse_boolean(r, j_conf, OIDC_METADATA_SSL_VALIDATE_SERVER,
&provider->ssl_validate_server, cfg->provider.ssl_validate_server);

oidc_metadata_parse_boolean(r, j_conf, OIDC_METADATA_VALIDATE_ISSUER,
&provider->validate_issuer, cfg->provider.validate_issuer);

/* find out what scopes we should be requesting from this provider */
// TODO: use the provider "scopes_supported" to mix-and-match with what we've configured for the client
// TODO: check that "openid" is always included in the configured scopes, right?
Expand Down
5 changes: 2 additions & 3 deletions src/mod_auth_openidc.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ static apr_byte_t oidc_unsolicited_proto_state(request_rec *r, oidc_cfg *c,
}

/* validate the state JWT, validating optional exp + iat */
if (oidc_proto_validate_jwt(r, jwt, provider->issuer, FALSE, FALSE,
if (oidc_proto_validate_jwt(r, jwt, provider->validate_issuer ? provider->issuer : NULL, FALSE, FALSE,
provider->idtoken_iat_slack,
OIDC_TOKEN_BINDING_POLICY_DISABLED) == FALSE) {
oidc_jwt_destroy(jwt);
Expand Down Expand Up @@ -2916,8 +2916,7 @@ static int oidc_handle_logout_backchannel(request_rec *r, oidc_cfg *cfg) {

// oidc_proto_validate_idtoken would try and require a token binding cnf
// if the policy is set to "required", so don't use that here

if (oidc_proto_validate_jwt(r, jwt, provider->issuer, FALSE, FALSE,
if (oidc_proto_validate_jwt(r, jwt, provider->validate_issuer ? provider->issuer : NULL, FALSE, FALSE,
provider->idtoken_iat_slack,
OIDC_TOKEN_BINDING_POLICY_DISABLED) == FALSE)
goto out;
Expand Down
1 change: 1 addition & 0 deletions src/mod_auth_openidc.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ typedef struct oidc_provider_t {

// the next ones function as global default settings too
int ssl_validate_server;
int validate_issuer;
char *client_name;
char *client_contact;
char *registration_token;
Expand Down
2 changes: 1 addition & 1 deletion src/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ static apr_byte_t oidc_proto_validate_idtoken(request_rec *r,
}

/* validate the ID Token JWT, requiring iss match, and valid exp + iat */
if (oidc_proto_validate_jwt(r, jwt, provider->issuer, TRUE, TRUE,
if (oidc_proto_validate_jwt(r, jwt, provider->validate_issuer ? provider->issuer : NULL, TRUE, TRUE,
provider->idtoken_iat_slack,
provider->token_binding_policy) == FALSE)
return FALSE;
Expand Down

0 comments on commit 3d2d697

Please sign in to comment.