]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: oauth2 - Support passing openid-configuration URL to client on failure
authorAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 10 May 2021 19:37:44 +0000 (22:37 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 21 May 2021 19:31:46 +0000 (19:31 +0000)
doc/example-config/dovecot-oauth2.conf.ext
src/auth/auth-request.h
src/auth/db-oauth2.c
src/auth/mech-oauth2.c

index 2ac31a0dfc8040674034ff7600cc743c0a6a4bc6..4b3b8baf795a16b9bbe24bcd3d4903bf4acdbdd5 100644 (file)
@@ -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 =
 
index b3ff52996c8c461400f3ec99ed19e0eac33835e1..c77b271c4b6e9a7c91a94908758b5579448c0d54 100644 (file)
@@ -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;
index 9f94b20a43772e1be28db36b2fb3c7d9e4779157..68946d5ef2059fe9d411f7b3f46d65d8754484f3 100644 (file)
@@ -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) {
index db0c24346be9d72149e971697976215da55680b0..180b99fc3665140891d5b6910ca8abd452c69930 100644 (file)
@@ -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));