1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /***************************************************************************
21  * Copyright (C) 2017-2021 ZmartZone Holding BV
22  * Copyright (C) 2013-2017 Ping Identity Corporation
23  * All rights reserved.
24  *
25  * DISCLAIMER OF WARRANTIES:
26  *
27  * THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
28  * ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
29  * WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
30  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  NOR ARE THERE ANY
31  * WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
32  * USAGE.  FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
33  * YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
34  * WILL BE UNINTERRUPTED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
35  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
37  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * @Author: Hans Zandbelt - hans.zandbelt@zmartzone.eu
42  */
43 
44 #ifndef MOD_AUTH_OPENIDC_H_
45 #define MOD_AUTH_OPENIDC_H_
46 
47 #include <stdint.h>
48 #include <httpd.h>
49 #include <http_core.h>
50 #include <http_config.h>
51 #include <mod_auth.h>
52 
53 #include "jose.h"
54 #include "cache/cache.h"
55 #include "parse.h"
56 #include <apr_uuid.h>
57 
58 #ifdef APLOG_USE_MODULE
59 APLOG_USE_MODULE(auth_openidc);
60 #endif
61 
62 #ifndef OIDC_DEBUG
63 #define OIDC_DEBUG APLOG_DEBUG
64 #endif
65 
66 #define oidc_log(r, level, fmt, ...) ap_log_rerror(APLOG_MARK, level, 0, r,"%s: %s", __FUNCTION__, apr_psprintf(r->pool, fmt, ##__VA_ARGS__))
67 #define oidc_slog(s, level, fmt, ...) ap_log_error(APLOG_MARK, level, 0, s, "%s: %s", __FUNCTION__, apr_psprintf(s->process->pool, fmt, ##__VA_ARGS__))
68 //#define oidc_log(r, level, fmt, ...) fprintf(stderr, "# %s: %s\n", __FUNCTION__, apr_psprintf(r->pool, fmt, ##__VA_ARGS__))
69 //#define oidc_slog(s, level, fmt, ...) fprintf(stderr, "## %s: %s\n", __FUNCTION__, apr_psprintf(s->process->pool, fmt, ##__VA_ARGS__))
70 
71 #define oidc_debug(r, fmt, ...) oidc_log(r, OIDC_DEBUG, fmt, ##__VA_ARGS__)
72 #define oidc_warn(r, fmt, ...) oidc_log(r, APLOG_WARNING, fmt, ##__VA_ARGS__)
73 #define oidc_error(r, fmt, ...) oidc_log(r, APLOG_ERR, fmt, ##__VA_ARGS__)
74 
75 #define oidc_sdebug(s, fmt, ...) oidc_slog(s, OIDC_DEBUG, fmt, ##__VA_ARGS__)
76 #define oidc_swarn(s, fmt, ...) oidc_slog(s, APLOG_WARNING, fmt, ##__VA_ARGS__)
77 #define oidc_serror(s, fmt, ...) oidc_slog(s, APLOG_ERR, fmt, ##__VA_ARGS__)
78 
79 #ifndef NAMEVER
80 #define NAMEVERSION "mod_auth_openidc-0.0.0"
81 #else
82 #define STRINGIFY(x) #x
83 #define TOSTRING(x) STRINGIFY(x)
84 #define NAMEVERSION TOSTRING(NAMEVER)
85 #endif
86 
87 /* keys for storing info in the request state */
88 #define OIDC_REQUEST_STATE_KEY_IDTOKEN "i"
89 #define OIDC_REQUEST_STATE_KEY_CLAIMS  "c"
90 
91 /* parameter name of the callback URL in the discovery response */
92 #define OIDC_DISC_CB_PARAM "oidc_callback"
93 /* parameter name of the OP provider selection in the discovery response */
94 #define OIDC_DISC_OP_PARAM "iss"
95 /* parameter name of the user URL in the discovery response */
96 #define OIDC_DISC_USER_PARAM "disc_user"
97 /* parameter name of the original URL in the discovery response */
98 #define OIDC_DISC_RT_PARAM "target_link_uri"
99 /* parameter name of the original method in the discovery response */
100 #define OIDC_DISC_RM_PARAM "method"
101 /* parameter name of login hint in the discovery response */
102 #define OIDC_DISC_LH_PARAM "login_hint"
103 /* parameter name of parameters that need to be passed in the authentication request */
104 #define OIDC_DISC_AR_PARAM "auth_request_params"
105 /* parameter name of the scopes required in the discovery response */
106 #define OIDC_DISC_SC_PARAM "scopes"
107 
108 /* value that indicates to use server-side cache based session tracking */
109 #define OIDC_SESSION_TYPE_SERVER_CACHE 0
110 /* value that indicates to use client cookie based session tracking */
111 #define OIDC_SESSION_TYPE_CLIENT_COOKIE 1
112 
113 /* nonce bytes length */
114 #define OIDC_PROTO_NONCE_LENGTH 32
115 
116 /* code verifier length */
117 #define OIDC_PROTO_CODE_VERIFIER_LENGTH 32
118 
119 /* pass id_token as individual claims in headers (default) */
120 #define OIDC_PASS_IDTOKEN_AS_CLAIMS     1
121 /* pass id_token payload as JSON object in header */
122 #define OIDC_PASS_IDTOKEN_AS_PAYLOAD    2
123 /* pass id_token in compact serialized format in header */
124 #define OIDC_PASS_IDTOKEN_AS_SERIALIZED 4
125 
126 /* pass userinfo as individual claims in headers (default) */
127 #define OIDC_PASS_USERINFO_AS_CLAIMS      1
128 /* pass userinfo payload as JSON object in header */
129 #define OIDC_PASS_USERINFO_AS_JSON_OBJECT 2
130 /* pass userinfo as a JWT in header (when returned as a JWT) */
131 #define OIDC_PASS_USERINFO_AS_JWT         4
132 
133 /* logout on refresh error before expiry */
134 #define OIDC_LOGOUT_ON_ERROR_REFRESH 1
135 
136 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_DEFAULT 0
137 /* accept bearer token in header (default) */
138 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_HEADER  1
139 /* accept bearer token as a post parameter */
140 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_POST    2
141 /* accept bearer token as a query parameter */
142 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_QUERY   4
143 /* accept bearer token as a cookie parameter (PingAccess) */
144 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_COOKIE  8
145 /* accept bearer token as basic auth password (non-oauth clients) */
146 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_BASIC   16
147 
148 /* the hash key of the cookie name value in the list of options */
149 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_OPTION_COOKIE_NAME "cookie-name"
150 
151 /* introspection method options */
152 #define OIDC_INTROSPECTION_METHOD_GET  "GET"
153 #define OIDC_INTROSPECTION_METHOD_POST "POST"
154 
155 /* HTTP methods to send authentication requests */
156 #define OIDC_AUTH_REQUEST_METHOD_GET  0
157 #define OIDC_AUTH_REQUEST_METHOD_POST 1
158 
159 /* default prefix for information passed in HTTP headers */
160 #define OIDC_DEFAULT_HEADER_PREFIX "OIDC_"
161 
162 /* the (global) key for the mod_auth_openidc related state that is stored in the request userdata context */
163 #define OIDC_USERDATA_KEY "mod_auth_openidc_state"
164 #define OIDC_USERDATA_POST_PARAMS_KEY "oidc_userdata_post_params"
165 
166 /* input filter hook name */
167 #define OIDC_UTIL_HTTP_SENDSTRING "OIDC_UTIL_HTTP_SENDSTRING"
168 
169 /* the name of the keyword that follows the Require primitive to indicate claims-based authorization */
170 #define OIDC_REQUIRE_CLAIM_NAME "claim"
171 #ifdef USE_LIBJQ
172 /* the name of the keyword that follows the Require primitive to indicate claims-expression-based authorization */
173 #define OIDC_REQUIRE_CLAIMS_EXPR_NAME "claims_expr"
174 #endif
175 
176 /* defines for how long provider metadata will be cached */
177 #define OIDC_CACHE_PROVIDER_METADATA_EXPIRY_DEFAULT 86400
178 
179 /* define the parameter value for the "logout" request that indicates a GET-style logout call from the OP */
180 #define OIDC_GET_STYLE_LOGOUT_PARAM_VALUE "get"
181 #define OIDC_IMG_STYLE_LOGOUT_PARAM_VALUE "img"
182 #define OIDC_BACKCHANNEL_STYLE_LOGOUT_PARAM_VALUE "backchannel"
183 
184 /* define the name of the cookie/parameter for CSRF protection */
185 #define OIDC_CSRF_NAME "x_csrf"
186 
187 /* http methods */
188 #define OIDC_METHOD_GET       "get"
189 #define OIDC_METHOD_FORM_POST "form_post"
190 
191 /* the maximum size of data that we accept in a single POST value: 1MB */
192 #define OIDC_MAX_POST_DATA_LEN 1024 * 1024
193 
194 #define OIDC_UNAUTH_AUTHENTICATE 1
195 #define OIDC_UNAUTH_PASS         2
196 #define OIDC_UNAUTH_RETURN401    3
197 #define OIDC_UNAUTH_RETURN410    4
198 #define OIDC_UNAUTH_RETURN407    5
199 
200 #define OIDC_UNAUTZ_RETURN403    1
201 #define OIDC_UNAUTZ_RETURN401    2
202 #define OIDC_UNAUTZ_AUTHENTICATE 3
203 
204 #define OIDC_REQUEST_URI_CACHE_DURATION 30
205 
206 #define OIDC_USER_INFO_TOKEN_METHOD_HEADER 0
207 #define OIDC_USER_INFO_TOKEN_METHOD_POST   1
208 
209 #define OIDC_COOKIE_EXT_SAME_SITE_LAX    "SameSite=Lax"
210 #define OIDC_COOKIE_EXT_SAME_SITE_STRICT "SameSite=Strict"
211 #define OIDC_COOKIE_EXT_SAME_SITE_NONE(r) \
212 		oidc_util_request_is_secure(r) ? "SameSite=None" : NULL
213 
214 #define OIDC_COOKIE_SAMESITE_STRICT(c, r) \
215 		c->cookie_same_site ? OIDC_COOKIE_EXT_SAME_SITE_STRICT : OIDC_COOKIE_EXT_SAME_SITE_NONE(r)
216 #define OIDC_COOKIE_SAMESITE_LAX(c, r) \
217 		c->cookie_same_site ? OIDC_COOKIE_EXT_SAME_SITE_LAX : OIDC_COOKIE_EXT_SAME_SITE_NONE(r)
218 
219 /* https://tools.ietf.org/html/draft-ietf-tokbind-ttrp-01 */
220 #define OIDC_TB_CFG_PROVIDED_ENV_VAR     "Sec-Provided-Token-Binding-ID"
221 /* https://www.ietf.org/id/draft-ietf-oauth-mtls-12 */
222 #define OIDC_TB_CFG_FINGERPRINT_ENV_VAR  "TB_SSL_CLIENT_CERT_FINGERPRINT"
223 
224 #define OIDC_TOKEN_BINDING_POLICY_DISABLED  0
225 #define OIDC_TOKEN_BINDING_POLICY_OPTIONAL  1
226 #define OIDC_TOKEN_BINDING_POLICY_REQUIRED  2
227 #define OIDC_TOKEN_BINDING_POLICY_ENFORCED  3
228 
229 #define OIDC_STATE_INPUT_HEADERS_USER_AGENT 1
230 #define OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR 2
231 
232 typedef apr_byte_t (*oidc_proto_pkce_state)(request_rec *r, char **state);
233 typedef apr_byte_t (*oidc_proto_pkce_challenge)(request_rec *r, const char *state, char **code_challenge);
234 typedef apr_byte_t (*oidc_proto_pkce_verifier)(request_rec *r, const char *state, char **code_verifier);
235 
236 typedef struct oidc_proto_pkce_t {
237 	const char *method;
238 	oidc_proto_pkce_state     state;
239 	oidc_proto_pkce_verifier  verifier;
240 	oidc_proto_pkce_challenge challenge;
241 } oidc_proto_pkce_t;
242 
243 extern oidc_proto_pkce_t oidc_pkce_plain;
244 extern oidc_proto_pkce_t oidc_pkce_s256;
245 extern oidc_proto_pkce_t oidc_pkce_referred_tb;
246 
247 typedef struct oidc_jwks_uri_t {
248 	const char *url;
249 	int refresh_interval;
250 	int ssl_validate_server;
251 } oidc_jwks_uri_t;
252 
253 typedef struct oidc_provider_t {
254 	char *metadata_url;
255 	char *issuer;
256 	char *authorization_endpoint_url;
257 	char *token_endpoint_url;
258 	char *token_endpoint_auth;
259 	char *token_endpoint_params;
260 	char *userinfo_endpoint_url;
261 	char *revocation_endpoint_url;
262 	char *registration_endpoint_url;
263 	char *check_session_iframe;
264 	char *end_session_endpoint;
265 	char *jwks_uri;
266 	char *client_id;
267 	char *client_secret;
268 	char *token_endpoint_tls_client_key;
269 	char *token_endpoint_tls_client_cert;
270 	int backchannel_logout_supported;
271 
272 	// the next ones function as global default settings too
273 	int ssl_validate_server;
274 	int validate_issuer;
275 	char *client_name;
276 	char *client_contact;
277 	char *registration_token;
278 	char *registration_endpoint_json;
279 	char *scope;
280 	char *response_type;
281 	char *response_mode;
282 	int jwks_refresh_interval;
283 	int idtoken_iat_slack;
284 	char *auth_request_params;
285 	int session_max_duration;
286 	oidc_proto_pkce_t *pkce;
287 	int userinfo_refresh_interval;
288 
289 	apr_array_header_t *client_signing_keys;
290 	apr_array_header_t *client_encryption_keys;
291 
292 	char *client_jwks_uri;
293 	char *id_token_signed_response_alg;
294 	char *id_token_encrypted_response_alg;
295 	char *id_token_encrypted_response_enc;
296 	char *userinfo_signed_response_alg;
297 	char *userinfo_encrypted_response_alg;
298 	char *userinfo_encrypted_response_enc;
299 	int userinfo_token_method;
300 	char *request_object;
301 	int auth_request_method;
302 	int token_binding_policy;
303 
304 	int issuer_specific_redirect_uri;
305 } oidc_provider_t ;
306 
307 typedef struct oidc_remote_user_claim_t {
308 	const char *claim_name;
309 	const char *reg_exp;
310 	const char *replace;
311 } oidc_remote_user_claim_t;
312 
313 typedef struct oidc_oauth_t {
314 	int ssl_validate_server;
315 	char *client_id;
316 	char *client_secret;
317 	char *metadata_url;
318 	char *introspection_endpoint_tls_client_key;
319 	char *introspection_endpoint_tls_client_cert;
320 	char *introspection_endpoint_url;
321 	char *introspection_endpoint_method;
322 	char *introspection_endpoint_params;
323 	char *introspection_endpoint_auth;
324 	char *introspection_client_auth_bearer_token;
325 	char *introspection_token_param_name;
326 	char *introspection_token_expiry_claim_name;
327 	char *introspection_token_expiry_claim_format;
328 	int introspection_token_expiry_claim_required;
329 	oidc_remote_user_claim_t remote_user_claim;
330 	apr_hash_t *verify_shared_keys;
331 	char *verify_jwks_uri;
332 	apr_hash_t *verify_public_keys;
333 	int access_token_binding_policy;
334 } oidc_oauth_t;
335 
336 typedef struct oidc_cfg {
337 	/* indicates whether this is a derived config, merged from a base one */
338 	unsigned int merged;
339 
340 	/* HTML to display error messages+description */
341 	char *error_template;
342 
343 	/* the redirect URI as configured with the OpenID Connect OP's that we talk to */
344 	char *redirect_uri;
345 	/* (optional) default URL for 3rd-party initiated SSO */
346 	char *default_sso_url;
347 	/* (optional) default URL to go to after logout */
348 	char *default_slo_url;
349 
350 	/* public keys in JWK format, used by parters for encrypting JWTs sent to us */
351 	apr_array_header_t *public_keys;
352 	/* private keys in JWK format used for decrypting encrypted JWTs sent to us */
353 	apr_array_header_t *private_keys;
354 
355 	/* a pointer to the (single) provider that we connect to */
356 	/* NB: if metadata_dir is set, these settings will function as defaults for the metadata read from there) */
357 	oidc_provider_t provider;
358 	/* a pointer to the oauth server settings */
359 	oidc_oauth_t oauth;
360 
361 	/* directory that holds the provider & client metadata files */
362 	char *metadata_dir;
363 	/* type of session management/storage */
364 	int session_type;
365 	/* session cookie or persistent cookie */
366 	int persistent_session_cookie;
367 	/* session cookie chunk size */
368 	int session_cookie_chunk_size;
369 
370 	/* pointer to cache functions */
371 	oidc_cache_t *cache;
372 	void *cache_cfg;
373 	/* cache_type = file: directory that holds the cache files (if not set, we'll try and use an OS defined one like "/tmp" */
374 	char *cache_file_dir;
375 	/* cache_type = file: clean interval */
376 	int cache_file_clean_interval;
377 #ifdef USE_MEMCACHE
378 	/* cache_type= memcache: list of memcache host/port servers to use */
379 	char *cache_memcache_servers;
380 #endif
381 	/* cache_type = shm: size of the shared memory segment (cq. max number of cached entries) */
382 	int cache_shm_size_max;
383 	/* cache_type = shm: maximum size in bytes of a cache entry */
384 	int cache_shm_entry_size_max;
385 #ifdef USE_LIBHIREDIS
386 	/* cache_type= redis: Redis host/port server to use */
387 	char *cache_redis_server;
388 	char *cache_redis_password;
389 	int cache_redis_database;
390 #endif
391 	int cache_encrypt;
392 
393 	int http_timeout_long;
394 	int http_timeout_short;
395 	int state_timeout;
396 	int max_number_of_state_cookies;
397 	int delete_oldest_state_cookies;
398 	int session_inactivity_timeout;
399 	int session_cache_fallback_to_cookie;
400 
401 	char *cookie_domain;
402 	char *claim_delimiter;
403 	char *claim_prefix;
404 	oidc_remote_user_claim_t remote_user_claim;
405 	int pass_idtoken_as;
406 	int pass_userinfo_as;
407 	int cookie_http_only;
408 	int cookie_same_site;
409 
410 	char *outgoing_proxy;
411 
412 	char *crypto_passphrase;
413 
414 	int provider_metadata_refresh_interval;
415 
416 	apr_hash_t *info_hook_data;
417 	apr_hash_t *black_listed_claims;
418 	apr_hash_t *white_listed_claims;
419 
420 	apr_byte_t state_input_headers;
421 
422 	apr_hash_t *redirect_urls_allowed;
423 
424 	char *ca_bundle_path;
425 } oidc_cfg;
426 
427 int oidc_check_user_id(request_rec *r);
428 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
429 authz_status oidc_authz_checker_claim(request_rec *r, const char *require_args, const void *parsed_require_args);
430 #ifdef USE_LIBJQ
431 authz_status oidc_authz_checker_claims_expr(request_rec *r, const char *require_args, const void *parsed_require_args);
432 #endif
433 #else
434 int oidc_auth_checker(request_rec *r);
435 #endif
436 void oidc_request_state_set(request_rec *r, const char *key, const char *value);
437 const char*oidc_request_state_get(request_rec *r, const char *key);
438 int oidc_handle_jwks(request_rec *r, oidc_cfg *c);
439 int oidc_handle_remove_at_cache(request_rec *r, oidc_cfg *c);
440 apr_byte_t oidc_post_preserve_javascript(request_rec *r, const char *location, char **javascript, char **javascript_method);
441 void oidc_scrub_headers(request_rec *r);
442 void oidc_strip_cookies(request_rec *r);
443 int oidc_content_handler(request_rec *r);
444 apr_byte_t oidc_get_remote_user(request_rec *r, const char *claim_name, const char *replace, const char *reg_exp,
445                                 json_t *json, char **request_user);
446 
447 #define OIDC_REDIRECT_URI_REQUEST_INFO             "info"
448 #define OIDC_REDIRECT_URI_REQUEST_LOGOUT           "logout"
449 #define OIDC_REDIRECT_URI_REQUEST_JWKS             "jwks"
450 #define OIDC_REDIRECT_URI_REQUEST_SESSION          "session"
451 #define OIDC_REDIRECT_URI_REQUEST_REFRESH          "refresh"
452 #define OIDC_REDIRECT_URI_REQUEST_REMOVE_AT_CACHE  "remove_at_cache"
453 #define OIDC_REDIRECT_URI_REQUEST_REQUEST_URI      "request_uri"
454 
455 // oidc_oauth
456 int oidc_oauth_check_userid(request_rec *r, oidc_cfg *c, const char *access_token);
457 apr_byte_t oidc_oauth_get_bearer_token(request_rec *r, const char **access_token);
458 
459 // oidc_proto.c
460 #define OIDC_PROTO_ISS                   "iss"
461 #define OIDC_PROTO_CODE                  "code"
462 #define OIDC_PROTO_CLIENT_ID             "client_id"
463 #define OIDC_PROTO_CLIENT_SECRET         "client_secret"
464 #define OIDC_PROTO_CLIENT_ASSERTION      "client_assertion"
465 #define OIDC_PROTO_CLIENT_ASSERTION_TYPE "client_assertion_type"
466 #define OIDC_PROTO_ACCESS_TOKEN          "access_token"
467 #define OIDC_PROTO_ID_TOKEN              "id_token"
468 #define OIDC_PROTO_STATE                 "state"
469 #define OIDC_PROTO_GRANT_TYPE            "grant_type"
470 #define OIDC_PROTO_REDIRECT_URI          "redirect_uri"
471 #define OIDC_PROTO_CODE_VERIFIER         "code_verifier"
472 #define OIDC_PROTO_CODE_CHALLENGE        "code_challenge"
473 #define OIDC_PROTO_CODE_CHALLENGE_METHOD "code_challenge_method"
474 #define OIDC_PROTO_SCOPE                 "scope"
475 #define OIDC_PROTO_REFRESH_TOKEN         "refresh_token"
476 #define OIDC_PROTO_TOKEN_TYPE            "token_type"
477 #define OIDC_PROTO_EXPIRES_IN            "expires_in"
478 #define OIDC_PROTO_RESPONSE_TYPE         "response_type"
479 #define OIDC_PROTO_RESPONSE_MODE         "response_mode"
480 #define OIDC_PROTO_NONCE                 "nonce"
481 #define OIDC_PROTO_PROMPT                "prompt"
482 #define OIDC_PROTO_LOGIN_HINT            "login_hint"
483 #define OIDC_PROTO_ID_TOKEN_HINT         "id_token_hint"
484 #define OIDC_PROTO_REQUEST_URI           "request_uri"
485 #define OIDC_PROTO_REQUEST_OBJECT        "request"
486 #define OIDC_PROTO_SESSION_STATE         "session_state"
487 #define OIDC_PROTO_ACTIVE                "active"
488 #define OIDC_PROTO_LOGOUT_TOKEN          "logout_token"
489 
490 #define OIDC_PROTO_RESPONSE_TYPE_CODE               "code"
491 #define OIDC_PROTO_RESPONSE_TYPE_IDTOKEN            "id_token"
492 #define OIDC_PROTO_RESPONSE_TYPE_IDTOKEN_TOKEN      "id_token token"
493 #define OIDC_PROTO_RESPONSE_TYPE_CODE_IDTOKEN       "code id_token"
494 #define OIDC_PROTO_RESPONSE_TYPE_CODE_TOKEN         "code token"
495 #define OIDC_PROTO_RESPONSE_TYPE_CODE_IDTOKEN_TOKEN "code id_token token"
496 #define OIDC_PROTO_RESPONSE_TYPE_TOKEN              "token"
497 
498 #define OIDC_PROTO_RESPONSE_MODE_QUERY     "query"
499 #define OIDC_PROTO_RESPONSE_MODE_FRAGMENT  "fragment"
500 #define OIDC_PROTO_RESPONSE_MODE_FORM_POST "form_post"
501 
502 #define OIDC_PROTO_SCOPE_OPENID           "openid"
503 #define OIDC_PROTO_PROMPT_NONE            "none"
504 #define OIDC_PROTO_ERROR                  "error"
505 #define OIDC_PROTO_ERROR_DESCRIPTION      "error_description"
506 #define OIDC_PROTO_REALM                  "realm"
507 
508 #define OIDC_PROTO_ERR_INVALID_TOKEN          "invalid_token"
509 #define OIDC_PROTO_ERR_INVALID_REQUEST        "invalid_request"
510 
511 #define OIDC_PROTO_GRANT_TYPE_AUTHZ_CODE    "authorization_code"
512 #define OIDC_PROTO_GRANT_TYPE_REFRESH_TOKEN "refresh_token"
513 
514 #define OIDC_PROTO_CLIENT_ASSERTION_TYPE_JWT_BEARER "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
515 
516 #define OIDC_PROTO_CLIENT_SECRET_BASIC "client_secret_basic"
517 #define OIDC_PROTO_CLIENT_SECRET_POST  "client_secret_post"
518 #define OIDC_PROTO_CLIENT_SECRET_JWT   "client_secret_jwt"
519 #define OIDC_PROTO_PRIVATE_KEY_JWT     "private_key_jwt"
520 #define OIDC_PROTO_BEARER_ACCESS_TOKEN "bearer_access_token"
521 #define OIDC_PROTO_ENDPOINT_AUTH_NONE  "none"
522 
523 #define OIDC_PROTO_BEARER  "Bearer"
524 #define OIDC_PROTO_BASIC   "Basic"
525 
526 #define OIDC_CLAIM_ISS             "iss"
527 #define OIDC_CLAIM_AUD             "aud"
528 #define OIDC_CLAIM_AZP             "azp"
529 #define OIDC_CLAIM_SUB             "sub"
530 #define OIDC_CLAIM_JTI             "jti"
531 #define OIDC_CLAIM_EXP             "exp"
532 #define OIDC_CLAIM_IAT             "iat"
533 #define OIDC_CLAIM_NONCE           "nonce"
534 #define OIDC_CLAIM_AT_HASH         "at_hash"
535 #define OIDC_CLAIM_C_HASH          "c_hash"
536 #define OIDC_CLAIM_RFP             "rfp"
537 #define OIDC_CLAIM_TARGET_LINK_URI "target_link_uri"
538 #define OIDC_CLAIM_CNF             "cnf"
539 #define OIDC_CLAIM_CNF_TBH         "tbh"
540 #define OIDC_CLAIM_CNF_X5T_S256    "x5t#S256"
541 #define OIDC_CLAIM_SID             "sid"
542 #define OIDC_CLAIM_EVENTS          "events"
543 
544 #define OIDC_JWK_X5T       "x5t"
545 #define OIDC_JWK_KEYS      "keys"
546 #define OIDC_JWK_USE       "use"
547 #define OIDC_JWK_SIG       "sig"
548 #define OIDC_JWK_ENC       "enc"
549 
550 #define OIDC_HOOK_INFO_FORMAT_JSON         "json"
551 #define OIDC_HOOK_INFO_FORMAT_HTML         "html"
552 #define OIDC_HOOK_INFO_TIMESTAMP           "iat"
553 #define OIDC_HOOK_INFO_ACCES_TOKEN         "access_token"
554 #define OIDC_HOOK_INFO_ACCES_TOKEN_EXP     "access_token_expires"
555 #define OIDC_HOOK_INFO_ID_TOKEN            "id_token"
556 #define OIDC_HOOK_INFO_USER_INFO           "userinfo"
557 #define OIDC_HOOK_INFO_SESSION             "session"
558 #define OIDC_HOOK_INFO_SESSION_STATE       "state"
559 #define OIDC_HOOK_INFO_SESSION_UUID        "uuid"
560 #define OIDC_HOOK_INFO_SESSION_EXP         "exp"
561 #define OIDC_HOOK_INFO_SESSION_TIMEOUT     "timeout"
562 #define OIDC_HOOK_INFO_SESSION_REMOTE_USER "remote_user"
563 #define OIDC_HOOK_INFO_REFRESH_TOKEN       "refresh_token"
564 
565 #define OIDC_CONTENT_TYPE_JSON          "application/json"
566 #define OIDC_CONTENT_TYPE_JWT           "application/jwt"
567 #define OIDC_CONTENT_TYPE_FORM_ENCODED  "application/x-www-form-urlencoded"
568 #define OIDC_CONTENT_TYPE_IMAGE_PNG     "image/png"
569 #define OIDC_CONTENT_TYPE_TEXT_HTML     "text/html"
570 #define OIDC_CONTENT_TYPE_APP_XHTML_XML "application/xhtml+xml"
571 #define OIDC_CONTENT_TYPE_ANY           "*/*"
572 
573 #define OIDC_STR_SPACE         " "
574 #define OIDC_STR_EQUAL         "="
575 #define OIDC_STR_AMP           "&"
576 #define OIDC_STR_QUERY         "?"
577 #define OIDC_STR_COLON         ":"
578 #define OIDC_STR_SEMI_COLON    ";"
579 #define OIDC_STR_FORWARD_SLASH "/"
580 #define OIDC_STR_AT            "@"
581 #define OIDC_STR_COMMA         ","
582 #define OIDC_STR_HASH          "#"
583 
584 #define OIDC_CHAR_EQUAL         '='
585 #define OIDC_CHAR_COLON         ':'
586 #define OIDC_CHAR_TILDE         '~'
587 #define OIDC_CHAR_SPACE         ' '
588 #define OIDC_CHAR_COMMA         ','
589 #define OIDC_CHAR_QUERY         '?'
590 #define OIDC_CHAR_DOT           '.'
591 #define OIDC_CHAR_AT            '@'
592 #define OIDC_CHAR_FORWARD_SLASH '/'
593 #define OIDC_CHAR_PIPE          '|'
594 #define OIDC_CHAR_AMP           '&'
595 #define OIDC_CHAR_SEMI_COLON    ';'
596 
597 #define OIDC_APP_INFO_REFRESH_TOKEN     "refresh_token"
598 #define OIDC_APP_INFO_ACCESS_TOKEN      "access_token"
599 #define OIDC_APP_INFO_ACCESS_TOKEN_EXP  "access_token_expires"
600 #define OIDC_APP_INFO_ID_TOKEN          "id_token"
601 #define OIDC_APP_INFO_ID_TOKEN_PAYLOAD  "id_token_payload"
602 #define OIDC_APP_INFO_USERINFO_JSON     "userinfo_json"
603 #define OIDC_APP_INFO_USERINFO_JWT      "userinfo_jwt"
604 
605 typedef json_t oidc_proto_state_t;
606 
607 oidc_proto_state_t *oidc_proto_state_new();
608 void oidc_proto_state_destroy(oidc_proto_state_t *proto_state);
609 oidc_proto_state_t *oidc_proto_state_from_cookie(request_rec *r, oidc_cfg *c, const char *cookieValue);
610 char *oidc_proto_state_to_cookie(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state);
611 char *oidc_proto_state_to_string(request_rec *r, oidc_proto_state_t *proto_state);
612 const char *oidc_proto_state_get_issuer(oidc_proto_state_t *proto_state);
613 const char *oidc_proto_state_get_nonce(oidc_proto_state_t *proto_state);
614 apr_time_t oidc_proto_state_get_timestamp(oidc_proto_state_t *proto_state);
615 const char *oidc_proto_state_get_state(oidc_proto_state_t *proto_state);
616 const char *oidc_proto_state_get_original_url(oidc_proto_state_t *proto_state);
617 const char *oidc_proto_state_get_prompt(oidc_proto_state_t *proto_state);
618 const char *oidc_proto_state_get_response_type(oidc_proto_state_t *proto_state);
619 const char *oidc_proto_state_get_response_mode(oidc_proto_state_t *proto_state);
620 const char *oidc_proto_state_get_original_url(oidc_proto_state_t *proto_state);
621 const char *oidc_proto_state_get_original_method(oidc_proto_state_t *proto_state);
622 const char *oidc_proto_state_get_pkce_state(oidc_proto_state_t *proto_state);
623 void oidc_proto_state_set_state(oidc_proto_state_t *proto_state, const char *state);
624 void oidc_proto_state_set_issuer(oidc_proto_state_t *proto_state, const char *issuer);
625 void oidc_proto_state_set_original_url(oidc_proto_state_t *proto_state, const char *original_url);
626 void oidc_proto_state_set_original_method(oidc_proto_state_t *proto_state, const char *original_method);
627 void oidc_proto_state_set_response_mode(oidc_proto_state_t *proto_state, const char *response_mode);
628 void oidc_proto_state_set_response_type(oidc_proto_state_t *proto_state, const char *response_type);
629 void oidc_proto_state_set_nonce(oidc_proto_state_t *proto_state, const char *nonce);
630 void oidc_proto_state_set_prompt(oidc_proto_state_t *proto_state, const char *prompt);
631 void oidc_proto_state_set_pkce_state(oidc_proto_state_t *proto_state, const char *pkce_state);
632 void oidc_proto_state_set_timestamp_now(oidc_proto_state_t *proto_state);
633 
634 apr_byte_t oidc_proto_token_endpoint_auth(request_rec *r, oidc_cfg *cfg, const char *token_endpoint_auth, const char *client_id, const char *client_secret, const apr_array_header_t *client_signing_keys, const char *audience, apr_table_t *params, const char *bearer_access_token, char **basic_auth_str, char **bearer_auth_str);
635 
636 char *oidc_proto_peek_jwt_header(request_rec *r, const char *jwt, char **alg);
637 int oidc_proto_authorization_request(request_rec *r, struct oidc_provider_t *provider, const char *login_hint, const char *redirect_uri, const char *state, oidc_proto_state_t *proto_state, const char *id_token_hint, const char *code_challenge, const char *auth_request_params, const char *path_scope);
638 apr_byte_t oidc_proto_is_post_authorization_response(request_rec *r, oidc_cfg *cfg);
639 apr_byte_t oidc_proto_is_redirect_authorization_response(request_rec *r, oidc_cfg *cfg);
640 apr_byte_t oidc_proto_refresh_request(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *rtoken, char **id_token, char **access_token, char **token_type, int *expires_in, char **refresh_token);
641 apr_byte_t oidc_proto_resolve_userinfo(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *id_token_sub, const char *access_token, char **response, char **userinfo_jwt);
642 apr_byte_t oidc_proto_account_based_discovery(request_rec *r, oidc_cfg *cfg, const char *acct, char **issuer);
643 apr_byte_t oidc_proto_url_based_discovery(request_rec *r, oidc_cfg *cfg, const char *url, char **issuer);
644 apr_byte_t oidc_proto_parse_idtoken(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *id_token, const char *nonce, oidc_jwt_t **jwt, apr_byte_t is_code_flow);
645 int oidc_proto_javascript_implicit(request_rec *r, oidc_cfg *c);
646 apr_array_header_t *oidc_proto_supported_flows(apr_pool_t *pool);
647 apr_byte_t oidc_proto_flow_is_supported(apr_pool_t *pool, const char *flow);
648 apr_byte_t oidc_proto_validate_authorization_response(request_rec *r, const char *response_type, const char *requested_response_mode, char **code, char **id_token, char **access_token, char **token_type, const char *used_response_mode);
649 apr_byte_t oidc_proto_jwt_verify(request_rec *r, oidc_cfg *cfg, oidc_jwt_t *jwt, const oidc_jwks_uri_t *jwks_uri, apr_hash_t *symmetric_keys, const char *alg);
650 apr_byte_t oidc_proto_validate_jwt(request_rec *r, oidc_jwt_t *jwt, const char *iss, apr_byte_t exp_is_mandatory, apr_byte_t iat_is_mandatory, int iat_slack, int token_binding_policy);
651 apr_byte_t oidc_proto_generate_nonce(request_rec *r, char **nonce, int len);
652 apr_byte_t oidc_proto_validate_aud_and_azp(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, oidc_jwt_payload_t *id_token_payload);
653 
654 apr_byte_t oidc_proto_authorization_response_code_idtoken_token(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state, oidc_provider_t *provider, apr_table_t *params, const char *response_mode, oidc_jwt_t **jwt);
655 apr_byte_t oidc_proto_authorization_response_code_idtoken(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state, oidc_provider_t *provider, apr_table_t *params, const char *response_mode, oidc_jwt_t **jwt);
656 apr_byte_t oidc_proto_handle_authorization_response_code_token(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state, oidc_provider_t *provider, apr_table_t *params, const char *response_mode, oidc_jwt_t **jwt);
657 apr_byte_t oidc_proto_handle_authorization_response_code(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state, oidc_provider_t *provider, apr_table_t *params, const char *response_mode, oidc_jwt_t **jwt);
658 apr_byte_t oidc_proto_handle_authorization_response_idtoken_token(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state, oidc_provider_t *provider, apr_table_t *params, const char *response_mode, oidc_jwt_t **jwt);
659 apr_byte_t oidc_proto_handle_authorization_response_idtoken(request_rec *r, oidc_cfg *c, oidc_proto_state_t *proto_state, oidc_provider_t *provider, apr_table_t *params, const char *response_mode, oidc_jwt_t **jwt);
660 
661 // non-static for test.c
662 apr_byte_t oidc_proto_validate_access_token(request_rec *r, oidc_provider_t *provider, oidc_jwt_t *jwt, const char *response_type, const char *access_token);
663 apr_byte_t oidc_proto_validate_code(request_rec *r, oidc_provider_t *provider, oidc_jwt_t *jwt, const char *response_type, const char *code);
664 apr_byte_t oidc_proto_validate_nonce(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *nonce, oidc_jwt_t *jwt);
665 
666 // oidc_authz.c
667 typedef apr_byte_t (*oidc_authz_match_claim_fn_type)(request_rec *, const char * const, const json_t * const);
668 apr_byte_t oidc_authz_match_claim(request_rec *r, const char * const attr_spec, const json_t * const claims);
669 #ifdef USE_LIBJQ
670 apr_byte_t oidc_authz_match_claims_expr(request_rec *r, const char * const attr_spec, const json_t * const claims);
671 #endif
672 #if MODULE_MAGIC_NUMBER_MAJOR < 20100714
673 int oidc_authz_worker22(request_rec *r, const json_t *const claims, const require_line *const reqs, int nelts);
674 #else
675 authz_status oidc_authz_worker24(request_rec *r, const json_t * const claims, const char *require_args, const void *parsed_require_args, oidc_authz_match_claim_fn_type match_claim_fn);
676 #endif
677 int oidc_oauth_return_www_authenticate(request_rec *r, const char *error, const char *error_description);
678 
679 // oidc_config.c
680 
681 #define OIDCPrivateKeyFiles                  "OIDCPrivateKeyFiles"
682 #define OIDCRedirectURI                      "OIDCRedirectURI"
683 #define OIDCDefaultURL                       "OIDCDefaultURL"
684 #define OIDCCookieDomain                     "OIDCCookieDomain"
685 #define OIDCClaimPrefix                      "OIDCClaimPrefix"
686 #define OIDCRemoteUserClaim                  "OIDCRemoteUserClaim"
687 #define OIDCOAuthRemoteUserClaim             "OIDCOAuthRemoteUserClaim"
688 #define OIDCSessionType                      "OIDCSessionType"
689 #define OIDCMemCacheServers                  "OIDCMemCacheServers"
690 #define OIDCCacheShmMax                      "OIDCCacheShmMax"
691 #define OIDCCacheShmEntrySizeMax             "OIDCCacheShmEntrySizeMax"
692 #define OIDCRedisCacheServer                 "OIDCRedisCacheServer"
693 #define OIDCCookiePath                       "OIDCCookiePath"
694 #define OIDCInfoHook                         "OIDCInfoHook"
695 #define OIDCWhiteListedClaims                "OIDCWhiteListedClaims"
696 
697 void *oidc_create_server_config(apr_pool_t *pool, server_rec *svr);
698 void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD);
699 void *oidc_create_dir_config(apr_pool_t *pool, char *path);
700 void *oidc_merge_dir_config(apr_pool_t *pool, void *BASE, void *ADD);
701 void oidc_register_hooks(apr_pool_t *pool);
702 char *oidc_cfg_dir_discover_url(request_rec *r);
703 char *oidc_cfg_dir_cookie(request_rec *r);
704 char *oidc_cfg_dir_cookie_path(request_rec *r);
705 char *oidc_cfg_dir_authn_header(request_rec *r);
706 apr_byte_t oidc_cfg_dir_pass_info_in_headers(request_rec *r);
707 apr_byte_t oidc_cfg_dir_pass_info_in_envvars(request_rec *r);
708 apr_byte_t oidc_cfg_dir_pass_info_base64url(request_rec *r);
709 apr_byte_t oidc_cfg_dir_pass_refresh_token(request_rec *r);
710 apr_byte_t oidc_cfg_dir_accept_token_in(request_rec *r);
711 char *oidc_cfg_dir_accept_token_in_option(request_rec *r, const char *key);
712 int oidc_cfg_token_introspection_interval(request_rec *r);
713 int oidc_cfg_dir_preserve_post(request_rec *r);
714 apr_array_header_t *oidc_dir_cfg_pass_cookies(request_rec *r);
715 apr_array_header_t *oidc_dir_cfg_strip_cookies(request_rec *r);
716 int oidc_dir_cfg_unauth_action(request_rec *r);
717 apr_byte_t oidc_dir_cfg_unauth_expr_is_set(request_rec *r);
718 int oidc_dir_cfg_unautz_action(request_rec *r);
719 char *oidc_dir_cfg_path_auth_request_params(request_rec *r);
720 char *oidc_dir_cfg_path_scope(request_rec *r);
721 oidc_valid_function_t oidc_cfg_get_valid_endpoint_auth_function(oidc_cfg *cfg);
722 int oidc_cfg_cache_encrypt(request_rec *r);
723 int oidc_cfg_session_cache_fallback_to_cookie(request_rec *r);
724 const char *oidc_parse_pkce_type(apr_pool_t *pool, const char *arg, oidc_proto_pkce_t **type);
725 const char *oidc_cfg_claim_prefix(request_rec *r);
726 int oidc_cfg_max_number_of_state_cookies(oidc_cfg *cfg);
727 int oidc_cfg_dir_refresh_access_token_before_expiry(request_rec *r);
728 int oidc_cfg_dir_logout_on_error_refresh(request_rec *r);
729 char *oidc_cfg_dir_state_cookie_prefix(request_rec *r);
730 int oidc_cfg_delete_oldest_state_cookies(oidc_cfg *cfg);
731 void oidc_cfg_provider_init(oidc_provider_t *provider);
732 
733 // oidc_util.c
734 int oidc_strnenvcmp(const char *a, const char *b, int len);
735 int oidc_base64url_encode(request_rec *r, char **dst, const char *src, int src_len, int remove_padding);
736 int oidc_base64url_decode(apr_pool_t *pool, char **dst, const char *src);
737 const char *oidc_get_current_url_host(request_rec *r);
738 char *oidc_get_current_url(request_rec *r);
739 const char *oidc_get_redirect_uri(request_rec *r, oidc_cfg *c);
740 const char *oidc_get_redirect_uri_iss(request_rec *r, oidc_cfg *c, oidc_provider_t *provider);
741 char *oidc_url_encode(const request_rec *r, const char *str, const char *charsToEncode);
742 char *oidc_normalize_header_name(const request_rec *r, const char *str);
743 apr_byte_t oidc_util_request_is_secure(request_rec *r);
744 void oidc_util_set_cookie(request_rec *r, const char *cookieName, const char *cookieValue, apr_time_t expires, const char *ext);
745 char *oidc_util_get_cookie(request_rec *r, const char *cookieName);
746 apr_byte_t oidc_util_http_get(request_rec *r, const char *url, const apr_table_t *params, const char *basic_auth, const char *bearer_token, int ssl_validate_server, char **response, int timeout, const char *outgoing_proxy, apr_array_header_t *pass_cookies, const char *ssl_cert, const char *ssl_key);
747 apr_byte_t oidc_util_http_post_form(request_rec *r, const char *url, const apr_table_t *params, const char *basic_auth, const char *bearer_token, int ssl_validate_server, char **response, int timeout, const char *outgoing_proxy, apr_array_header_t *pass_cookies, const char *ssl_cert, const char *ssl_key);
748 apr_byte_t oidc_util_http_post_json(request_rec *r, const char *url, json_t *data, const char *basic_auth, const char *bearer_token, int ssl_validate_server, char **response, int timeout, const char *outgoing_proxy, apr_array_header_t *pass_cookies, const char *ssl_cert, const char *ssl_key);
749 apr_byte_t oidc_util_request_matches_url(request_rec *r, const char *url);
750 apr_byte_t oidc_util_request_has_parameter(request_rec *r, const char* param);
751 apr_byte_t oidc_util_get_request_parameter(request_rec *r, char *name, char **value);
752 char *oidc_util_encode_json_object(request_rec *r, json_t *json, size_t flags);
753 apr_byte_t oidc_util_decode_json_object(request_rec *r, const char *str, json_t **json);
754 apr_byte_t oidc_util_decode_json_and_check_error(request_rec *r, const char *str, json_t **json);
755 int oidc_util_http_send(request_rec *r, const char *data, size_t data_len, const char *content_type, int success_rvalue);
756 int oidc_util_html_send(request_rec *r, const char *title, const char *html_head, const char *on_load, const char *html_body, int status_code);
757 char *oidc_util_escape_string(const request_rec *r, const char *str);
758 char *oidc_util_unescape_string(const request_rec *r, const char *str);
759 apr_byte_t oidc_util_read_form_encoded_params(request_rec *r, apr_table_t *table, char *data);
760 apr_byte_t oidc_util_read_post_params(request_rec *r, apr_table_t *table, apr_byte_t propagate, const char *strip_param_name);
761 apr_byte_t oidc_util_file_read(request_rec *r, const char *path, apr_pool_t *pool, char **result);
762 apr_byte_t oidc_util_file_write(request_rec *r, const char *path, const char *data);
763 apr_byte_t oidc_util_issuer_match(const char *a, const char *b);
764 int oidc_util_html_send_error(request_rec *r, const char *html_template, const char *error, const char *description, int status_code);
765 apr_byte_t oidc_util_json_array_has_value(request_rec *r, json_t *haystack, const char *needle);
766 void oidc_util_set_app_info(request_rec *r, const char *s_key, const char *s_value, const char *claim_prefix, apr_byte_t as_header, apr_byte_t as_env_var, apr_byte_t base64url);
767 void oidc_util_set_app_infos(request_rec *r, const json_t *j_attrs, const char *claim_prefix, const char *claim_delimiter, apr_byte_t as_header, apr_byte_t as_env_var, apr_byte_t base64url);
768 apr_hash_t *oidc_util_spaced_string_to_hashtable(apr_pool_t *pool, const char *str);
769 apr_byte_t oidc_util_spaced_string_equals(apr_pool_t *pool, const char *a, const char *b);
770 apr_byte_t oidc_util_spaced_string_contains(apr_pool_t *pool, const char *str, const char *match);
771 apr_byte_t oidc_json_object_get_string(apr_pool_t *pool, json_t *json, const char *name, char **value, const char *default_value);
772 apr_byte_t oidc_json_object_get_int(apr_pool_t *pool, json_t *json, const char *name, int *value, const int default_value);
773 apr_byte_t oidc_json_object_get_bool(apr_pool_t *pool, json_t *json, const char *name, int *value, const int default_value);
774 char *oidc_util_html_escape(apr_pool_t *pool, const char *input);
775 void oidc_util_table_add_query_encoded_params(apr_pool_t *pool, apr_table_t *table, const char *params);
776 apr_hash_t * oidc_util_merge_key_sets(apr_pool_t *pool, apr_hash_t *k1, const apr_array_header_t *k2);
777 apr_hash_t * oidc_util_merge_key_sets_hash(apr_pool_t *pool, apr_hash_t *k1, apr_hash_t *k2);
778 apr_byte_t oidc_util_regexp_substitute(apr_pool_t *pool, const char *input, const char *regexp, const char *replace, char **output, char **error_str);
779 apr_byte_t oidc_util_regexp_first_match(apr_pool_t *pool, const char *input, const char *regexp, char **output, char **error_str);
780 apr_byte_t oidc_util_json_merge(request_rec *r, json_t *src, json_t *dst);
781 int oidc_util_cookie_domain_valid(const char *hostname, char *cookie_domain);
782 apr_byte_t oidc_util_hash_string_and_base64url_encode(request_rec *r, const char *openssl_hash_algo, const char *input, char **output);
783 apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, json_t *payload, char **compact_encoded_jwt);
784 apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret, const char *compact_encoded_jwt, json_t **result);
785 char *oidc_util_get_chunked_cookie(request_rec *r, const char *cookieName, int cookie_chunk_size);
786 void oidc_util_set_chunked_cookie(request_rec *r, const char *cookieName, const char *cookieValue, apr_time_t expires, int chunkSize, const char *ext);
787 apr_byte_t oidc_util_create_symmetric_key(request_rec *r, const char *client_secret, unsigned int r_key_len, const char *hash_algo, apr_byte_t set_kid, oidc_jwk_t **jwk);
788 apr_hash_t * oidc_util_merge_symmetric_key(apr_pool_t *pool, const apr_array_header_t *keys, oidc_jwk_t *jwk);
789 const char *oidc_util_get_provided_token_binding_id(const request_rec *r);
790 char *oidc_util_http_query_encoded_url(request_rec *r, const char *url, const apr_table_t *params);
791 char *oidc_util_get_full_path(apr_pool_t *pool, const char *abs_or_rel_filename);
792 apr_byte_t oidc_enabled(request_rec *r);
793 char *oidc_util_http_form_encoded_data(request_rec *r, const apr_table_t *params);
794 
795 /* HTTP header constants */
796 #define OIDC_HTTP_HDR_COOKIE							"Cookie"
797 #define OIDC_HTTP_HDR_SET_COOKIE						"Set-Cookie"
798 #define OIDC_HTTP_HDR_USER_AGENT						"User-Agent"
799 #define OIDC_HTTP_HDR_X_FORWARDED_FOR					"X-Forwarded-For"
800 #define OIDC_HTTP_HDR_CONTENT_TYPE						"Content-Type"
801 #define OIDC_HTTP_HDR_CONTENT_LENGTH					"Content-Length"
802 #define OIDC_HTTP_HDR_X_REQUESTED_WITH					"X-Requested-With"
803 #define OIDC_HTTP_HDR_ACCEPT							"Accept"
804 #define OIDC_HTTP_HDR_AUTHORIZATION						"Authorization"
805 #define OIDC_HTTP_HDR_X_FORWARDED_PROTO					"X-Forwarded-Proto"
806 #define OIDC_HTTP_HDR_X_FORWARDED_PORT					"X-Forwarded-Port"
807 #define OIDC_HTTP_HDR_X_FORWARDED_HOST					"X-Forwarded-Host"
808 #define OIDC_HTTP_HDR_HOST								"Host"
809 #define OIDC_HTTP_HDR_LOCATION							"Location"
810 #define OIDC_HTTP_HDR_CACHE_CONTROL						"Cache-Control"
811 #define OIDC_HTTP_HDR_PRAGMA							"Pragma"
812 #define OIDC_HTTP_HDR_P3P								"P3P"
813 #define OIDC_HTTP_HDR_EXPIRES							"Expires"
814 #define OIDC_HTTP_HDR_X_FRAME_OPTIONS					"X-Frame-Options"
815 #define OIDC_HTTP_HDR_WWW_AUTHENTICATE					"WWW-Authenticate"
816 #define OIDC_HTTP_HDR_INCLUDE_REFERRED_TOKEN_BINDING_ID	"Include-Referred-Token-Binding-ID"
817 
818 #define OIDC_HTTP_HDR_VAL_XML_HTTP_REQUEST				"XMLHttpRequest"
819 
820 void oidc_util_hdr_in_set(const request_rec *r, const char *name, const char *value);
821 const char *oidc_util_hdr_in_cookie_get(const request_rec *r);
822 void oidc_util_hdr_in_cookie_set(const request_rec *r, const char *value);
823 const char *oidc_util_hdr_in_user_agent_get(const request_rec *r);
824 const char *oidc_util_hdr_in_x_forwarded_for_get(const request_rec *r);
825 const char *oidc_util_hdr_in_content_type_get(const request_rec *r);
826 const char *oidc_util_hdr_in_content_length_get(const request_rec *r);
827 const char *oidc_util_hdr_in_x_requested_with_get(const request_rec *r);
828 const char *oidc_util_hdr_in_accept_get(const request_rec *r);
829 const char *oidc_util_hdr_in_authorization_get(const request_rec *r);
830 const char *oidc_util_hdr_in_x_forwarded_proto_get(const request_rec *r);
831 const char *oidc_util_hdr_in_x_forwarded_port_get(const request_rec *r);
832 const char *oidc_util_hdr_in_x_forwarded_host_get(const request_rec *r);
833 const char *oidc_util_hdr_in_host_get(const request_rec *r);
834 void oidc_util_hdr_out_location_set(const request_rec *r, const char *value);
835 const char *oidc_util_hdr_out_location_get(const request_rec *r);
836 void oidc_util_hdr_err_out_add(const request_rec *r, const char *name, const char *value);
837 apr_byte_t oidc_util_hdr_in_accept_contains(const request_rec *r, const char *needle);
838 apr_byte_t oidc_util_json_validate_cnf(request_rec *r, json_t *jwt, int token_binding_policy);
839 
840 // oidc_metadata.c
841 apr_byte_t oidc_metadata_provider_retrieve(request_rec *r, oidc_cfg *cfg, const char *issuer, const char *url, json_t **j_metadata, char **response);
842 apr_byte_t oidc_metadata_provider_parse(request_rec *r, oidc_cfg *cfg, json_t *j_provider, oidc_provider_t *provider);
843 apr_byte_t oidc_metadata_provider_is_valid(request_rec *r, oidc_cfg *cfg, json_t *j_provider, const char *issuer);
844 apr_byte_t oidc_metadata_list(request_rec *r, oidc_cfg *cfg, apr_array_header_t **arr);
845 apr_byte_t oidc_metadata_get(request_rec *r, oidc_cfg *cfg, const char *selected, oidc_provider_t **provider, apr_byte_t allow_discovery);
846 apr_byte_t oidc_metadata_jwks_get(request_rec *r, oidc_cfg *cfg, const oidc_jwks_uri_t *jwks_uri, json_t **j_jwks, apr_byte_t *refresh);
847 apr_byte_t oidc_oauth_metadata_provider_parse(request_rec *r, oidc_cfg *c, json_t *j_provider);
848 
849 // oidc_session.c
850 typedef struct {
851 	char uuid[APR_UUID_FORMATTED_LENGTH + 1]; /* unique id */
852     const char *remote_user;                  /* user who owns this particular session */
853     json_t *state;                            /* the state for this session, encoded in a JSON object */
854     apr_time_t expiry;                        /* if > 0, the time of expiry of this session */
855     const char *sid;
856 } oidc_session_t;
857 
858 apr_byte_t oidc_session_load(request_rec *r, oidc_session_t **z);
859 apr_byte_t oidc_session_get(request_rec *r, oidc_session_t *z, const char *key, const char **value);
860 apr_byte_t oidc_session_set(request_rec *r, oidc_session_t *z, const char *key, const char *value);
861 apr_byte_t oidc_session_save(request_rec *r, oidc_session_t *z, apr_byte_t first_time);
862 apr_byte_t oidc_session_kill(request_rec *r, oidc_session_t *z);
863 apr_byte_t oidc_session_free(request_rec *r, oidc_session_t *z);
864 apr_byte_t oidc_session_extract(request_rec *r, oidc_session_t *z);
865 apr_byte_t oidc_session_load_cache_by_uuid(request_rec *r, oidc_cfg *c, const char *uuid, oidc_session_t *z);
866 
867 void oidc_session_set_userinfo_jwt(request_rec *r, oidc_session_t *z, const char *userinfo_jwt);
868 const char * oidc_session_get_userinfo_jwt(request_rec *r, oidc_session_t *z);
869 void oidc_session_set_userinfo_claims(request_rec *r, oidc_session_t *z, const char *claims);
870 const char * oidc_session_get_userinfo_claims(request_rec *r, oidc_session_t *z);
871 json_t *oidc_session_get_userinfo_claims_json(request_rec *r, oidc_session_t *z);
872 void oidc_session_set_idtoken_claims(request_rec *r, oidc_session_t *z, const char *idtoken_claims);
873 const char * oidc_session_get_idtoken_claims(request_rec *r, oidc_session_t *z);
874 json_t *oidc_session_get_idtoken_claims_json(request_rec *r, oidc_session_t *z);
875 void oidc_session_set_idtoken(request_rec *r, oidc_session_t *z, const char *s_id_token);
876 const char * oidc_session_get_idtoken(request_rec *r, oidc_session_t *z);
877 void oidc_session_set_access_token(request_rec *r, oidc_session_t *z, const char *access_token);
878 const char * oidc_session_get_access_token(request_rec *r, oidc_session_t *z);
879 void oidc_session_set_access_token_expires(request_rec *r, oidc_session_t *z, const int expires_in);
880 const char * oidc_session_get_access_token_expires(request_rec *r, oidc_session_t *z);
881 void oidc_session_set_refresh_token(request_rec *r, oidc_session_t *z, const char *refresh_token);
882 const char * oidc_session_get_refresh_token(request_rec *r, oidc_session_t *z);
883 void oidc_session_set_session_expires(request_rec *r, oidc_session_t *z, const apr_time_t expires);
884 apr_time_t oidc_session_get_session_expires(request_rec *r, oidc_session_t *z);
885 void oidc_session_set_cookie_domain(request_rec *r, oidc_session_t *z, const char *cookie_domain);
886 const char * oidc_session_get_cookie_domain(request_rec *r, oidc_session_t *z);
887 void oidc_session_reset_userinfo_last_refresh(request_rec *r, oidc_session_t *z);
888 apr_time_t oidc_session_get_userinfo_last_refresh(request_rec *r, oidc_session_t *z);
889 void oidc_session_reset_access_token_last_refresh(request_rec *r, oidc_session_t *z);
890 apr_time_t oidc_session_get_access_token_last_refresh(request_rec *r, oidc_session_t *z);
891 void oidc_session_set_request_state(request_rec *r, oidc_session_t *z, const char *request_state);
892 const char * oidc_session_get_request_state(request_rec *r, oidc_session_t *z);
893 void oidc_session_set_original_url(request_rec *r, oidc_session_t *z, const char *original_url);
894 const char * oidc_session_get_original_url(request_rec *r, oidc_session_t *z);
895 void oidc_session_set_session_state(request_rec *r, oidc_session_t *z, const char *session_state);
896 const char * oidc_session_get_session_state(request_rec *r, oidc_session_t *z);
897 void oidc_session_set_issuer(request_rec *r, oidc_session_t *z, const char *issuer);
898 const char * oidc_session_get_issuer(request_rec *r, oidc_session_t *z);
899 void oidc_session_set_client_id(request_rec *r, oidc_session_t *z, const char *client_id);
900 
901 char *oidc_parse_base64(apr_pool_t *pool, const char *input, char **output, int *output_len);
902 
903 #endif /* MOD_AUTH_OPENIDC_H_ */
904