From c6de40d420733af6ba5ca73eef42c924aa956a2c Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Mon, 10 May 2021 22:37:44 +0300 Subject: [PATCH] auth: oauth2 - Support passing openid-configuration URL to client on failure --- doc/example-config/dovecot-oauth2.conf.ext | 3 ++ src/auth/auth-request.h | 3 ++ src/auth/db-oauth2.c | 37 ++++++++++++++++++++++ src/auth/mech-oauth2.c | 14 ++++++++ 4 files changed, 57 insertions(+) diff --git a/doc/example-config/dovecot-oauth2.conf.ext b/doc/example-config/dovecot-oauth2.conf.ext index 2ac31a0dfc..4b3b8baf79 100644 --- a/doc/example-config/dovecot-oauth2.conf.ext +++ b/doc/example-config/dovecot-oauth2.conf.ext @@ -39,6 +39,9 @@ ## Expected issuer(s) for the token (space separated list) # issuers = +## URL to RFC 7628 OpenID Provider Configuration Information schema +# openid_configuration_url = + ## Extra fields to set in passdb response (in passdb static style) # pass_attrs = diff --git a/src/auth/auth-request.h b/src/auth/auth-request.h index b3ff52996c..c77b271c4b 100644 --- a/src/auth/auth-request.h +++ b/src/auth/auth-request.h @@ -118,6 +118,9 @@ struct auth_request { struct auth_request_handler *handler; struct auth_master_connection *master; + /* FIXME: Remove this once mech-oauth2 correctly does the processing */ + const char *openid_config_url; + unsigned int connect_uid; unsigned int client_pid; unsigned int id; diff --git a/src/auth/db-oauth2.c b/src/auth/db-oauth2.c index 9f94b20a43..68946d5ef2 100644 --- a/src/auth/db-oauth2.c +++ b/src/auth/db-oauth2.c @@ -9,6 +9,7 @@ #include "settings.h" #include "oauth2.h" #include "http-client.h" +#include "http-url.h" #include "iostream-ssl.h" #include "auth-request.h" #include "auth-settings.h" @@ -54,6 +55,12 @@ struct passdb_oauth2_settings { const char *local_validation_key_dict; /* valid token issuers */ const char *issuers; + /* The URL for a document following the OpenID Provider Configuration + Information schema, see + + https://datatracker.ietf.org/doc/html/rfc7628#section-3.2.2 + */ + const char *openid_configuration_url; /* TLS options */ const char *tls_ca_cert_file; @@ -122,6 +129,7 @@ static struct setting_def setting_defs[] = { DEF_STR(client_id), DEF_STR(client_secret), DEF_STR(issuers), + DEF_STR(openid_configuration_url), DEF_INT(timeout_msecs), DEF_INT(max_idle_time_msecs), DEF_INT(max_parallel_connections), @@ -157,6 +165,7 @@ static struct passdb_oauth2_settings default_oauth2_settings = { .client_id = "", .client_secret = "", .issuers = "", + .openid_configuration_url = "", .pass_attrs = "", .local_validation_key_dict = "", .rawlog_dir = "", @@ -304,6 +313,16 @@ struct db_oauth2 *db_oauth2_init(const char *config_path) db->oauth2_set.issuers = (const char *const *) p_strsplit_spaces(pool, db->set.issuers, " "); + if (*db->set.openid_configuration_url != '\0') { + struct http_url *parsed_url ATTR_UNUSED; + if (http_url_parse(db->set.openid_configuration_url, NULL, 0, + pool_datastack_create(), &parsed_url, + &error) < 0) { + i_fatal("Invalid openid_configuration_url: %s", + error); + } + } + DLLIST_PREPEND(&db_oauth2_head, db); return db; @@ -342,6 +361,21 @@ void db_oauth2_unref(struct db_oauth2 **_db) pool_unref(&db->pool); } +static void +db_oauth2_add_openid_config_url(struct db_oauth2_request *req) +{ + /* FIXME: HORRIBLE HACK - REMOVE ME!!! + It is because the mech has not been implemented properly + that we need to pass the config url in this strange way. + + This **must** be moved to mech-oauth2 once the validation + result et al is handled there. + */ + req->auth_request->openid_config_url = + p_strdup_empty(req->auth_request->pool, + req->db->set.openid_configuration_url); +} + static bool db_oauth2_have_all_fields(struct db_oauth2_request *req) { @@ -507,6 +541,9 @@ static void db_oauth2_callback(struct db_oauth2_request *req, i_assert(result == PASSDB_RESULT_OK || error != NULL); + if (result != PASSDB_RESULT_OK) + db_oauth2_add_openid_config_url(req); + /* Successful lookups were logged by the caller. Failed lookups will be logged either with e_error() or e_info() by the callback. */ if (callback != NULL) { diff --git a/src/auth/mech-oauth2.c b/src/auth/mech-oauth2.c index db0c24346b..180b99fc36 100644 --- a/src/auth/mech-oauth2.c +++ b/src/auth/mech-oauth2.c @@ -70,6 +70,20 @@ static void oauth2_verify_callback(enum passdb_result result, json_append_escaped(error, error_fields[i+1]); str_append_c(error, '"'); } + /* FIXME: HORRIBLE HACK - REMOVE ME!!! + It is because the mech has not been implemented properly + that we need to pass the config url in this strange way. + + This **must** be removed from here and db-oauth2 once the + validation result et al is handled here. + */ + if (request->openid_config_url != NULL) { + if (str_len(error) > 0) + str_append_c(error, ','); + str_printfa(error, "\"openid-configuration\":\""); + json_append_escaped(error, request->openid_config_url); + str_append_c(error, '"'); + } str_append_c(error, '}'); auth_request_handler_reply_continue(request, str_data(error), str_len(error)); -- 2.47.3