]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
oauth: Accept multiple entries in aud field
authorMarco Bettini <marco.bettini@open-xchange.com>
Tue, 3 Oct 2023 13:11:49 +0000 (13:11 +0000)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 5 Oct 2023 11:45:56 +0000 (11:45 +0000)
src/auth/db-oauth2.c
src/lib-oauth2/oauth2-jwt.c

index b36a4ced3f98bd070b0701247da7aed37f4f611a..d5ef6041886aca97790cf02e0ca31b2ecb76e1f5 100644 (file)
@@ -3,6 +3,7 @@
 #include "auth-common.h"
 #include "array.h"
 #include "str.h"
+#include "strescape.h"
 #include "var-expand.h"
 #include "env-util.h"
 #include "var-expand.h"
@@ -650,7 +651,8 @@ db_oauth2_token_in_scope(struct db_oauth2_request *req,
        if (*req->db->set.scope != '\0') {
                bool found = FALSE;
                const char *value = auth_fields_find(req->fields, "scope");
-               if (value == NULL)
+               bool has_scope = value != NULL;
+               if (!has_scope)
                        value = auth_fields_find(req->fields, "aud");
                e_debug(authdb_event(req->auth_request),
                        "Token scope(s): %s",
@@ -658,9 +660,11 @@ db_oauth2_token_in_scope(struct db_oauth2_request *req,
                if (value != NULL) {
                        const char **wanted_scopes =
                                t_strsplit_spaces(req->db->set.scope, " ");
-                       const char **scopes = t_strsplit_spaces(value, " ");
+                       const char *const *entries = has_scope ?
+                               t_strsplit_spaces(value, " ") :
+                               t_strsplit_tabescaped(value);
                        for (; !found && *wanted_scopes != NULL; wanted_scopes++)
-                               found = str_array_find(scopes, *wanted_scopes);
+                               found = str_array_find(entries, *wanted_scopes);
                }
                if (!found) {
                        *error_r = t_strdup_printf("Token is not valid for scope '%s'",
index bc7779fe1d1b127296237c1d15fcbbb34250aaa2..04db602e9d45b00e97472d57a433c72742aaab39 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "buffer.h"
 #include "str.h"
+#include "strescape.h"
 #include "hmac.h"
 #include "array.h"
 #include "hash-method.h"
@@ -30,6 +31,29 @@ static const char *get_field(const struct json_tree *tree, const char *key)
        return json_tree_get_value_str(value_node);
 }
 
+static const char *get_field_multiple(const struct json_tree *tree, const char *key)
+{
+       const struct json_tree_node *root = json_tree_root(tree);
+       const struct json_tree_node *value_node = json_tree_find_key(root, key);
+       if (value_node == NULL || value_node->value_type == JSON_TYPE_OBJECT)
+               return NULL;
+       if (value_node->value_type != JSON_TYPE_ARRAY)
+               return json_tree_get_value_str(value_node);
+
+       const struct json_tree_node *entry_node = json_tree_get_child(value_node);
+       string_t *values = t_str_new(64);
+       for (; entry_node != NULL; entry_node = entry_node->next) {
+               if (entry_node->value_type == JSON_TYPE_OBJECT ||
+                   entry_node->value_type == JSON_TYPE_ARRAY)
+                       continue;
+               const char *value_str = json_tree_get_value_str(entry_node);
+               if (str_len(values) > 0)
+                       str_append_c(values, '\t');
+               str_append_tabescaped(values, value_str);
+       }
+       return str_c(values);
+}
+
 static int get_time_field(const struct json_tree *tree, const char *key,
                          int64_t *value_r)
 {
@@ -418,7 +442,7 @@ oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg,
                }
        }
 
-       const char *aud = get_field(tree, "aud");
+       const char *aud = get_field_multiple(tree, "aud");
        /* if there is client_id configured, then aud should be present */
        if (set->client_id != NULL && *set->client_id != '\0') {
                if (aud == NULL) {
@@ -426,7 +450,7 @@ oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg,
                        return -1;
 
                }
-               const char *const *auds = t_strsplit_spaces(aud, " ");
+               const char *const *auds = t_strsplit_tabescaped(aud);
                if (!str_array_find(auds, set->client_id)) {
                        *error_r = "client_id not found in aud field";
                        return -1;