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 #include <apr_base64.h>
45 #include <apr_lib.h>
46
47 #include <httpd.h>
48 #include <http_core.h>
49 #include <http_config.h>
50 #include <http_log.h>
51
52 #include "mod_auth_openidc.h"
53
54 extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
55
56 /* the name of the remote-user attribute in the session */
57 #define OIDC_SESSION_REMOTE_USER_KEY "r"
58 /* the name of the session expiry attribute in the session */
59 #define OIDC_SESSION_EXPIRY_KEY "e"
60 /* the name of the provided token binding attribute in the session */
61 #define OIDC_SESSION_PROVIDED_TOKEN_BINDING_KEY "ptb"
62 /* the name of the session identifier in the session */
63 #define OIDC_SESSION_SESSION_ID "i"
64 /* the name of the sub attribute in the session */
65 #define OIDC_SESSION_SUB_KEY "sub"
66 /* the name of the sid attribute in the session */
67 #define OIDC_SESSION_SID_KEY "sid"
68
oidc_session_encode(request_rec * r,oidc_cfg * c,oidc_session_t * z,char ** s_value,apr_byte_t encrypt)69 static apr_byte_t oidc_session_encode(request_rec *r, oidc_cfg *c,
70 oidc_session_t *z, char **s_value, apr_byte_t encrypt) {
71
72 if (encrypt == FALSE) {
73 *s_value = oidc_util_encode_json_object(r, z->state, JSON_COMPACT);
74 return (*s_value != NULL);
75 }
76
77 if (oidc_util_jwt_create(r, c->crypto_passphrase, z->state,
78 s_value) == FALSE)
79 return FALSE;
80
81 return TRUE;
82 }
83
oidc_session_decode(request_rec * r,oidc_cfg * c,oidc_session_t * z,const char * s_json,apr_byte_t encrypt)84 static apr_byte_t oidc_session_decode(request_rec *r, oidc_cfg *c,
85 oidc_session_t *z, const char *s_json, apr_byte_t encrypt) {
86
87 if (encrypt == FALSE) {
88 return oidc_util_decode_json_object(r, s_json, &z->state);
89 }
90
91 if (oidc_util_jwt_verify(r, c->crypto_passphrase, s_json,
92 &z->state) == FALSE) {
93 oidc_error(r,
94 "could not verify secure JWT: cache value possibly corrupted");
95 return FALSE;
96 }
97 return TRUE;
98 }
99
100 /*
101 * generate a unique identifier for a session
102 */
oidc_session_uuid_new(request_rec * r,oidc_session_t * z)103 static void oidc_session_uuid_new(request_rec *r, oidc_session_t *z) {
104 apr_uuid_t uuid;
105 apr_uuid_get(&uuid);
106 apr_uuid_format((char *) &z->uuid, &uuid);
107 }
108
109 /*
110 * clear contents of a session
111 */
oidc_session_clear(request_rec * r,oidc_session_t * z)112 static void oidc_session_clear(request_rec *r, oidc_session_t *z) {
113 z->uuid[0] = '\0';
114 z->remote_user = NULL;
115 // NB: don't clear sid
116 z->expiry = 0;
117 if (z->state) {
118 json_decref(z->state);
119 z->state = NULL;
120 }
121 }
122
oidc_session_load_cache_by_uuid(request_rec * r,oidc_cfg * c,const char * uuid,oidc_session_t * z)123 apr_byte_t oidc_session_load_cache_by_uuid(request_rec *r, oidc_cfg *c,
124 const char *uuid, oidc_session_t *z) {
125 const char *stored_uuid = NULL;
126 char *s_json = NULL;
127 apr_byte_t rc = FALSE;
128
129 rc = oidc_cache_get_session(r, uuid, &s_json);
130
131 if ((rc == TRUE) && (s_json != NULL)) {
132 rc = oidc_session_decode(r, c, z, s_json, FALSE);
133 if (rc == TRUE) {
134 strncpy(z->uuid, uuid, APR_UUID_FORMATTED_LENGTH);
135 z->uuid[APR_UUID_FORMATTED_LENGTH] = '\0';
136
137 /* compare the session id in the cache value so it allows us to detect cache corruption */
138 oidc_session_get(r, z, OIDC_SESSION_SESSION_ID, &stored_uuid);
139 if ((stored_uuid == NULL)
140 || (apr_strnatcmp(stored_uuid, uuid) != 0)) {
141 oidc_error(r,
142 "cache corruption detected: stored session id (%s) is not equal to requested session id (%s)",
143 stored_uuid, uuid);
144
145 /* delete the cache entry */
146 oidc_cache_set_session(r, z->uuid, NULL, 0);
147 /* clear the session */
148 oidc_session_clear(r, z);
149
150 rc = FALSE;
151 }
152 }
153 }
154
155 return rc;
156 }
157
158 /*
159 * load the session from the cache using the cookie as the index
160 */
oidc_session_load_cache(request_rec * r,oidc_session_t * z)161 static apr_byte_t oidc_session_load_cache(request_rec *r, oidc_session_t *z) {
162 oidc_cfg *c = ap_get_module_config(r->server->module_config,
163 &auth_openidc_module);
164
165 apr_byte_t rc = FALSE;
166
167 /* get the cookie that should be our uuid/key */
168 char *uuid = oidc_util_get_cookie(r, oidc_cfg_dir_cookie(r));
169
170 /* get the string-encoded session from the cache based on the key; decryption is based on the cache backend config */
171 if (uuid != NULL) {
172
173 rc = oidc_session_load_cache_by_uuid(r, c, uuid, z);
174
175 if (rc == FALSE || z->state == NULL) {
176 /* delete the session cookie */
177 oidc_util_set_cookie(r, oidc_cfg_dir_cookie(r), "", 0,
178 OIDC_COOKIE_EXT_SAME_SITE_NONE(r));
179 }
180 }
181
182 return rc;
183 }
184
185 /*
186 * save the session to the cache using a cookie for the index
187 */
oidc_session_save_cache(request_rec * r,oidc_session_t * z,apr_byte_t first_time)188 static apr_byte_t oidc_session_save_cache(request_rec *r, oidc_session_t *z,
189 apr_byte_t first_time) {
190 oidc_cfg *c = ap_get_module_config(r->server->module_config,
191 &auth_openidc_module);
192
193 apr_byte_t rc = TRUE;
194
195 if (z->state != NULL) {
196
197 if (apr_strnatcmp(z->uuid, "") == 0) {
198 /* get a new uuid for this session */
199 oidc_session_uuid_new(r, z);
200 /* store the session id in the cache value so it allows us to detect cache corruption */
201 oidc_session_set(r, z, OIDC_SESSION_SESSION_ID, z->uuid);
202 }
203
204 if (z->sid != NULL) {
205 oidc_cache_set_sid(r, z->sid, z->uuid, z->expiry);
206 oidc_session_set(r, z, OIDC_SESSION_SID_KEY, z->sid);
207 }
208
209 /* store the string-encoded session in the cache; encryption depends on cache backend settings */
210 char *s_value = NULL;
211 if (oidc_session_encode(r, c, z, &s_value, FALSE) == FALSE)
212 return FALSE;
213 rc = oidc_cache_set_session(r, z->uuid, s_value, z->expiry);
214
215 if (rc == TRUE)
216 /* set the uuid in the cookie */
217 oidc_util_set_cookie(r, oidc_cfg_dir_cookie(r), z->uuid,
218 c->persistent_session_cookie ? z->expiry : -1,
219 c->cookie_same_site ?
220 (first_time ?
221 OIDC_COOKIE_EXT_SAME_SITE_LAX :
222 OIDC_COOKIE_EXT_SAME_SITE_STRICT) :
223 OIDC_COOKIE_EXT_SAME_SITE_NONE(r));
224
225 } else {
226
227 if (z->sid != NULL)
228 oidc_cache_set_sid(r, z->sid, NULL, 0);
229
230 /* clear the cookie */
231 oidc_util_set_cookie(r, oidc_cfg_dir_cookie(r), "", 0,
232 OIDC_COOKIE_EXT_SAME_SITE_NONE(r));
233
234 /* remove the session from the cache */
235 rc = oidc_cache_set_session(r, z->uuid, NULL, 0);
236 }
237
238 return rc;
239 }
240
241 /*
242 * load the session from a self-contained client-side cookie
243 */
oidc_session_load_cookie(request_rec * r,oidc_cfg * c,oidc_session_t * z)244 static apr_byte_t oidc_session_load_cookie(request_rec *r, oidc_cfg *c,
245 oidc_session_t *z) {
246 char *cookieValue = oidc_util_get_chunked_cookie(r, oidc_cfg_dir_cookie(r),
247 c->session_cookie_chunk_size);
248 if ((cookieValue != NULL)
249 && (oidc_session_decode(r, c, z, cookieValue, TRUE) == FALSE))
250 return FALSE;
251 return TRUE;
252 }
253
254 /*
255 * store the session in a self-contained client-side-only cookie storage
256 */
oidc_session_save_cookie(request_rec * r,oidc_session_t * z,apr_byte_t first_time)257 static apr_byte_t oidc_session_save_cookie(request_rec *r, oidc_session_t *z,
258 apr_byte_t first_time) {
259 oidc_cfg *c = ap_get_module_config(r->server->module_config,
260 &auth_openidc_module);
261 char *cookieValue = "";
262 if ((z->state != NULL)
263 && (oidc_session_encode(r, c, z, &cookieValue, TRUE) == FALSE))
264 return FALSE;
265
266 oidc_util_set_chunked_cookie(r, oidc_cfg_dir_cookie(r), cookieValue,
267 c->persistent_session_cookie ? z->expiry : -1,
268 c->session_cookie_chunk_size,
269 (z->state == NULL) ? OIDC_COOKIE_EXT_SAME_SITE_NONE(r) :
270 c->cookie_same_site ?
271 (first_time ?
272 OIDC_COOKIE_EXT_SAME_SITE_LAX :
273 OIDC_COOKIE_EXT_SAME_SITE_STRICT) :
274 OIDC_COOKIE_EXT_SAME_SITE_NONE(r));
275
276 return TRUE;
277 }
278
oidc_session_extract(request_rec * r,oidc_session_t * z)279 apr_byte_t oidc_session_extract(request_rec *r, oidc_session_t *z) {
280 apr_byte_t rc = FALSE;
281 const char *ses_p_tb_id = NULL, *env_p_tb_id = NULL;
282
283 if (z->state == NULL)
284 goto out;
285
286 json_t *j_expires = json_object_get(z->state, OIDC_SESSION_EXPIRY_KEY);
287 if (j_expires)
288 z->expiry = apr_time_from_sec(json_integer_value(j_expires));
289
290 /* check whether it has expired */
291 if (apr_time_now() > z->expiry) {
292
293 oidc_warn(r, "session restored from cache has expired");
294 oidc_session_clear(r, z);
295
296 goto out;
297 }
298
299 oidc_session_get(r, z, OIDC_SESSION_PROVIDED_TOKEN_BINDING_KEY,
300 &ses_p_tb_id);
301
302 if (ses_p_tb_id != NULL) {
303 env_p_tb_id = oidc_util_get_provided_token_binding_id(r);
304 if ((env_p_tb_id == NULL)
305 || (apr_strnatcmp(env_p_tb_id, ses_p_tb_id) != 0)) {
306 oidc_error(r,
307 "the Provided Token Binding ID stored in the session doesn't match the one presented by the user agent");
308 oidc_session_clear(r, z);
309 }
310 }
311
312 oidc_session_get(r, z, OIDC_SESSION_REMOTE_USER_KEY, &z->remote_user);
313 oidc_session_get(r, z, OIDC_SESSION_SID_KEY, &z->sid);
314
315 rc = TRUE;
316
317 out:
318
319 return rc;
320 }
321
322 /*
323 * load a session from the cache/cookie
324 */
oidc_session_load(request_rec * r,oidc_session_t ** zz)325 apr_byte_t oidc_session_load(request_rec *r, oidc_session_t **zz) {
326 oidc_cfg *c = ap_get_module_config(r->server->module_config,
327 &auth_openidc_module);
328
329 apr_byte_t rc = FALSE;
330
331 /* allocate space for the session object and fill it */
332 oidc_session_t *z = (*zz = apr_pcalloc(r->pool, sizeof(oidc_session_t)));
333 oidc_session_clear(r, z);
334 z->sid = NULL;
335
336 if (c->session_type == OIDC_SESSION_TYPE_SERVER_CACHE)
337 /* load the session from the cache */
338 rc = oidc_session_load_cache(r, z);
339
340 /* if we get here we configured client-cookie or retrieving from the cache failed */
341 if ((c->session_type == OIDC_SESSION_TYPE_CLIENT_COOKIE)
342 || ((rc == FALSE) && oidc_cfg_session_cache_fallback_to_cookie(r)))
343 /* load the session from a self-contained cookie */
344 rc = oidc_session_load_cookie(r, c, z);
345
346 if (rc == TRUE)
347 rc = oidc_session_extract(r, z);
348
349 return rc;
350 }
351
352 /*
353 * save a session to cache/cookie
354 */
oidc_session_save(request_rec * r,oidc_session_t * z,apr_byte_t first_time)355 apr_byte_t oidc_session_save(request_rec *r, oidc_session_t *z,
356 apr_byte_t first_time) {
357 oidc_cfg *c = ap_get_module_config(r->server->module_config,
358 &auth_openidc_module);
359
360 apr_byte_t rc = FALSE;
361 const char *p_tb_id = oidc_util_get_provided_token_binding_id(r);
362
363 if (z->state != NULL) {
364 oidc_session_set(r, z, OIDC_SESSION_REMOTE_USER_KEY, z->remote_user);
365 json_object_set_new(z->state, OIDC_SESSION_EXPIRY_KEY,
366 json_integer(apr_time_sec(z->expiry)));
367
368 if ((first_time) && (p_tb_id != NULL)) {
369 oidc_debug(r,
370 "Provided Token Binding ID environment variable found; adding its value to the session state");
371 oidc_session_set(r, z, OIDC_SESSION_PROVIDED_TOKEN_BINDING_KEY,
372 p_tb_id);
373 }
374 }
375
376 if (c->session_type == OIDC_SESSION_TYPE_SERVER_CACHE)
377 /* store the session in the cache */
378 rc = oidc_session_save_cache(r, z, first_time);
379
380 /* if we get here we configured client-cookie or saving in the cache failed */
381 if ((c->session_type == OIDC_SESSION_TYPE_CLIENT_COOKIE)
382 || ((rc == FALSE) && oidc_cfg_session_cache_fallback_to_cookie(r)))
383 /* store the session in a self-contained cookie */
384 rc = oidc_session_save_cookie(r, z, first_time);
385
386 return rc;
387 }
388
389 /*
390 * free resources allocated for a session
391 */
oidc_session_free(request_rec * r,oidc_session_t * z)392 apr_byte_t oidc_session_free(request_rec *r, oidc_session_t *z) {
393 oidc_session_clear(r, z);
394 return TRUE;
395 }
396
397 /*
398 * terminate a session
399 */
oidc_session_kill(request_rec * r,oidc_session_t * z)400 apr_byte_t oidc_session_kill(request_rec *r, oidc_session_t *z) {
401 if (z->state) {
402 json_decref(z->state);
403 z->state = NULL;
404 }
405 oidc_session_save(r, z, FALSE);
406 return oidc_session_free(r, z);
407 }
408
409 /*
410 * get a value from the session based on the name from a name/value pair
411 */
oidc_session_get(request_rec * r,oidc_session_t * z,const char * key,const char ** value)412 apr_byte_t oidc_session_get(request_rec *r, oidc_session_t *z, const char *key,
413 const char **value) {
414
415 /* just return the value for the key */
416 oidc_json_object_get_string(r->pool, z->state, key, (char **) value, NULL);
417
418 return TRUE;
419 }
420
421 /*
422 * set a name/value key pair in the session
423 */
oidc_session_set(request_rec * r,oidc_session_t * z,const char * key,const char * value)424 apr_byte_t oidc_session_set(request_rec *r, oidc_session_t *z, const char *key,
425 const char *value) {
426
427 /* only set it if non-NULL, otherwise delete the entry */
428 if (value) {
429 if (z->state == NULL)
430 z->state = json_object();
431 json_object_set_new(z->state, key, json_string(value));
432 } else if (z->state != NULL) {
433 json_object_del(z->state, key);
434 }
435
436 return TRUE;
437 }
438
439 /*
440 * session object keys
441 */
442 /* key for storing the userinfo claims in the session context */
443 #define OIDC_SESSION_KEY_USERINFO_CLAIMS "uic"
444 /* key for storing the userinfo JWT in the session context */
445 #define OIDC_SESSION_KEY_USERINFO_JWT "uij"
446 /* key for storing the id_token in the session context */
447 #define OIDC_SESSION_KEY_IDTOKEN_CLAIMS "idc"
448 /* key for storing the raw id_token in the session context */
449 #define OIDC_SESSION_KEY_IDTOKEN "idt"
450 /* key for storing the access_token in the session context */
451 #define OIDC_SESSION_KEY_ACCESSTOKEN "at"
452 /* key for storing the access_token expiry in the session context */
453 #define OIDC_SESSION_KEY_ACCESSTOKEN_EXPIRES "ate"
454 /* key for storing the refresh_token in the session context */
455 #define OIDC_SESSION_KEY_REFRESH_TOKEN "rt"
456 /* key for storing maximum session duration in the session context */
457 #define OIDC_SESSION_KEY_SESSION_EXPIRES "se"
458 /* key for storing the cookie domain in the session context */
459 #define OIDC_SESSION_KEY_COOKIE_DOMAIN "cd"
460 /* key for storing last user info refresh timestamp in the session context */
461 #define OIDC_SESSION_KEY_USERINFO_LAST_REFRESH "uilr"
462 /* key for storing last access token refresh timestamp in the session context */
463 #define OIDC_SESSION_KEY_ACCESS_TOKEN_LAST_REFRESH "atlr"
464 /* key for storing request state */
465 #define OIDC_SESSION_KEY_REQUEST_STATE "rs"
466 /* key for storing the original URL */
467 #define OIDC_SESSION_KEY_ORIGINAL_URL "ou"
468 /* key for storing the session_state in the session context */
469 #define OIDC_SESSION_KEY_SESSION_STATE "ss"
470 /* key for storing the issuer in the session context */
471 #define OIDC_SESSION_KEY_ISSUER "iss"
472
473 /*
474 * helper functions
475 */
476 typedef const char *(*oidc_session_get_str_function)(request_rec *r,
477 oidc_session_t *z);
478
oidc_session_set_timestamp(request_rec * r,oidc_session_t * z,const char * key,const apr_time_t timestamp)479 static void oidc_session_set_timestamp(request_rec *r, oidc_session_t *z,
480 const char *key, const apr_time_t timestamp) {
481 if (timestamp != -1)
482 oidc_session_set(r, z, key,
483 apr_psprintf(r->pool, "%" APR_TIME_T_FMT, timestamp));
484 }
485
oidc_session_get_str2json(request_rec * r,oidc_session_t * z,oidc_session_get_str_function session_get_str_fn)486 static json_t *oidc_session_get_str2json(request_rec *r, oidc_session_t *z,
487 oidc_session_get_str_function session_get_str_fn) {
488 json_t *json = NULL;
489 const char *str = session_get_str_fn(r, z);
490 if (str != NULL)
491 oidc_util_decode_json_object(r, str, &json);
492 return json;
493 }
494
oidc_session_get_key2string(request_rec * r,oidc_session_t * z,const char * key)495 static const char *oidc_session_get_key2string(request_rec *r,
496 oidc_session_t *z, const char *key) {
497 const char *s_value = NULL;
498 oidc_session_get(r, z, key, &s_value);
499 return s_value;
500 }
501
oidc_session_get_key2timestamp(request_rec * r,oidc_session_t * z,const char * key)502 static apr_time_t oidc_session_get_key2timestamp(request_rec *r,
503 oidc_session_t *z, const char *key) {
504 apr_time_t t_expires = 0;
505 const char *s_expires = oidc_session_get_key2string(r, z, key);
506 if (s_expires != NULL)
507 sscanf(s_expires, "%" APR_TIME_T_FMT, &t_expires);
508 return t_expires;
509 }
510
oidc_session_set_filtered_claims(request_rec * r,oidc_session_t * z,const char * session_key,const char * claims)511 void oidc_session_set_filtered_claims(request_rec *r, oidc_session_t *z,
512 const char *session_key, const char *claims) {
513 oidc_cfg *c = ap_get_module_config(r->server->module_config,
514 &auth_openidc_module);
515
516 const char *name;
517 json_t *src = NULL, *dst = NULL, *value = NULL;
518 void *iter = NULL;
519 apr_byte_t is_allowed;
520
521 if (oidc_util_decode_json_object(r, claims, &src) == FALSE) {
522 oidc_session_set(r, z, session_key, NULL);
523 return;
524 }
525
526 dst = json_object();
527 iter = json_object_iter(src);
528 while (iter) {
529 is_allowed = TRUE;
530 name = json_object_iter_key(iter);
531 value = json_object_iter_value(iter);
532
533 if ((c->black_listed_claims != NULL)
534 && (apr_hash_get(c->black_listed_claims, name,
535 APR_HASH_KEY_STRING) != NULL)) {
536 oidc_debug(r, "removing blacklisted claim [%s]: '%s'", session_key,
537 name);
538 is_allowed = FALSE;
539 }
540
541 if ((is_allowed == TRUE) && (c->white_listed_claims != NULL)
542 && (apr_hash_get(c->white_listed_claims, name,
543 APR_HASH_KEY_STRING) == NULL)) {
544 oidc_debug(r, "removing non-whitelisted claim [%s]: '%s'",
545 session_key, name);
546 is_allowed = FALSE;
547 }
548
549 if (is_allowed == TRUE)
550 json_object_set(dst, name, value);
551
552 iter = json_object_iter_next(src, iter);
553 }
554
555 char *filtered_claims = oidc_util_encode_json_object(r, dst, JSON_COMPACT);
556 json_decref(dst);
557 json_decref(src);
558 oidc_session_set(r, z, session_key, filtered_claims);
559 }
560
561 /*
562 * userinfo claims
563 */
oidc_session_set_userinfo_claims(request_rec * r,oidc_session_t * z,const char * claims)564 void oidc_session_set_userinfo_claims(request_rec *r, oidc_session_t *z,
565 const char *claims) {
566 oidc_session_set_filtered_claims(r, z, OIDC_SESSION_KEY_USERINFO_CLAIMS,
567 claims);
568 }
569
oidc_session_get_userinfo_claims(request_rec * r,oidc_session_t * z)570 const char * oidc_session_get_userinfo_claims(request_rec *r, oidc_session_t *z) {
571 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_USERINFO_CLAIMS);
572 }
573
oidc_session_get_userinfo_claims_json(request_rec * r,oidc_session_t * z)574 json_t *oidc_session_get_userinfo_claims_json(request_rec *r, oidc_session_t *z) {
575 return oidc_session_get_str2json(r, z, oidc_session_get_userinfo_claims);
576 }
577
oidc_session_set_userinfo_jwt(request_rec * r,oidc_session_t * z,const char * s_userinfo_jwt)578 void oidc_session_set_userinfo_jwt(request_rec *r, oidc_session_t *z,
579 const char *s_userinfo_jwt) {
580 oidc_session_set(r, z, OIDC_SESSION_KEY_USERINFO_JWT, s_userinfo_jwt);
581 }
582
oidc_session_get_userinfo_jwt(request_rec * r,oidc_session_t * z)583 const char * oidc_session_get_userinfo_jwt(request_rec *r, oidc_session_t *z) {
584 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_USERINFO_JWT);
585 }
586
587 /*
588 * id_token claims
589 */
oidc_session_set_idtoken_claims(request_rec * r,oidc_session_t * z,const char * idtoken_claims)590 void oidc_session_set_idtoken_claims(request_rec *r, oidc_session_t *z,
591 const char *idtoken_claims) {
592 oidc_session_set_filtered_claims(r, z, OIDC_SESSION_KEY_IDTOKEN_CLAIMS,
593 idtoken_claims);
594 }
595
oidc_session_get_idtoken_claims(request_rec * r,oidc_session_t * z)596 const char * oidc_session_get_idtoken_claims(request_rec *r, oidc_session_t *z) {
597 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_IDTOKEN_CLAIMS);
598 }
599
oidc_session_get_idtoken_claims_json(request_rec * r,oidc_session_t * z)600 json_t *oidc_session_get_idtoken_claims_json(request_rec *r, oidc_session_t *z) {
601 return oidc_session_get_str2json(r, z, oidc_session_get_idtoken_claims);
602 }
603
604 /*
605 * compact serialized id_token
606 */
oidc_session_set_idtoken(request_rec * r,oidc_session_t * z,const char * s_id_token)607 void oidc_session_set_idtoken(request_rec *r, oidc_session_t *z,
608 const char *s_id_token) {
609 oidc_session_set(r, z, OIDC_SESSION_KEY_IDTOKEN, s_id_token);
610 }
611
oidc_session_get_idtoken(request_rec * r,oidc_session_t * z)612 const char * oidc_session_get_idtoken(request_rec *r, oidc_session_t *z) {
613 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_IDTOKEN);
614 }
615
616 /*
617 * access token
618 */
oidc_session_set_access_token(request_rec * r,oidc_session_t * z,const char * access_token)619 void oidc_session_set_access_token(request_rec *r, oidc_session_t *z,
620 const char *access_token) {
621 oidc_session_set(r, z, OIDC_SESSION_KEY_ACCESSTOKEN, access_token);
622 }
623
oidc_session_get_access_token(request_rec * r,oidc_session_t * z)624 const char * oidc_session_get_access_token(request_rec *r, oidc_session_t *z) {
625 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_ACCESSTOKEN);
626 }
627
628 /*
629 * access token expires
630 */
oidc_session_set_access_token_expires(request_rec * r,oidc_session_t * z,const int expires_in)631 void oidc_session_set_access_token_expires(request_rec *r, oidc_session_t *z,
632 const int expires_in) {
633 if (expires_in != -1) {
634 oidc_session_set(r, z, OIDC_SESSION_KEY_ACCESSTOKEN_EXPIRES,
635 apr_psprintf(r->pool, "%" APR_TIME_T_FMT,
636 apr_time_sec(apr_time_now()) + expires_in));
637 }
638 }
639
oidc_session_get_access_token_expires(request_rec * r,oidc_session_t * z)640 const char * oidc_session_get_access_token_expires(request_rec *r,
641 oidc_session_t *z) {
642 return oidc_session_get_key2string(r, z,
643 OIDC_SESSION_KEY_ACCESSTOKEN_EXPIRES);
644 }
645
646 /*
647 * refresh token
648 */
oidc_session_set_refresh_token(request_rec * r,oidc_session_t * z,const char * refresh_token)649 void oidc_session_set_refresh_token(request_rec *r, oidc_session_t *z,
650 const char *refresh_token) {
651 oidc_session_set(r, z, OIDC_SESSION_KEY_REFRESH_TOKEN, refresh_token);
652 }
653
oidc_session_get_refresh_token(request_rec * r,oidc_session_t * z)654 const char * oidc_session_get_refresh_token(request_rec *r, oidc_session_t *z) {
655 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_REFRESH_TOKEN);
656 }
657
658 /*
659 * session expires
660 */
oidc_session_set_session_expires(request_rec * r,oidc_session_t * z,const apr_time_t expires)661 void oidc_session_set_session_expires(request_rec *r, oidc_session_t *z,
662 const apr_time_t expires) {
663 oidc_session_set_timestamp(r, z, OIDC_SESSION_KEY_SESSION_EXPIRES, expires);
664 }
665
oidc_session_get_session_expires(request_rec * r,oidc_session_t * z)666 apr_time_t oidc_session_get_session_expires(request_rec *r, oidc_session_t *z) {
667 return oidc_session_get_key2timestamp(r, z,
668 OIDC_SESSION_KEY_SESSION_EXPIRES);
669 }
670
671 /*
672 * cookie domain
673 */
oidc_session_set_cookie_domain(request_rec * r,oidc_session_t * z,const char * cookie_domain)674 void oidc_session_set_cookie_domain(request_rec *r, oidc_session_t *z,
675 const char *cookie_domain) {
676 oidc_session_set(r, z, OIDC_SESSION_KEY_COOKIE_DOMAIN, cookie_domain);
677 }
678
oidc_session_get_cookie_domain(request_rec * r,oidc_session_t * z)679 const char * oidc_session_get_cookie_domain(request_rec *r, oidc_session_t *z) {
680 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_COOKIE_DOMAIN);
681 }
682
683 /*
684 * userinfo last refresh
685 */
oidc_session_reset_userinfo_last_refresh(request_rec * r,oidc_session_t * z)686 void oidc_session_reset_userinfo_last_refresh(request_rec *r, oidc_session_t *z) {
687 oidc_session_set_timestamp(r, z, OIDC_SESSION_KEY_USERINFO_LAST_REFRESH,
688 apr_time_now());
689 }
690
oidc_session_get_userinfo_last_refresh(request_rec * r,oidc_session_t * z)691 apr_time_t oidc_session_get_userinfo_last_refresh(request_rec *r,
692 oidc_session_t *z) {
693 return oidc_session_get_key2timestamp(r, z,
694 OIDC_SESSION_KEY_USERINFO_LAST_REFRESH);
695 }
696
697 /*
698 * access_token last refresh
699 */
oidc_session_reset_access_token_last_refresh(request_rec * r,oidc_session_t * z)700 void oidc_session_reset_access_token_last_refresh(request_rec *r,
701 oidc_session_t *z) {
702 oidc_session_set_timestamp(r, z, OIDC_SESSION_KEY_ACCESS_TOKEN_LAST_REFRESH,
703 apr_time_now());
704 }
705
oidc_session_get_access_token_last_refresh(request_rec * r,oidc_session_t * z)706 apr_time_t oidc_session_get_access_token_last_refresh(request_rec *r,
707 oidc_session_t *z) {
708 return oidc_session_get_key2timestamp(r, z,
709 OIDC_SESSION_KEY_ACCESS_TOKEN_LAST_REFRESH);
710 }
711
712 /*
713 * request state
714 */
oidc_session_set_request_state(request_rec * r,oidc_session_t * z,const char * request_state)715 void oidc_session_set_request_state(request_rec *r, oidc_session_t *z,
716 const char *request_state) {
717 oidc_session_set(r, z, OIDC_SESSION_KEY_REQUEST_STATE, request_state);
718 }
719
oidc_session_get_request_state(request_rec * r,oidc_session_t * z)720 const char * oidc_session_get_request_state(request_rec *r, oidc_session_t *z) {
721 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_REQUEST_STATE);
722 }
723
724 /*
725 * original url
726 */
oidc_session_set_original_url(request_rec * r,oidc_session_t * z,const char * original_url)727 void oidc_session_set_original_url(request_rec *r, oidc_session_t *z,
728 const char *original_url) {
729 oidc_session_set(r, z, OIDC_SESSION_KEY_ORIGINAL_URL, original_url);
730 }
731
oidc_session_get_original_url(request_rec * r,oidc_session_t * z)732 const char * oidc_session_get_original_url(request_rec *r, oidc_session_t *z) {
733 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_ORIGINAL_URL);
734 }
735
736 /*
737 * session state
738 */
oidc_session_set_session_state(request_rec * r,oidc_session_t * z,const char * session_state)739 void oidc_session_set_session_state(request_rec *r, oidc_session_t *z,
740 const char *session_state) {
741 oidc_session_set(r, z, OIDC_SESSION_KEY_SESSION_STATE, session_state);
742 }
743
oidc_session_get_session_state(request_rec * r,oidc_session_t * z)744 const char * oidc_session_get_session_state(request_rec *r, oidc_session_t *z) {
745 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_SESSION_STATE);
746 }
747
748 /*
749 * issuer
750 */
oidc_session_set_issuer(request_rec * r,oidc_session_t * z,const char * issuer)751 void oidc_session_set_issuer(request_rec *r, oidc_session_t *z,
752 const char *issuer) {
753 oidc_session_set(r, z, OIDC_SESSION_KEY_ISSUER, issuer);
754 }
755
oidc_session_get_issuer(request_rec * r,oidc_session_t * z)756 const char * oidc_session_get_issuer(request_rec *r, oidc_session_t *z) {
757 return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_ISSUER);
758 }
759