/* * see if we have provider metadata and check its validity * if not, use OpenID Connect Discovery to get it, check it and store it */ static apr_byte_t oidc_metadata_provider_get(request_rec *r, oidc_cfg *cfg, const char *issuer, json_t **j_provider, apr_byte_t allow_discovery) { /* holds the response data/string/JSON from the OP */ const char *response = NULL; /* get the full file path to the provider metadata for this issuer */ const char *provider_path = oidc_metadata_provider_file_path(r, issuer); /* see if we have valid metadata already, if so, return it */ if (oidc_metadata_file_read_json(r, provider_path, j_provider) == TRUE) { /* return the validation result */ return oidc_metadata_provider_is_valid(r, *j_provider, issuer); } if (!allow_discovery) { oidc_warn(r, "no metadata found for the requested issuer (%s), and Discovery is not allowed", issuer); return FALSE; } // TODO: how to do validity/expiry checks on provider metadata /* assemble the URL to the .well-known OpenID metadata */ const char *url = apr_psprintf(r->pool, "%s", ((strstr(issuer, "http://") == issuer) || (strstr(issuer, "https://") == issuer)) ? issuer : apr_psprintf(r->pool, "https://%s", issuer)); url = apr_psprintf(r->pool, "%s%s.well-known/openid-configuration", url, url[strlen(url) - 1] != '/' ? "/" : ""); /* get the metadata for the issuer using OpenID Connect Discovery and validate it */ if (oidc_metadata_provider_retrieve(r, cfg, issuer, url, j_provider, &response) == FALSE) return FALSE; /* since it is valid, write the obtained provider metadata file */ if (oidc_metadata_file_write(r, provider_path, response) == FALSE) return FALSE; return TRUE; }
/* * see if we have config metadata */ static apr_byte_t oidc_metadata_conf_get(request_rec *r, oidc_cfg *cfg, const char *issuer, json_t **j_conf) { /* get the full file path to the conf metadata for this issuer */ const char *conf_path = oidc_metadata_conf_path(r, issuer); /* the .conf file is optional */ apr_finfo_t fi; if (apr_stat(&fi, conf_path, APR_FINFO_MTIME, r->pool) != APR_SUCCESS) return TRUE; /* see if we have valid metadata already, if so, return it */ if (oidc_metadata_file_read_json(r, conf_path, j_conf) == TRUE) { /* return the validation result */ return oidc_metadata_conf_is_valid(r, *j_conf, issuer); } return FALSE; }
/* * see if we have client metadata and check its validity * if not, use OpenID Connect Client Registration to get it, check it and store it */ static apr_byte_t oidc_metadata_client_get(request_rec *r, oidc_cfg *cfg, const char *issuer, oidc_provider_t *provider, json_t **j_client) { /* get the full file path to the client metadata for this issuer */ const char *client_path = oidc_metadata_client_file_path(r, issuer); /* see if we have valid metadata already, if so, return it */ if (oidc_metadata_file_read_json(r, client_path, j_client) == TRUE) { /* if the client metadata is (still) valid, return it */ if (oidc_metadata_client_is_valid(r, *j_client, issuer) == TRUE) return TRUE; } /* at this point we have no valid client metadata, see if there's a registration endpoint for this provider */ if (provider->registration_endpoint_url == NULL) { oidc_error(r, "no (valid) client metadata exists for provider (%s) and provider JSON object did not contain a (valid) \"registration_endpoint\" string", issuer); return FALSE; } /* try and get client metadata by registering the client at the registration endpoint */ const char *response = NULL; if (oidc_metadata_client_register(r, cfg, provider, j_client, &response) == FALSE) return FALSE; /* check to see if it is valid metadata */ if (oidc_metadata_client_is_valid(r, *j_client, issuer) == FALSE) return FALSE; /* since it is valid, write the obtained client metadata file */ if (oidc_metadata_file_write(r, client_path, response) == FALSE) return FALSE; return TRUE; }