/* * validate an access token against the validation endpoint of the Authorization server and gets a response back */ static int oidc_oauth_validate_access_token(request_rec *r, oidc_cfg *c, const char *token, const char **response) { /* get a handle to the directory config */ oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config, &auth_openidc_module); /* assemble parameters to call the token endpoint for validation */ apr_table_t *params = apr_table_make(r->pool, 4); /* add any configured extra static parameters to the introspection endpoint */ oidc_util_table_add_query_encoded_params(r->pool, params, c->oauth.introspection_endpoint_params); /* add the access_token itself */ apr_table_addn(params, "token", token); /* see if we want to do basic auth or post-param-based auth */ const char *basic_auth = NULL; if ((c->oauth.introspection_endpoint_auth != NULL) && (apr_strnatcmp(c->oauth.introspection_endpoint_auth, "client_secret_post") == 0)) { apr_table_addn(params, "client_id", c->oauth.client_id); apr_table_addn(params, "client_secret", c->oauth.client_secret); } else { basic_auth = apr_psprintf(r->pool, "%s:%s", c->oauth.client_id, c->oauth.client_secret); } /* call the endpoint with the constructed parameter set and return the resulting response */ return oidc_util_http_post_form(r, c->oauth.introspection_endpoint_url, params, basic_auth, NULL, c->oauth.ssl_validate_server, response, c->http_timeout_long, c->outgoing_proxy, dir_cfg->pass_cookies); }
/* * send a code/refresh request to the token endpoint and return the parsed contents */ static apr_byte_t oidc_proto_token_endpoint_request(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, apr_table_t *params, char **id_token, char **access_token, char **token_type, int *expires_in, char **refresh_token) { const char *response = NULL; /* see if we need to do basic auth or auth-through-post-params (both applied through the HTTP POST method though) */ const char *basic_auth = NULL; if ((provider->token_endpoint_auth == NULL) || (apr_strnatcmp(provider->token_endpoint_auth, "client_secret_basic") == 0)) { basic_auth = apr_psprintf(r->pool, "%s:%s", provider->client_id, provider->client_secret); } else { apr_table_addn(params, "client_id", provider->client_id); apr_table_addn(params, "client_secret", provider->client_secret); } /* add any configured extra static parameters to the token endpoint */ oidc_util_table_add_query_encoded_params(r->pool, params, provider->token_endpoint_params); /* send the refresh request to the token endpoint */ if (oidc_util_http_post_form(r, provider->token_endpoint_url, params, basic_auth, NULL, provider->ssl_validate_server, &response, cfg->http_timeout_long, cfg->outgoing_proxy) == FALSE) { oidc_warn(r, "error when calling the token endpoint (%s)", provider->token_endpoint_url); return FALSE; } /* check for errors, the response itself will have been logged already */ json_t *result = NULL; if (oidc_util_decode_json_and_check_error(r, response, &result) == FALSE) return FALSE; /* get the id_token from the parsed response */ oidc_json_object_get_string(r->pool, result, "id_token", id_token, NULL); /* get the access_token from the parsed response */ oidc_json_object_get_string(r->pool, result, "access_token", access_token, NULL); /* get the token type from the parsed response */ oidc_json_object_get_string(r->pool, result, "token_type", token_type, NULL); /* check the new token type */ if (token_type != NULL) { if (oidc_proto_validate_token_type(r, provider, *token_type) == FALSE) { oidc_warn(r, "access token type did not validate, dropping it"); *access_token = NULL; } } /* get the expires_in value */ oidc_json_object_get_int(r->pool, result, "expires_in", expires_in, -1); /* get the refresh_token from the parsed response */ oidc_json_object_get_string(r->pool, result, "refresh_token", refresh_token, NULL); json_decref(result); return TRUE; }
/* * resolves the code received from the OP in to an access_token and id_token and returns the parsed contents */ apr_byte_t oidc_proto_resolve_code(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *code, char **s_idtoken, char **s_access_token, char **s_token_type) { ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: entering"); const char *response = NULL; /* assemble the parameters for a call to the token endpoint */ apr_table_t *params = apr_table_make(r->pool, 5); apr_table_addn(params, "grant_type", "authorization_code"); apr_table_addn(params, "code", code); apr_table_addn(params, "redirect_uri", cfg->redirect_uri); /* see if we need to do basic auth or auth-through-post-params (both applied through the HTTP POST method though) */ const char *basic_auth = NULL; if ((apr_strnatcmp(provider->token_endpoint_auth, "client_secret_basic")) == 0) { basic_auth = apr_psprintf(r->pool, "%s:%s", provider->client_id, provider->client_secret); } else { apr_table_addn(params, "client_id", provider->client_id); apr_table_addn(params, "client_secret", provider->client_secret); } /* see if we've configured any extra static parameters to the token endpoint */ if (provider->token_endpoint_params != NULL) { const char *key, *val; const char *p = provider->token_endpoint_params; while (*p && (val = ap_getword(r->pool, &p, '&'))) { key = ap_getword(r->pool, &val, '='); ap_unescape_url((char *) key); ap_unescape_url((char *) val); apr_table_addn(params, key, val); } } /* resolve the code against the token endpoint */ if (oidc_util_http_post_form(r, provider->token_endpoint_url, params, basic_auth, NULL, provider->ssl_validate_server, &response, cfg->http_timeout_long, cfg->outgoing_proxy) == FALSE) { ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: could not successfully resolve the \"code\" (%s) against the token endpoint (%s)", code, provider->token_endpoint_url); return FALSE; } /* check for errors, the response itself will have been logged already */ json_t *result = NULL; if (oidc_util_decode_json_and_check_error(r, response, &result) == FALSE) return FALSE; /* get the access_token from the parsed response */ json_t *access_token = json_object_get(result, "access_token"); if ((access_token != NULL) && (json_is_string(access_token))) { *s_access_token = apr_pstrdup(r->pool, json_string_value(access_token)); /* log and set the obtained acces_token */ ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: returned access_token: %s", *s_access_token); /* the provider must return the token type */ json_t *token_type = json_object_get(result, "token_type"); if ((token_type == NULL) || (!json_is_string(token_type))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "oidc_proto_resolve_code: response JSON object did not contain a token_type string"); json_decref(result); return FALSE; } *s_token_type = apr_pstrdup(r->pool, json_string_value(token_type)); } else { ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: response JSON object did not contain an access_token string"); } /* get the id_token from the response */ json_t *id_token = json_object_get(result, "id_token"); if ((id_token != NULL) && (json_is_string(id_token))) { *s_idtoken = apr_pstrdup(r->pool, json_string_value(id_token)); /* log and set the obtained id_token */ ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: returned id_token: %s", *s_idtoken); } json_decref(result); return TRUE; }