~ubuntu-branches/ubuntu/vivid/libapache2-mod-auth-openidc/vivid-proposed

« back to all changes in this revision

Viewing changes to src/proto.c

  • Committer: Package Import Robot
  • Author(s): Hans Zandbelt
  • Date: 2014-10-13 12:23:35 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20141013122335-31wgnq50ascmubib
Tags: 1.6.0-1
new upstream release; add libssl-dev dependency

Show diffs side-by-side

added added

removed removed

Lines of Context:
68
68
        /* read the parameters that are POST-ed to us */
69
69
        apr_table_t *params = apr_table_make(r->pool, 8);
70
70
        if (oidc_util_read_post(r, params) == FALSE) {
71
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
72
 
                                "oidc_proto_authorization_request: something went wrong when reading the POST parameters");
 
71
                oidc_error(r, "something went wrong when reading the POST parameters");
73
72
                return HTTP_INTERNAL_SERVER_ERROR;
74
73
        }
75
74
 
76
 
        // TODO: html encode names/values
77
75
        const apr_array_header_t *arr = apr_table_elts(params);
78
76
        const apr_table_entry_t *elts = (const apr_table_entry_t*) arr->elts;
79
77
        int i;
80
78
        char *json = "";
81
79
        for (i = 0; i < arr->nelts; i++) {
82
 
                json = apr_psprintf(r->pool, "%s'%s': '%s'%s", json, elts[i].key,
83
 
                                elts[i].val, i < arr->nelts - 1 ? "," : "");
 
80
                json = apr_psprintf(r->pool, "%s'%s': '%s'%s", json,
 
81
                                oidc_util_html_escape(r->pool, elts[i].key),
 
82
                                oidc_util_html_escape(r->pool, elts[i].val),
 
83
                                i < arr->nelts - 1 ? "," : "");
84
84
        }
85
85
        json = apr_psprintf(r->pool, "{ %s }", json);
86
86
 
103
103
                                                        "  </body>\n"
104
104
                                                        "</html>\n", json, authorization_request);
105
105
 
106
 
        return oidc_util_http_sendstring(r, java_script, DONE);
 
106
        return oidc_util_html_send(r, java_script, DONE);
107
107
}
108
108
 
109
109
/*
112
112
int oidc_proto_authorization_request(request_rec *r,
113
113
                struct oidc_provider_t *provider, const char *login_hint,
114
114
                const char *redirect_uri, const char *state,
115
 
                oidc_proto_state *proto_state) {
 
115
                oidc_proto_state *proto_state, const char *id_token_hint,
 
116
                const char *auth_request_params) {
116
117
 
117
118
        /* log some stuff */
118
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
119
 
                        "oidc_proto_authorization_request: entering (issuer=%s, redirect_uri=%s, original_url=%s, state=%s, nonce=%s)",
 
119
        oidc_debug(r,
 
120
                        "enter, issuer=%s, redirect_uri=%s, original_url=%s, state=%s, nonce=%s",
120
121
                        provider->issuer, redirect_uri, proto_state->original_url, state,
121
122
                        proto_state->nonce);
122
123
 
155
156
                authorization_request = apr_psprintf(r->pool, "%s&login_hint=%s",
156
157
                                authorization_request, oidc_util_escape_string(r, login_hint));
157
158
 
158
 
        /* add any custom authorization request parameters if configured */
 
159
        /* add the id_token_hint if provided */
 
160
        if (id_token_hint != NULL)
 
161
                authorization_request = apr_psprintf(r->pool, "%s&id_token_hint=%s",
 
162
                                authorization_request,
 
163
                                oidc_util_escape_string(r, id_token_hint));
 
164
 
 
165
        /* add the prompt setting if provided (e.g. "none" for no-GUI checks) */
 
166
        if (proto_state->prompt != NULL)
 
167
                authorization_request = apr_psprintf(r->pool, "%s&prompt=%s",
 
168
                                authorization_request,
 
169
                                oidc_util_escape_string(r, proto_state->prompt));
 
170
 
 
171
        /* add any statically configured custom authorization request parameters */
159
172
        if (provider->auth_request_params != NULL) {
160
173
                authorization_request = apr_psprintf(r->pool, "%s&%s",
161
174
                                authorization_request, provider->auth_request_params);
162
175
        }
163
176
 
 
177
        /* add any dynamically configured custom authorization request parameters */
 
178
        if (auth_request_params != NULL) {
 
179
                authorization_request = apr_psprintf(r->pool, "%s&%s",
 
180
                                authorization_request, auth_request_params);
 
181
        }
 
182
 
164
183
        /* preserve POSTed form parameters if enabled */
165
184
        if (apr_strnatcmp(proto_state->original_method, "form_post") == 0)
166
185
                return oidc_proto_authorization_request_post_preserve(r,
170
189
        apr_table_add(r->headers_out, "Location", authorization_request);
171
190
 
172
191
        /* some more logging */
173
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
174
 
                        "oidc_proto_authorization_request: adding outgoing header: Location: %s",
 
192
        oidc_debug(r, "adding outgoing header: Location: %s",
175
193
                        authorization_request);
176
194
 
177
195
        /* and tell Apache to return an HTTP Redirect (302) message */
210
228
 
211
229
        /* see if we have this nonce cached already */
212
230
        const char *replay = NULL;
213
 
        cfg->cache->get(r, nonce, &replay);
 
231
        cfg->cache->get(r, OIDC_CACHE_SECTION_NONCE, nonce, &replay);
214
232
        if (replay != NULL) {
215
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
216
 
                                "oidc_proto_validate_nonce: the nonce value (%s) passed in the browser state was found in the cache already; possible replay attack!?",
 
233
                oidc_error(r,
 
234
                                "the nonce value (%s) passed in the browser state was found in the cache already; possible replay attack!?",
217
235
                                nonce);
218
236
                return FALSE;
219
237
        }
223
241
        apr_jwt_get_string(r->pool, &jwt->payload.value, "nonce", &j_nonce);
224
242
 
225
243
        if (j_nonce == NULL) {
226
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
227
 
                                "oidc_proto_validate_nonce: id_token JSON payload did not contain a \"nonce\" string");
 
244
                oidc_error(r,
 
245
                                "id_token JSON payload did not contain a \"nonce\" string");
228
246
                return FALSE;
229
247
        }
230
248
 
231
249
        /* see if the nonce in the id_token matches the one that we sent in the authorization request */
232
250
        if (apr_strnatcmp(nonce, j_nonce) != 0) {
233
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
234
 
                                "oidc_proto_validate_nonce: the nonce value (%s) in the id_token did not match the one stored in the browser session (%s)",
 
251
                oidc_error(r,
 
252
                                "the nonce value (%s) in the id_token did not match the one stored in the browser session (%s)",
235
253
                                j_nonce, nonce);
236
254
                return FALSE;
237
255
        }
244
262
                        provider->idtoken_iat_slack * 2 + 10);
245
263
 
246
264
        /* store it in the cache for the calculated duration */
247
 
        cfg->cache->set(r, nonce, nonce, apr_time_now() + nonce_cache_duration);
 
265
        cfg->cache->set(r, OIDC_CACHE_SECTION_NONCE, nonce, nonce,
 
266
                        apr_time_now() + nonce_cache_duration);
248
267
 
249
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
250
 
                        "oidc_proto_validate_nonce: nonce \"%s\" validated successfully and is now cached for %" APR_TIME_T_FMT " seconds",
 
268
        oidc_debug(r,
 
269
                        "nonce \"%s\" validated successfully and is now cached for %" APR_TIME_T_FMT " seconds",
251
270
                        nonce, apr_time_sec(nonce_cache_duration));
252
271
 
253
272
        return TRUE;
268
287
         * the same as the sole audience.
269
288
         */
270
289
        if ((azp != NULL) && (apr_strnatcmp(azp, provider->client_id) != 0)) {
271
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
272
 
                                "oidc_proto_validate_aud_and_azp: the \"azp\" claim (%s) is present in the id_token, but is not equal to the configured client_id (%s)",
 
290
                oidc_error(r,
 
291
                                "the \"azp\" claim (%s) is present in the id_token, but is not equal to the configured client_id (%s)",
273
292
                                azp, provider->client_id);
274
293
                return FALSE;
275
294
        }
284
303
                        /* a single-valued audience must be equal to our client_id */
285
304
                        if (apr_strnatcmp(json_string_value(aud), provider->client_id)
286
305
                                        != 0) {
287
 
                                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
288
 
                                                "oidc_proto_validate_aud_and_azp: the configured client_id (%s) did not match the \"aud\" claim value (%s) in the id_token",
 
306
                                oidc_error(r,
 
307
                                                "the configured client_id (%s) did not match the \"aud\" claim value (%s) in the id_token",
289
308
                                                provider->client_id, json_string_value(aud));
290
309
                                return FALSE;
291
310
                        }
294
313
                } else if (json_is_array(aud)) {
295
314
 
296
315
                        if ((json_array_size(aud) > 1) && (azp == NULL)) {
297
 
                                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
298
 
                                                "oidc_proto_validate_aud_and_azp: the \"aud\" claim value in the id_token is an array with more than 1 element, but \"azp\" claim is not present (a SHOULD in the spec...)");
 
316
                                oidc_debug(r,
 
317
                                                "the \"aud\" claim value in the id_token is an array with more than 1 element, but \"azp\" claim is not present (a SHOULD in the spec...)");
299
318
                        }
300
319
 
301
320
                        if (oidc_util_json_array_has_value(r, aud,
302
321
                                        provider->client_id) == FALSE) {
303
 
                                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
304
 
                                                "oidc_proto_validate_aud_and_azp: our configured client_id (%s) could not be found in the array of values for \"aud\" claim",
 
322
                                oidc_error(r,
 
323
                                                "our configured client_id (%s) could not be found in the array of values for \"aud\" claim",
305
324
                                                provider->client_id);
306
325
                                return FALSE;
307
326
                        }
308
327
                } else {
309
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
310
 
                                        "oidc_proto_validate_aud_and_azp: id_token JSON payload \"aud\" claim is not a string nor an array");
 
328
                        oidc_error(r,
 
329
                                        "id_token JSON payload \"aud\" claim is not a string nor an array");
311
330
                        return FALSE;
312
331
                }
313
332
 
314
333
        } else {
315
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
316
 
                                "oidc_proto_validate_aud_and_azp: id_token JSON payload did not contain an \"aud\" claim");
 
334
                oidc_error(r, "id_token JSON payload did not contain an \"aud\" claim");
317
335
                return FALSE;
318
336
        }
319
337
 
326
344
apr_byte_t oidc_proto_validate_iat(request_rec *r, oidc_provider_t *provider,
327
345
                apr_jwt_t *jwt) {
328
346
        if (jwt->payload.iat == APR_JWT_CLAIM_TIME_EMPTY) {
329
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
330
 
                                "oidc_proto_validate_iat: id_token JSON payload did not contain an \"iat\" number value");
 
347
                oidc_error(r,
 
348
                                "id_token JSON payload did not contain an \"iat\" number value");
331
349
                return FALSE;
332
350
        }
333
351
 
334
352
        /* check if this id_token has been issued just now +- slack (default 10 minutes) */
335
353
        if ((apr_time_now() - apr_time_from_sec(provider->idtoken_iat_slack))
336
354
                        > jwt->payload.iat) {
337
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
338
 
                                "oidc_proto_validate_iat: \"iat\" validation failure (%" APR_TIME_T_FMT "): JWT was issued more than %d seconds ago",
 
355
                oidc_error(r,
 
356
                                "\"iat\" validation failure (%" APR_TIME_T_FMT "): JWT was issued more than %d seconds ago",
339
357
                                jwt->payload.iat, provider->idtoken_iat_slack);
340
358
                return FALSE;
341
359
        }
342
360
        if ((apr_time_now() + apr_time_from_sec(provider->idtoken_iat_slack))
343
361
                        < jwt->payload.iat) {
344
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
345
 
                                "oidc_proto_validate_iat: \"iat\" validation failure (%" APR_TIME_T_FMT "): JWT was issued more than %d seconds in the future",
 
362
                oidc_error(r,
 
363
                                "\"iat\" validation failure (%" APR_TIME_T_FMT "): JWT was issued more than %d seconds in the future",
346
364
                                jwt->payload.iat, provider->idtoken_iat_slack);
347
365
                return FALSE;
348
366
        }
355
373
 */
356
374
apr_byte_t oidc_proto_validate_exp(request_rec *r, apr_jwt_t *jwt) {
357
375
        if (apr_time_now() > jwt->payload.exp) {
358
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
359
 
                                "oidc_proto_validate_exp: \"exp\" validation failure (%" APR_TIME_T_FMT "): JWT expired",
 
376
                oidc_error(r,
 
377
                                "\"exp\" validation failure (%" APR_TIME_T_FMT "): JWT expired",
360
378
                                jwt->payload.exp);
361
379
                return FALSE;
362
380
        }
372
390
        oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
373
391
                        &auth_openidc_module);
374
392
 
375
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
376
 
                        "oidc_proto_validate_idtoken: entering jwt.header=\"%s\", jwt.payload=\%s\", nonce=%s",
 
393
        oidc_debug(r, "enter, jwt.header=\"%s\", jwt.payload=\%s\", nonce=%s",
377
394
                        jwt->header.value.str, jwt->payload.value.str, nonce);
378
395
 
379
396
        /* if a nonce is not passed, we're doing a ("code") flow where the nonce is optional */
385
402
 
386
403
        /* issuer is mandatory in id_token */
387
404
        if (jwt->payload.iss == NULL) {
388
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
389
 
                                "oidc_proto_validate_idtoken: response JSON object did not contain an \"iss\" string");
 
405
                oidc_error(r, "response JSON object did not contain an \"iss\" string");
390
406
                return FALSE;
391
407
        }
392
408
 
393
409
        /* check if the issuer matches the requested value */
394
410
        if (oidc_util_issuer_match(provider->issuer, jwt->payload.iss) == FALSE) {
395
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
396
 
                                "oidc_proto_validate_idtoken: configured issuer (%s) does not match received \"iss\" value in id_token (%s)",
 
411
                oidc_error(r,
 
412
                                "configured issuer (%s) does not match received \"iss\" value in id_token (%s)",
397
413
                                provider->issuer, jwt->payload.iss);
398
414
                return FALSE;
399
415
        }
408
424
 
409
425
        /* check if the required-by-spec "sub" claim is present */
410
426
        if (jwt->payload.sub == NULL) {
411
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
412
 
                                "oidc_proto_validate_idtoken: id_token JSON payload did not contain the required-by-spec \"sub\" string value");
 
427
                oidc_error(r,
 
428
                                "id_token JSON payload did not contain the required-by-spec \"sub\" string value");
413
429
                return FALSE;
414
430
        }
415
431
 
431
447
        char *x5t = NULL;
432
448
        apr_jwt_get_string(r->pool, &jwt_hdr->value, "x5t", &x5t);
433
449
 
434
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
435
 
                        "oidc_proto_get_key_from_jwks: search for kid \"%s\" or thumbprint x5t \"%s\"",
 
450
        oidc_debug(r, "search for kid \"%s\" or thumbprint x5t \"%s\"",
436
451
                        jwt_hdr->kid, x5t);
437
452
 
438
453
        /* get the "keys" JSON array from the JWKs object */
439
454
        json_t *keys = json_object_get(j_jwks, "keys");
440
455
        if ((keys == NULL) || !(json_is_array(keys))) {
441
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
442
 
                                "oidc_proto_get_key_from_jwks: \"keys\" array element is not a JSON array");
 
456
                oidc_error(r, "\"keys\" array element is not a JSON array");
443
457
                return FALSE;
444
458
        }
445
459
 
451
465
 
452
466
                /* check that it is a JSON object */
453
467
                if (!json_is_object(elem)) {
454
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
455
 
                                        "oidc_proto_get_key_from_jwks: \"keys\" array element is not a JSON object, skipping");
 
468
                        oidc_warn(r,
 
469
                                        "\"keys\" array element is not a JSON object, skipping");
456
470
                        continue;
457
471
                }
458
472
 
464
478
 
465
479
                /* see if we were looking for a specific kid, if not we'll return the first one found */
466
480
                if ((jwt_hdr->kid == NULL) && (x5t == NULL)) {
467
 
                        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
468
 
                                        "oidc_proto_get_key_from_jwks: no kid/x5t to match, return first key found");
 
481
                        oidc_debug(r, "no kid/x5t to match, return first key found");
469
482
 
470
483
                        apr_jwk_parse_json(r->pool, elem, NULL, result);
471
484
                        break;
476
489
                if ((ekid != NULL) && json_is_string(ekid) && (jwt_hdr->kid != NULL)) {
477
490
                        /* compare the requested kid against the current element */
478
491
                        if (apr_strnatcmp(jwt_hdr->kid, json_string_value(ekid)) == 0) {
479
 
                                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
480
 
                                                "oidc_proto_get_key_from_jwks: found matching kid: \"%s\"",
481
 
                                                jwt_hdr->kid);
 
492
                                oidc_debug(r, "found matching kid: \"%s\"", jwt_hdr->kid);
482
493
 
483
494
                                apr_jwk_parse_json(r->pool, elem, NULL, result);
484
495
                                break;
490
501
                if ((ex5t != NULL) && json_is_string(ex5t) && (x5t != NULL)) {
491
502
                        /* compare the requested kid against the current element */
492
503
                        if (apr_strnatcmp(x5t, json_string_value(ex5t)) == 0) {
493
 
                                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
494
 
                                                "oidc_proto_get_key_from_jwks: found matching x5t: \"%s\"",
495
 
                                                x5t);
 
504
                                oidc_debug(r, "found matching x5t: \"%s\"", x5t);
496
505
 
497
506
                                apr_jwk_parse_json(r->pool, elem, NULL, result);
498
507
                                break;
516
525
        /* get the set of JSON Web Keys for this provider (possibly by downloading them from the specified provider->jwk_uri) */
517
526
        oidc_metadata_jwks_get(r, cfg, provider, &j_jwks, refresh);
518
527
        if (j_jwks == NULL) {
519
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
520
 
                                "oidc_proto_get_key_from_jwk_uri: could not resolve JSON Web Keys");
 
528
                oidc_error(r, "could not resolve JSON Web Keys");
521
529
                return NULL;
522
530
        }
523
531
 
532
540
 
533
541
                /* we did not get a key, but we have not refreshed the JWKs from the jwks_uri yet */
534
542
 
535
 
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
536
 
                                "oidc_proto_get_key_from_jwk_uri: could not find a key in the cached JSON Web Keys, doing a forced refresh");
 
543
                oidc_warn(r,
 
544
                                "could not find a key in the cached JSON Web Keys, doing a forced refresh");
537
545
 
538
546
                /* get the set of JSON Web Keys for this provider forcing a fresh download from the specified provider->jwk_uri) */
539
547
                *refresh = TRUE;
540
548
                oidc_metadata_jwks_get(r, cfg, provider, &j_jwks, refresh);
541
549
                if (j_jwks == NULL) {
542
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
543
 
                                        "oidc_proto_get_key_from_jwk_uri: could not refresh JSON Web Keys");
 
550
                        oidc_error(r, "could not refresh JSON Web Keys");
544
551
                        return NULL;
545
552
                }
546
553
 
567
574
 
568
575
        if (apr_jws_signature_is_hmac(r->pool, jwt)) {
569
576
 
570
 
                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
571
 
                                "oidc_proto_idtoken_verify_signature: verifying HMAC signature on id_token: header=%s, message=%s",
 
577
                oidc_debug(r,
 
578
                                "verifying HMAC signature on id_token: header=%s, message=%s",
572
579
                                jwt->header.value.str, jwt->message);
573
580
 
574
581
                result = apr_jws_verify_hmac(r->pool, jwt, provider->client_secret,
587
594
 
588
595
                if (jwk != NULL) {
589
596
 
590
 
                        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
591
 
                                        "oidc_proto_idtoken_verify_signature: verifying RSA/EC signature on id_token: header=%s, message=%s",
 
597
                        oidc_debug(r,
 
598
                                        "verifying RSA/EC signature on id_token: header=%s, message=%s",
592
599
                                        jwt->header.value.str, jwt->message);
593
600
 
594
601
                        result =
602
609
 
603
610
                } else {
604
611
 
605
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
606
 
                                        "oidc_proto_idtoken_verify_signature: could not find a key in the JSON Web Keys");
 
612
                        oidc_warn(r, "could not find a key in the JSON Web Keys");
607
613
 
608
614
                        if (*refresh == FALSE) {
609
615
 
610
 
                                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
611
 
                                                "oidc_proto_idtoken_verify_signature: force refresh of the JWKS");
 
616
                                oidc_debug(r, "force refresh of the JWKS");
612
617
 
613
618
                                /* do it again, forcing a JWKS refresh */
614
619
                                *refresh = TRUE;
619
624
 
620
625
        } else {
621
626
 
622
 
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
623
 
                                "oidc_proto_idtoken_verify_signature: cannot verify id_token; unsupported algorithm \"%s\", must be RSA or HMAC",
 
627
                oidc_warn(r,
 
628
                                "cannot verify id_token; unsupported algorithm \"%s\", must be RSA or HMAC",
624
629
                                jwt->header.alg);
625
630
 
626
631
        }
627
632
 
628
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
629
 
                        "oidc_proto_idtoken_verify_signature: verification result of signature with algorithm \"%s\": %s",
 
633
        oidc_debug(r, "verification result of signature with algorithm \"%s\": %s",
630
634
                        jwt->header.alg, (result == TRUE) ? "TRUE" : "FALSE");
631
635
 
632
636
        return result;
655
659
        apr_jwt_get_string(r->pool, &jwt->payload.value, claim_name, &username);
656
660
 
657
661
        if (username == NULL) {
658
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
659
 
                                "oidc_proto_set_remote_user: OIDCRemoteUserClaim is set to \"%s\", but the id_token JSON payload did not contain a \"%s\" string",
 
662
                oidc_error(r,
 
663
                                "OIDCRemoteUserClaim is set to \"%s\", but the id_token JSON payload did not contain a \"%s\" string",
660
664
                                c->remote_user_claim, claim_name);
661
665
                return FALSE;
662
666
        }
666
670
                        apr_psprintf(r->pool, "%s@%s", username, issuer) :
667
671
                        apr_pstrdup(r->pool, username);
668
672
 
669
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
670
 
                        "oidc_proto_set_remote_user: set remote_user to %s", *user);
 
673
        oidc_debug(r, "set remote_user to \"%s\"", *user);
671
674
 
672
675
        return TRUE;
673
676
}
679
682
                oidc_provider_t *provider, const char *id_token, const char *nonce,
680
683
                char **user, apr_jwt_t **jwt, apr_byte_t is_code_flow) {
681
684
 
682
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
683
 
                        "oidc_proto_parse_idtoken: entering");
 
685
        oidc_debug(r, "enter");
684
686
 
685
687
        if (apr_jwt_parse(r->pool, id_token, jwt, cfg->private_keys,
686
688
                        provider->client_secret) == FALSE) {
687
689
                if ((*jwt) && ((*jwt)->header.alg)
688
690
                                && (apr_jwe_algorithm_is_supported(r->pool, (*jwt)->header.alg)
689
691
                                                == FALSE)) {
690
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
691
 
                                        "oidc_proto_parse_idtoken: JWE content key encryption algorithm is not supported: %s",
 
692
                        oidc_error(r,
 
693
                                        "JWE content key encryption algorithm is not supported: %s",
692
694
                                        (*jwt)->header.alg);
693
695
                }
694
696
                if ((*jwt) && ((*jwt)->header.enc)
695
697
                                && (apr_jwe_encryption_is_supported(r->pool, (*jwt)->header.enc)
696
698
                                                == FALSE)) {
697
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
698
 
                                        "oidc_proto_parse_idtoken: JWE encryption type is not supported: %s",
 
699
                        oidc_error(r, "JWE encryption type is not supported: %s",
699
700
                                        (*jwt)->header.enc);
700
701
                }
701
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
702
 
                                "oidc_proto_parse_idtoken: apr_jwt_parse failed for JWT with header: \"%s\"",
 
702
                oidc_error(r, "apr_jwt_parse failed for JWT with header: \"%s\"",
703
703
                                apr_jwt_header_to_string(r->pool, id_token));
704
704
                apr_jwt_destroy(*jwt);
705
705
                return FALSE;
706
706
        }
707
707
 
708
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
709
 
                        "oidc_proto_parse_idtoken: successfully parsed (and possibly decrypted) JWT with header: \"%s\"",
 
708
        oidc_debug(r,
 
709
                        "successfully parsed (and possibly decrypted) JWT with header: \"%s\"",
710
710
                        apr_jwt_header_to_string(r->pool, id_token));
711
711
 
712
712
        // make signature validation exception for 'code' flow and the algorithm NONE
715
715
                apr_byte_t refresh = FALSE;
716
716
                if (oidc_proto_idtoken_verify_signature(r, cfg, provider, *jwt,
717
717
                                &refresh) == FALSE) {
718
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
719
 
                                        "oidc_proto_parse_idtoken: id_token signature could not be validated, aborting");
 
718
                        oidc_error(r,
 
719
                                        "id_token signature could not be validated, aborting");
720
720
                        apr_jwt_destroy(*jwt);
721
721
                        return FALSE;
722
722
                }
724
724
 
725
725
        /* this is where the meat is */
726
726
        if (oidc_proto_validate_idtoken(r, provider, *jwt, nonce) == FALSE) {
727
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
728
 
                                "oidc_proto_parse_idtoken: id_token payload could not be validated, aborting");
 
727
                oidc_error(r, "id_token payload could not be validated, aborting");
729
728
                apr_jwt_destroy(*jwt);
730
729
                return FALSE;
731
730
        }
732
731
 
733
732
        if (oidc_proto_set_remote_user(r, cfg, provider, *jwt, user) == FALSE) {
734
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
735
 
                                "oidc_proto_parse_idtoken: remote user could not be set, aborting");
 
733
                oidc_error(r, "remote user could not be set, aborting");
736
734
                apr_jwt_destroy(*jwt);
737
735
                return FALSE;
738
736
        }
739
737
 
740
738
        /* log our results */
741
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
742
 
                        "oidc_proto_parse_idtoken: valid id_token for user \"%s\" (expires in %" APR_TIME_T_FMT " seconds)",
 
739
        oidc_debug(r,
 
740
                        "valid id_token for user \"%s\" (expires in %" APR_TIME_T_FMT " seconds)",
743
741
                        *user, (*jwt)->payload.exp - apr_time_sec(apr_time_now()));
744
742
 
745
743
        /* since we've made it so far, we may as well say it is a valid id_token */
754
752
        /*  we only support bearer/Bearer  */
755
753
        if ((token_type != NULL) && (apr_strnatcasecmp(token_type, "Bearer") != 0)
756
754
                        && (provider->userinfo_endpoint_url != NULL)) {
757
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
758
 
                                "oidc_proto_check_token_type: token_type is \"%s\" and UserInfo endpoint (%s) for issuer \"%s\" is set: can only deal with Bearer authentication against a UserInfo endpoint!",
 
755
                oidc_error(r,
 
756
                                "token_type is \"%s\" and UserInfo endpoint (%s) for issuer \"%s\" is set: can only deal with Bearer authentication against a UserInfo endpoint!",
759
757
                                token_type, provider->userinfo_endpoint_url, provider->issuer);
760
758
                return FALSE;
761
759
        }
769
767
                oidc_provider_t *provider, const char *code, char **s_idtoken,
770
768
                char **s_access_token, char **s_token_type) {
771
769
 
772
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
773
 
                        "oidc_proto_resolve_code: entering");
 
770
        oidc_debug(r, "enter");
774
771
        const char *response = NULL;
775
772
 
776
773
        /* assemble the parameters for a call to the token endpoint */
781
778
 
782
779
        /* see if we need to do basic auth or auth-through-post-params (both applied through the HTTP POST method though) */
783
780
        const char *basic_auth = NULL;
784
 
        if ((apr_strnatcmp(provider->token_endpoint_auth, "client_secret_basic"))
785
 
                        == 0) {
 
781
        if ((provider->token_endpoint_auth == NULL)
 
782
                        || (apr_strnatcmp(provider->token_endpoint_auth,
 
783
                                        "client_secret_basic") == 0)) {
786
784
                basic_auth = apr_psprintf(r->pool, "%s:%s", provider->client_id,
787
785
                                provider->client_secret);
788
786
        } else {
790
788
                apr_table_addn(params, "client_secret", provider->client_secret);
791
789
        }
792
790
 
793
 
        /*
794
 
         if (strcmp(provider->issuer, "https://sts.windows.net/b4ea3de6-839e-4ad1-ae78-c78e5c0cdc06/") == 0) {
795
 
         apr_table_addn(params, "resource", "https://graph.windows.net");
796
 
         }
797
 
         */
 
791
        /* see if we've configured any extra static parameters to the token endpoint */
 
792
        if (provider->token_endpoint_params != NULL) {
 
793
                const char *key, *val;
 
794
                const char *p = provider->token_endpoint_params;
 
795
                while (*p && (val = ap_getword(r->pool, &p, '&'))) {
 
796
                        key = ap_getword(r->pool, &val, '=');
 
797
                        ap_unescape_url((char *) key);
 
798
                        ap_unescape_url((char *) val);
 
799
                        apr_table_addn(params, key, val);
 
800
                }
 
801
        }
798
802
 
799
803
        /* resolve the code against the token endpoint */
800
804
        if (oidc_util_http_post_form(r, provider->token_endpoint_url, params,
801
805
                        basic_auth, NULL, provider->ssl_validate_server, &response,
802
806
                        cfg->http_timeout_long, cfg->outgoing_proxy) == FALSE) {
803
 
                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
804
 
                                "oidc_proto_resolve_code: could not successfully resolve the \"code\" (%s) against the token endpoint (%s)",
 
807
                oidc_warn(r,
 
808
                                "could not successfully resolve the \"code\" (%s) against the token endpoint (%s)",
805
809
                                code, provider->token_endpoint_url);
806
810
                return FALSE;
807
811
        }
818
822
                *s_access_token = apr_pstrdup(r->pool, json_string_value(access_token));
819
823
 
820
824
                /* log and set the obtained acces_token */
821
 
                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
822
 
                                "oidc_proto_resolve_code: returned access_token: %s",
823
 
                                *s_access_token);
 
825
                oidc_debug(r, "returned access_token: %s", *s_access_token);
824
826
 
825
827
                /* the provider must return the token type */
826
828
                json_t *token_type = json_object_get(result, "token_type");
827
829
                if ((token_type == NULL) || (!json_is_string(token_type))) {
828
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
829
 
                                        "oidc_proto_resolve_code: response JSON object did not contain a token_type string");
 
830
                        oidc_error(r,
 
831
                                        "response JSON object did not contain a token_type string");
830
832
                        json_decref(result);
831
833
                        return FALSE;
832
834
                }
834
836
                *s_token_type = apr_pstrdup(r->pool, json_string_value(token_type));
835
837
 
836
838
        } else {
837
 
                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
838
 
                                "oidc_proto_resolve_code: response JSON object did not contain an access_token string");
 
839
                oidc_debug(r,
 
840
                                "response JSON object did not contain an access_token string");
839
841
        }
840
842
 
841
843
        /* get the id_token from the response */
844
846
                *s_idtoken = apr_pstrdup(r->pool, json_string_value(id_token));
845
847
 
846
848
                /* log and set the obtained id_token */
847
 
                ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
848
 
                                "oidc_proto_resolve_code: returned id_token: %s", *s_idtoken);
 
849
                oidc_debug(r, "returned id_token: %s", *s_idtoken);
849
850
        }
850
851
 
851
852
        json_decref(result);
860
861
                oidc_provider_t *provider, const char *access_token,
861
862
                const char **response, json_t **claims) {
862
863
 
863
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
864
 
                        "oidc_resolve_userinfo: entering, endpoint=%s, access_token=%s",
 
864
        oidc_debug(r, "enter, endpoint=%s, access_token=%s",
865
865
                        provider->userinfo_endpoint_url, access_token);
866
866
 
867
 
        /* only do this if an actual endpoint was set */
868
 
        if (provider->userinfo_endpoint_url == NULL)
869
 
                return FALSE;
870
 
 
871
 
        /* only do this if we have an access_token */
872
 
        if (access_token == NULL)
873
 
                return FALSE;
874
 
 
875
867
        /* get the JSON response */
876
868
        if (oidc_util_http_get(r, provider->userinfo_endpoint_url,
877
869
                        NULL, NULL, access_token, provider->ssl_validate_server, response,
890
882
 
891
883
        // TODO: maybe show intermediate/progress screen "discovering..."
892
884
 
893
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
894
 
                        "oidc_proto_account_based_discovery: entering, acct=%s", acct);
 
885
        oidc_debug(r, "enter, acct=%s", acct);
895
886
 
896
887
        const char *resource = apr_psprintf(r->pool, "acct:%s", acct);
897
888
        const char *domain = strrchr(acct, '@');
898
889
        if (domain == NULL) {
899
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
900
 
                                "oidc_proto_account_based_discovery: invalid account name");
 
890
                oidc_error(r, "invalid account name");
901
891
                return FALSE;
902
892
        }
903
893
        domain++;
924
914
        /* get the links parameter */
925
915
        json_t *j_links = json_object_get(j_response, "links");
926
916
        if ((j_links == NULL) || (!json_is_array(j_links))) {
927
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
928
 
                                "oidc_proto_account_based_discovery: response JSON object did not contain a \"links\" array");
 
917
                oidc_error(r, "response JSON object did not contain a \"links\" array");
929
918
                json_decref(j_response);
930
919
                return FALSE;
931
920
        }
933
922
        /* get the one-and-only object in the "links" array */
934
923
        json_t *j_object = json_array_get(j_links, 0);
935
924
        if ((j_object == NULL) || (!json_is_object(j_object))) {
936
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
937
 
                                "oidc_proto_account_based_discovery: response JSON object did not contain a JSON object as the first element in the \"links\" array");
 
925
                oidc_error(r,
 
926
                                "response JSON object did not contain a JSON object as the first element in the \"links\" array");
938
927
                json_decref(j_response);
939
928
                return FALSE;
940
929
        }
942
931
        /* get the href from that object, which is the issuer value */
943
932
        json_t *j_href = json_object_get(j_object, "href");
944
933
        if ((j_href == NULL) || (!json_is_string(j_href))) {
945
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
946
 
                                "oidc_proto_account_based_discovery: response JSON object did not contain a \"href\" element in the first \"links\" array object");
 
934
                oidc_error(r,
 
935
                                "response JSON object did not contain a \"href\" element in the first \"links\" array object");
947
936
                json_decref(j_response);
948
937
                return FALSE;
949
938
        }
950
939
 
951
940
        *issuer = apr_pstrdup(r->pool, json_string_value(j_href));
952
941
 
953
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
954
 
                        "oidc_proto_account_based_discovery: returning issuer \"%s\" for account \"%s\" after doing successful webfinger-based discovery",
 
942
        oidc_debug(r,
 
943
                        "returning issuer \"%s\" for account \"%s\" after doing successful webfinger-based discovery",
955
944
                        *issuer, acct);
956
945
 
957
946
        json_decref(j_response);
961
950
 
962
951
int oidc_proto_javascript_implicit(request_rec *r, oidc_cfg *c) {
963
952
 
964
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
965
 
                        "oidc_proto_javascript_implicit: entering");
 
953
        oidc_debug(r, "enter");
966
954
 
967
955
//      char *java_script = NULL;
968
956
//      if (oidc_util_file_read(r, "/Users/hzandbelt/eclipse-workspace/mod_auth_openidc/src/implicit_post.html", &java_script) == FALSE) return HTTP_INTERNAL_SERVER_ERROR;
969
957
 
970
958
        const char *java_script =
971
959
                        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
 
960
                                        "<html>\n"
972
961
                                        "  <head>\n"
973
 
                                        "  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
 
962
                                        "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
974
963
                                        "    <script type=\"text/javascript\">\n"
975
964
                                        "      function postOnLoad() {\n"
976
965
                                        "        encoded = location.hash.substring(1).split('&');\n"
995
984
                                        "  </body>\n"
996
985
                                        "</html>\n";
997
986
 
998
 
        return oidc_util_http_sendstring(r, java_script, DONE);
 
987
        return oidc_util_html_send(r, java_script, DONE);
999
988
}
1000
989
 
1001
990
/*
1011
1000
 
1012
1001
        /* calculate the base64url-encoded value of the hash */
1013
1002
        char *encoded = NULL;
1014
 
        oidc_base64url_encode(r, &encoded, calc,
1015
 
                        apr_jws_hash_length(alg) / 2, 1);
 
1003
        oidc_base64url_encode(r, &encoded, calc, apr_jws_hash_length(alg) / 2, 1);
1016
1004
 
1017
1005
        /* compare the calculated hash against the provided hash */
1018
1006
        if ((apr_strnatcmp(encoded, hash) != 0)) {
1019
 
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1020
 
                                "oidc_proto_validate_hash: provided \"%s\" hash value (%s) does not match the calculated value (%s)",
 
1007
                oidc_error(r,
 
1008
                                "provided \"%s\" hash value (%s) does not match the calculated value (%s)",
1021
1009
                                type, hash, encoded);
1022
1010
                return FALSE;
1023
1011
        }
1024
1012
 
1025
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
1026
 
                        "oidc_proto_validate_hash: successfully validated the provided \"%s\" hash value (%s) against the calculated value (%s)",
 
1013
        oidc_debug(r,
 
1014
                        "successfully validated the provided \"%s\" hash value (%s) against the calculated value (%s)",
1027
1015
                        type, hash, encoded);
1028
1016
 
1029
1017
        return TRUE;
1053
1041
                for (i = 0; i < required_for_flows->nelts; i++) {
1054
1042
                        if (oidc_util_spaced_string_equals(r->pool, response_type,
1055
1043
                                        ((const char**) required_for_flows->elts)[i])) {
1056
 
                                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1057
 
                                                "oidc_proto_validate_hash_value: flow is \"%s\", but no %s found in id_token",
 
1044
                                oidc_warn(r, "flow is \"%s\", but no %s found in id_token",
1058
1045
                                                response_type, key);
1059
1046
                                return FALSE;
1060
1047
                        }
1133
1120
                char **code, char **id_token, char **access_token, char **token_type,
1134
1121
                const char *used_response_mode) {
1135
1122
 
1136
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
1137
 
                        "oidc_proto_validate_authorization_response: entering, response_type=%s, requested_response_mode=%s, code=%s, id_token=%s, access_token=%s, token_type=%s, used_response_mode=%s",
 
1123
        oidc_debug(r,
 
1124
                        "enter, response_type=%s, requested_response_mode=%s, code=%s, id_token=%s, access_token=%s, token_type=%s, used_response_mode=%s",
1138
1125
                        response_type, requested_response_mode, *code, *id_token,
1139
1126
                        *access_token, *token_type, used_response_mode);
1140
1127
 
1145
1132
                 * only warn because I'm not sure that most OPs will respect a requested
1146
1133
                 * response_mode and rather use the default for the flow
1147
1134
                 */
1148
 
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1149
 
                                "oidc_proto_validate_authorization_response: requested response_mode is \"%s\" the provider used \"%s\" for the authorization response...",
 
1135
                oidc_warn(r,
 
1136
                                "requested response_mode is \"%s\" the provider used \"%s\" for the authorization response...",
1150
1137
                                requested_response_mode, used_response_mode);
1151
1138
        }
1152
1139
 
1156
1143
        if (oidc_util_spaced_string_contains(r->pool, response_type, "code")) {
1157
1144
 
1158
1145
                if (*code == NULL) {
1159
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1160
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but no \"code\" parameter found in the authorization response",
 
1146
                        oidc_error(r,
 
1147
                                        "requested flow is \"%s\" but no \"code\" parameter found in the authorization response",
1161
1148
                                        response_type);
1162
1149
                        return FALSE;
1163
1150
                }
1165
1152
        } else {
1166
1153
 
1167
1154
                if (*code != NULL) {
1168
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1169
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but there is a \"code\" parameter in the authorization response that will be dropped",
 
1155
                        oidc_warn(r,
 
1156
                                        "requested flow is \"%s\" but there is a \"code\" parameter in the authorization response that will be dropped",
1170
1157
                                        response_type);
1171
1158
                        *code = NULL;
1172
1159
                }
1178
1165
        if (oidc_util_spaced_string_contains(r->pool, response_type, "id_token")) {
1179
1166
 
1180
1167
                if (*id_token == NULL) {
1181
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1182
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but no \"id_token\" parameter found in the authorization response",
 
1168
                        oidc_error(r,
 
1169
                                        "requested flow is \"%s\" but no \"id_token\" parameter found in the authorization response",
1183
1170
                                        response_type);
1184
1171
                        return FALSE;
1185
1172
                }
1187
1174
        } else {
1188
1175
 
1189
1176
                if (*id_token != NULL) {
1190
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1191
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but there is an \"id_token\" parameter in the authorization response that will be dropped",
 
1177
                        oidc_warn(r,
 
1178
                                        "requested flow is \"%s\" but there is an \"id_token\" parameter in the authorization response that will be dropped",
1192
1179
                                        response_type);
1193
1180
                        *id_token = NULL;
1194
1181
                }
1201
1188
        if (oidc_util_spaced_string_contains(r->pool, response_type, "token")) {
1202
1189
 
1203
1190
                if (*access_token == NULL) {
1204
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1205
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but no \"access_token\" parameter found in the authorization response",
 
1191
                        oidc_error(r,
 
1192
                                        "requested flow is \"%s\" but no \"access_token\" parameter found in the authorization response",
1206
1193
                                        response_type);
1207
1194
                        return FALSE;
1208
1195
                }
1209
1196
 
1210
1197
                if (*token_type == NULL) {
1211
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1212
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but no \"token_type\" parameter found in the authorization response",
 
1198
                        oidc_error(r,
 
1199
                                        "requested flow is \"%s\" but no \"token_type\" parameter found in the authorization response",
1213
1200
                                        response_type);
1214
1201
                        return FALSE;
1215
1202
                }
1217
1204
        } else {
1218
1205
 
1219
1206
                if (*access_token != NULL) {
1220
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1221
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but there is an \"access_token\" parameter in the authorization response that will be dropped",
 
1207
                        oidc_warn(r,
 
1208
                                        "requested flow is \"%s\" but there is an \"access_token\" parameter in the authorization response that will be dropped",
1222
1209
                                        response_type);
1223
1210
                        *access_token = NULL;
1224
1211
                }
1225
1212
 
1226
1213
                if (*token_type != NULL) {
1227
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1228
 
                                        "oidc_proto_validate_authorization_response: requested flow is \"%s\" but there is a \"token_type\" parameter in the authorization response that will be dropped",
 
1214
                        oidc_warn(r,
 
1215
                                        "requested flow is \"%s\" but there is a \"token_type\" parameter in the authorization response that will be dropped",
1229
1216
                                        response_type);
1230
1217
                        *token_type = NULL;
1231
1218
                }
1242
1229
                const char *response_type, char **id_token, char **access_token,
1243
1230
                char **token_type) {
1244
1231
 
1245
 
        ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
1246
 
                        "oidc_proto_validate_code_response: entering");
 
1232
        oidc_debug(r, "enter");
1247
1233
 
1248
1234
        /*
1249
1235
         * check id_token parameter
1251
1237
        if (!oidc_util_spaced_string_contains(r->pool, response_type, "id_token")) {
1252
1238
 
1253
1239
                if (*id_token == NULL) {
1254
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1255
 
                                        "oidc_proto_validate_code_response: requested flow is \"%s\" but no \"id_token\" parameter found in the code response",
 
1240
                        oidc_error(r,
 
1241
                                        "requested flow is \"%s\" but no \"id_token\" parameter found in the code response",
1256
1242
                                        response_type);
1257
1243
                        return FALSE;
1258
1244
                }
1260
1246
        } else {
1261
1247
 
1262
1248
                if (*id_token != NULL) {
1263
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1264
 
                                        "oidc_proto_validate_code_response: requested flow is \"%s\" but there is an \"id_token\" parameter in the code response that will be dropped",
 
1249
                        oidc_warn(r,
 
1250
                                        "requested flow is \"%s\" but there is an \"id_token\" parameter in the code response that will be dropped",
1265
1251
                                        response_type);
1266
1252
                        *id_token = NULL;
1267
1253
                }
1274
1260
        if (!oidc_util_spaced_string_contains(r->pool, response_type, "token")) {
1275
1261
 
1276
1262
                if (*access_token == NULL) {
1277
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1278
 
                                        "oidc_proto_validate_code_response: requested flow is \"%s\" but no \"access_token\" parameter found in the code response",
 
1263
                        oidc_error(r,
 
1264
                                        "requested flow is \"%s\" but no \"access_token\" parameter found in the code response",
1279
1265
                                        response_type);
1280
1266
                        return FALSE;
1281
1267
                }
1282
1268
 
1283
1269
                if (*token_type == NULL) {
1284
 
                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1285
 
                                        "oidc_proto_validate_code_response: requested flow is \"%s\" but no \"token_type\" parameter found in the code response",
 
1270
                        oidc_error(r,
 
1271
                                        "requested flow is \"%s\" but no \"token_type\" parameter found in the code response",
1286
1272
                                        response_type);
1287
1273
                        return FALSE;
1288
1274
                }
1290
1276
        } else {
1291
1277
 
1292
1278
                if (*access_token != NULL) {
1293
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1294
 
                                        "oidc_proto_validate_code_response: requested flow is \"%s\" but there is an \"access_token\" parameter in the code response that will be dropped",
 
1279
                        oidc_warn(r,
 
1280
                                        "requested flow is \"%s\" but there is an \"access_token\" parameter in the code response that will be dropped",
1295
1281
                                        response_type);
1296
1282
                        *access_token = NULL;
1297
1283
                }
1298
1284
 
1299
1285
                if (*token_type != NULL) {
1300
 
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
1301
 
                                        "oidc_proto_validate_code_response: requested flow is \"%s\" but there is a \"token_type\" parameter in the code response that will be dropped",
 
1286
                        oidc_warn(r,
 
1287
                                        "requested flow is \"%s\" but there is a \"token_type\" parameter in the code response that will be dropped",
1302
1288
                                        response_type);
1303
1289
                        *token_type = NULL;
1304
1290
                }