]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: sasl-server-mech-oauth2 - Implement backend API for token validation
authorStephan Bosch <stephan.bosch@open-xchange.com>
Tue, 31 Oct 2023 01:48:00 +0000 (02:48 +0100)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 9 Oct 2025 08:41:22 +0000 (08:41 +0000)
src/auth/Makefile.am
src/auth/auth-sasl-mech-oauth2.c
src/auth/auth-sasl-oauth2.h
src/auth/auth-sasl.c
src/auth/sasl-server-mech-oauth2.c
src/auth/sasl-server-oauth2.h
src/auth/sasl-server.h

index 4331791ff71ea7d5a52fc580c630e79114516049..5db3ac24c8f2cd9face37199075c1be9c0f8bb39 100644 (file)
@@ -119,6 +119,7 @@ auth_common_sources = \
        auth-request-var-expand.c \
        auth-sasl-mech-apop.c \
        auth-sasl-mech-dovecot-token.c \
+       auth-sasl-mech-oauth2.c \
        auth-sasl.c \
        auth-settings.c \
        auth-fields.c \
index f8739bf4df09ec784f48a401750182b9694ec050..1409f844c066cc1e8d82aacf5d5428637dae75f2 100644 (file)
@@ -1,25 +1,34 @@
 /* Copyright (c) 2023 Dovecot authors, see the included COPYING file */
 
 #include "auth-common.h"
-#include "auth-sasl.h"
-#include "auth-sasl-oauth2.h"
+#include "str.h"
+#include "strescape.h"
+#include "sasl-server-oauth2.h"
+#include "auth-worker-connection.h"
 #include "auth-request.h"
-
+#include "db-oauth2.h"
+#include "auth-sasl.h"
 #include "auth-sasl-oauth2.h"
 
 /*
  * Token verification
  */
 
+static struct db_oauth2 *db_oauth2 = NULL;
+
+struct oauth2_token_lookup {
+       struct sasl_server_oauth2_request request;
+
+       struct db_oauth2 *db;
+       struct db_oauth2_request db_req;
+       lookup_credentials_callback_t *callback;
+};
+
 static void
 oauth2_verify_finish(enum passdb_result result,
                     struct auth_request *auth_request)
 {
        struct sasl_server_req_ctx *srctx = &auth_request->sasl.req;
-       struct sasl_server_mech_request *request =
-               sasl_server_request_get_mech_request(srctx);
-       struct oauth2_auth_request *oauth2_req =
-               container_of(request, struct oauth2_auth_request, request);
        struct sasl_server_oauth2_failure failure;
 
        i_zero(&failure);
@@ -47,10 +56,6 @@ oauth2_verify_finish(enum passdb_result result,
                i_unreached();
        }
 
-       if (oauth2_req->db != NULL) {
-               failure.openid_configuration =
-                       db_oauth2_get_openid_configuration_url(oauth2_req->db);
-       }
        sasl_server_oauth2_request_fail(srctx, &failure);
 }
 
@@ -66,10 +71,12 @@ oauth2_verify_callback(enum passdb_result result,
 }
 
 static void
-mech_oauth2_verify_token_continue(struct oauth2_auth_request *oauth2_req,
+mech_oauth2_verify_token_continue(struct oauth2_token_lookup *lookup,
                                  const char *const *args)
 {
-       struct auth_request *auth_request = oauth2_req->request.request;
+       struct sasl_server_req_ctx *srctx = lookup->request.rctx;
+       struct auth_request *auth_request =
+               container_of(srctx, struct auth_request, sasl.req);
        int parsed;
        enum passdb_result result;
 
@@ -111,9 +118,9 @@ mech_oauth2_verify_token_input_args(
        struct auth_worker_connection *conn ATTR_UNUSED,
        const char *const *args, void *context)
 {
-       struct oauth2_auth_request *oauth2_req = context;
+       struct oauth2_token_lookup *lookup = context;
 
-       mech_oauth2_verify_token_continue(oauth2_req, args);
+       mech_oauth2_verify_token_continue(lookup, args);
        return TRUE;
 }
 
@@ -121,9 +128,11 @@ static void
 mech_oauth2_verify_token_local_continue(struct db_oauth2_request *db_req,
                                        enum passdb_result result,
                                        const char *error,
-                                       struct oauth2_auth_request *oauth2_req)
+                                       struct oauth2_token_lookup *lookup)
 {
-       struct auth_request *auth_request = oauth2_req->request.request;
+       struct sasl_server_req_ctx *srctx = lookup->request.rctx;
+       struct auth_request *auth_request =
+               container_of(srctx, struct auth_request, sasl.req);
 
        if (result == PASSDB_RESULT_OK) {
                auth_request_set_password_verified(auth_request);
@@ -144,14 +153,26 @@ mech_oauth2_verify_token_local_continue(struct db_oauth2_request *db_req,
        pool_unref(&db_req->pool);
 }
 
-static void
-auth_sasl_oauth2_verify_token(struct oauth2_auth_request *oauth2_req,
-                             const char *token)
+static int
+oauth2_auth_new(struct sasl_server_req_ctx *srctx, pool_t pool,
+               const char *token, struct sasl_server_oauth2_request **req_r)
 {
-       struct auth_request *auth_request = oauth2_req->request.request;
+       struct auth_request *auth_request =
+               container_of(srctx, struct auth_request, sasl.req);
+       struct oauth2_token_lookup *lookup;
+
+       if (db_oauth2 == NULL) {
+               e_error(auth_request->event, "BUG: oauth2 database missing");
+               return -1;
+       }
+
+       lookup = p_new(pool, struct oauth2_token_lookup, 1);
+       sasl_server_oauth2_request_init(&lookup->request, pool, srctx);
+       lookup->db_req.pool = pool;
+       lookup->db = db_oauth2;
 
        auth_request_ref(auth_request);
-       if (!db_oauth2_use_worker(oauth2_req->db)) {
+       if (!db_oauth2_use_worker(lookup->db)) {
                pool_t pool = pool_alloconly_create(
                        MEMPOOL_GROWING"oauth2 request", 256);
                struct db_oauth2_request *db_req =
@@ -159,8 +180,8 @@ auth_sasl_oauth2_verify_token(struct oauth2_auth_request *oauth2_req,
                db_req->pool = pool;
                db_req->auth_request = auth_request;
                db_oauth2_lookup(
-                       oauth2_req->db, db_req, token,  db_req->auth_request,
-                       mech_oauth2_verify_token_local_continue, oauth2_req);
+                       lookup->db, db_req, token, db_req->auth_request,
+                       mech_oauth2_verify_token_local_continue, lookup);
        } else {
                string_t *str = t_str_new(128);
                str_append(str, "TOKEN\tOAUTH2\t");
@@ -168,12 +189,19 @@ auth_sasl_oauth2_verify_token(struct oauth2_auth_request *oauth2_req,
                str_append_c(str, '\t');
                auth_request_export(auth_request, str);
                auth_worker_call(
-                       oauth2_req->db_req.pool,
+                       lookup->db_req.pool,
                        auth_request->fields.user, str_c(str),
-                       mech_oauth2_verify_token_input_args, oauth2_req);
+                       mech_oauth2_verify_token_input_args, lookup);
        }
+
+       *req_r = &lookup->request;
+       return 0;
 }
 
+static const struct sasl_server_oauth2_funcs mech_funcs = {
+       .auth_new = oauth2_auth_new,
+};
+
 void auth_sasl_oauth2_initialize(void)
 {
        const char *mech, *error;
@@ -186,3 +214,59 @@ void auth_sasl_oauth2_initialize(void)
                }
        }
 }
+
+/*
+ * Mechanisms
+ */
+
+static void
+mech_oauth_init_settings(struct sasl_server_oauth2_settings *oauth2_set)
+{
+       i_assert(db_oauth2 != NULL);
+
+       i_zero(oauth2_set);
+       oauth2_set->openid_configuration_url =
+               db_oauth2_get_openid_configuration_url(db_oauth2);
+}
+
+static bool
+mech_oauthbearer_register(struct sasl_server_instance *sasl_inst,
+                         const struct auth_settings *set ATTR_UNUSED)
+{
+       struct sasl_server_oauth2_settings oauth2_set;
+
+       mech_oauth_init_settings(&oauth2_set);
+       sasl_server_mech_register_oauthbearer(sasl_inst, &mech_funcs,
+                                             &oauth2_set);
+       return TRUE;
+}
+
+static bool
+mech_xoauth2_register(struct sasl_server_instance *sasl_inst,
+                     const struct auth_settings *set ATTR_UNUSED)
+{
+       struct sasl_server_oauth2_settings oauth2_set;
+
+       mech_oauth_init_settings(&oauth2_set);
+       sasl_server_mech_register_xoauth2(sasl_inst, &mech_funcs,
+                                         &oauth2_set);
+       return TRUE;
+}
+
+static const struct auth_sasl_mech_module mech_oauthbearer = {
+       .mech_name = SASL_MECH_NAME_OAUTHBEARER,
+
+       .mech_register = mech_oauthbearer_register,
+};
+
+static const struct auth_sasl_mech_module mech_xoauth2 = {
+       .mech_name = SASL_MECH_NAME_XOAUTH2,
+
+       .mech_register = mech_xoauth2_register,
+};
+
+void auth_sasl_mech_oauth2_register(void)
+{
+       auth_sasl_mech_register_module(&mech_oauthbearer);
+       auth_sasl_mech_register_module(&mech_xoauth2);
+}
index ebb574e266bf77390a8fa6c3d85c6d3363a18ee1..def7b840386a3ece1426327e61d414c507575104 100644 (file)
@@ -3,4 +3,6 @@
 
 void auth_sasl_oauth2_initialize(void);
 
+void auth_sasl_mech_oauth2_register(void);
+
 #endif
index 2b2df775f5359aa52fcdf39fd0cebd7b9427f7f9..e098402f71c9fe9d7677cb13b099112cd8d20217 100644 (file)
@@ -463,8 +463,6 @@ MECH_SIMPLE_REGISTER__TEMPLATE(cram_md5)
 MECH_SIMPLE_REGISTER__TEMPLATE(digest_md5)
 MECH_SIMPLE_REGISTER__TEMPLATE(external)
 MECH_SIMPLE_REGISTER__TEMPLATE(login)
-MECH_SIMPLE_REGISTER__TEMPLATE(oauthbearer)
-MECH_SIMPLE_REGISTER__TEMPLATE(xoauth2)
 MECH_SIMPLE_REGISTER__TEMPLATE(otp)
 MECH_SIMPLE_REGISTER__TEMPLATE(plain)
 MECH_SIMPLE_REGISTER__TEMPLATE(scram_sha1)
@@ -532,12 +530,6 @@ static const struct auth_sasl_mech_module mech_login = {
        .mech_register = mech_login_register,
 };
 
-static const struct auth_sasl_mech_module mech_oauthbearer = {
-       .mech_name = SASL_MECH_NAME_OAUTHBEARER,
-
-       .mech_register = mech_oauthbearer_register,
-};
-
 static const struct auth_sasl_mech_module mech_otp = {
        .mech_name = SASL_MECH_NAME_OTP,
 
@@ -586,12 +578,6 @@ static const struct auth_sasl_mech_module mech_winbind_gss_spnego = {
        .mech_register = mech_winbind_gss_spnego_register,
 };
 
-static const struct auth_sasl_mech_module mech_xoauth2 = {
-       .mech_name = SASL_MECH_NAME_XOAUTH2,
-
-       .mech_register = mech_xoauth2_register,
-};
-
 static const struct auth_sasl_mech_module mech_apop = {
        .mech_name = AUTH_SASL_MECH_NAME_APOP,
 
@@ -616,14 +602,13 @@ static void auth_sasl_mechs_init(const struct auth_settings *set)
        auth_sasl_mech_register_module(&mech_login);
        if (set->use_winbind)
                auth_sasl_mech_register_module(&mech_winbind_ntlm);
-       auth_sasl_mech_register_module(&mech_oauthbearer);
+       auth_sasl_mech_oauth2_register();
        auth_sasl_mech_register_module(&mech_otp);
        auth_sasl_mech_register_module(&mech_plain);
        auth_sasl_mech_register_module(&mech_scram_sha1);
        auth_sasl_mech_register_module(&mech_scram_sha1_plus);
        auth_sasl_mech_register_module(&mech_scram_sha256);
        auth_sasl_mech_register_module(&mech_scram_sha256_plus);
-       auth_sasl_mech_register_module(&mech_xoauth2);
 
        auth_sasl_mech_register_module(&mech_apop);
 }
index c8141b815131f200c246eff6ee92a8e11383f108..ac82079aecf80e4adbb3650c233ad8d6eb3b9476 100644 (file)
@@ -2,13 +2,11 @@
 
 #include "auth-common.h"
 #include "auth-fields.h"
-#include "auth-worker-connection.h"
 #include "ioloop.h"
 #include "str.h"
-#include "strescape.h"
+#include "buffer.h"
 #include "json-ostream.h"
 #include "auth-gs2.h"
-#include "db-oauth2.h"
 #include "oauth2.h"
 
 #include "sasl-server-protected.h"
 
 struct oauth2_auth_request {
        struct sasl_server_mech_request request;
-       struct db_oauth2 *db;
-       struct db_oauth2_request db_req;
-       lookup_credentials_callback_t *callback;
+       struct sasl_server_oauth2_request *backend;
 
        bool failed:1;
        bool verifying_token:1;
 };
 
+struct oauth2_auth_mech {
+       struct sasl_server_mech mech;
+       const struct sasl_server_oauth2_funcs *funcs;
+
+       struct sasl_server_oauth2_settings set;
+};
+
 static const struct sasl_server_mech_def mech_oauthbearer;
 static const struct sasl_server_mech_def mech_xoauth2;
 
-static struct db_oauth2 *db_oauth2 = NULL;
-
 static void
 oauth2_fail(struct oauth2_auth_request *oauth2_req,
            const struct sasl_server_oauth2_failure *failure)
 {
        struct sasl_server_mech_request *request = &oauth2_req->request;
+       const struct oauth2_auth_mech *oauth2_mech =
+               container_of(request->mech,
+                            const struct oauth2_auth_mech, mech);
+
+       oauth2_req->verifying_token = FALSE;
 
        if (failure == NULL) {
                sasl_server_request_internal_failure(request);
@@ -61,11 +67,11 @@ oauth2_fail(struct oauth2_auth_request *oauth2_req,
                json_ostream_nwrite_string(joutput, "scope", "mail");
        else
                json_ostream_nwrite_string(joutput, "scope", failure->scope);
-       if (failure->openid_configuration != NULL &&
-           *failure->openid_configuration != '\0') {
+       if (oauth2_mech->set.openid_configuration_url != NULL &&
+           *oauth2_mech->set.openid_configuration_url != '\0') {
                json_ostream_nwrite_string(
                        joutput, "openid-configuration",
-                       failure->openid_configuration);
+                       oauth2_mech->set.openid_configuration_url);
        }
        json_ostream_nascend_object(joutput);
        json_ostream_nfinish_destroy(&joutput);
@@ -107,7 +113,10 @@ void sasl_server_oauth2_request_succeed(struct sasl_server_req_ctx *rctx)
                container_of(request, struct oauth2_auth_request, request);
 
        i_assert(oauth2_req->verifying_token);
+       oauth2_req->verifying_token = FALSE;
        sasl_server_request_success(request, "", 0);
+
+       sasl_server_mech_request_unref(&request);
 }
 
 void sasl_server_oauth2_request_fail(
@@ -124,18 +133,63 @@ void sasl_server_oauth2_request_fail(
                container_of(request, struct oauth2_auth_request, request);
 
        i_assert(oauth2_req->verifying_token);
+       oauth2_req->verifying_token = FALSE;
        oauth2_fail(oauth2_req, failure);
+
+       sasl_server_mech_request_unref(&request);
 }
 
-#include "auth-sasl-mech-oauth2.c"
+struct sasl_server_oauth2_request *
+sasl_server_oauth2_request_get(struct sasl_server_req_ctx *rctx)
+{
+       struct sasl_server_mech_request *request =
+               sasl_server_request_get_mech_request(rctx);
+
+       i_assert(request->mech->def == &mech_oauthbearer ||
+                request->mech->def == &mech_xoauth2);
+
+       struct oauth2_auth_request *oauth2_req =
+               container_of(request, struct oauth2_auth_request, request);
+
+       return oauth2_req->backend;
+}
 
 static void
 mech_oauth2_verify_token(struct oauth2_auth_request *oauth2_req,
                         const char *token)
 {
+       struct sasl_server_mech_request *request = &oauth2_req->request;
+       struct sasl_server_req_ctx *rctx =
+               sasl_server_request_get_req_ctx(request);
+       const struct oauth2_auth_mech *oauth2_mech =
+               container_of(request->mech,
+                            const struct oauth2_auth_mech, mech);
+
+       /* Add reference for the lookup; dropped upon success/failure */
+       sasl_server_mech_request_ref(request);
+
        i_assert(token != NULL);
+       i_assert(oauth2_mech->funcs != NULL &&
+                oauth2_mech->funcs->auth_new != NULL);
        oauth2_req->verifying_token = TRUE;
-       auth_sasl_oauth2_verify_token(oauth2_req, token);
+
+       /* Call the backend auth_new() function under an additional reference in
+          case it fails the request immediately. */
+       sasl_server_mech_request_ref(request);
+       if (oauth2_mech->funcs->auth_new(rctx, request->pool, token,
+                                        &oauth2_req->backend) < 0) {
+               if (!oauth2_req->failed)
+                       sasl_server_oauth2_request_fail(rctx, NULL);
+               i_assert(oauth2_req->backend == NULL);
+       } else {
+               i_assert(!oauth2_req->verifying_token ||
+                        oauth2_req->backend != NULL);
+               i_assert(oauth2_req->backend == NULL ||
+                        oauth2_req->backend->pool != NULL);
+               i_assert(oauth2_req->backend == NULL ||
+                        oauth2_req->backend->rctx != NULL);
+       }
+       sasl_server_mech_request_unref(&request);
 }
 
 /* Input syntax for data:
@@ -149,11 +203,6 @@ mech_oauthbearer_auth_continue(struct sasl_server_mech_request *request,
        struct oauth2_auth_request *oauth2_req =
                container_of(request, struct oauth2_auth_request, request);
 
-       if (oauth2_req->db == NULL) {
-               e_error(request->mech_event, "BUG: oauth2 database missing");
-               sasl_server_request_internal_failure(request);
-               return;
-       }
        if (data_size == 0) {
                oauth2_fail_invalid_request(oauth2_req);
                return;
@@ -245,11 +294,6 @@ mech_xoauth2_auth_continue(struct sasl_server_mech_request *request,
        struct oauth2_auth_request *oauth2_req =
                container_of(request, struct oauth2_auth_request, request);
 
-       if (oauth2_req->db == NULL) {
-               e_error(request->mech_event, "BUG: oauth2 database missing");
-               sasl_server_request_internal_failure(request);
-               return;
-       }
        if (data_size == 0) {
                oauth2_fail_invalid_request(oauth2_req);
                return;
@@ -310,16 +354,40 @@ mech_oauth2_auth_new(const struct sasl_server_mech *mech ATTR_UNUSED,
        struct oauth2_auth_request *request;
 
        request = p_new(pool, struct oauth2_auth_request, 1);
-       request->db_req.pool = pool;
-       request->db = db_oauth2;
 
        return &request->request;
 }
 
+static void mech_oauth2_auth_free(struct sasl_server_mech_request *request)
+{
+       struct oauth2_auth_request *oauth2_req =
+               container_of(request, struct oauth2_auth_request, request);
+       const struct oauth2_auth_mech *oauth2_mech =
+               container_of(request->mech,
+                            const struct oauth2_auth_mech, mech);
+
+       i_assert(oauth2_mech->funcs != NULL);
+       if (oauth2_req->backend != NULL &&
+           oauth2_mech->funcs->auth_free != NULL)
+               oauth2_mech->funcs->auth_free(oauth2_req->backend);
+}
+
+static struct sasl_server_mech *mech_oauth2_mech_new(pool_t pool)
+{
+       struct oauth2_auth_mech *oauth2_mech;
+
+       oauth2_mech = p_new(pool, struct oauth2_auth_mech, 1);
+
+       return &oauth2_mech->mech;
+}
+
 static const struct sasl_server_mech_funcs mech_oauthbearer_funcs = {
        .auth_new = mech_oauth2_auth_new,
        .auth_initial = sasl_server_mech_generic_auth_initial,
        .auth_continue = mech_oauthbearer_auth_continue,
+       .auth_free = mech_oauth2_auth_free,
+
+       .mech_new = mech_oauth2_mech_new,
 };
 
 static const struct sasl_server_mech_def mech_oauthbearer = {
@@ -337,6 +405,9 @@ static const struct sasl_server_mech_funcs mech_xoauth2_funcs = {
        .auth_new = mech_oauth2_auth_new,
        .auth_initial = sasl_server_mech_generic_auth_initial,
        .auth_continue = mech_xoauth2_auth_continue,
+       .auth_free = mech_oauth2_auth_free,
+
+       .mech_new = mech_oauth2_mech_new,
 };
 
 static const struct sasl_server_mech_def mech_xoauth2 = {
@@ -348,12 +419,41 @@ static const struct sasl_server_mech_def mech_xoauth2 = {
        .funcs = &mech_xoauth2_funcs,
 };
 
-void sasl_server_mech_register_oauthbearer(struct sasl_server_instance *sinst)
+static void
+mech_oauth2_register(struct sasl_server_instance *sinst,
+                    const struct sasl_server_mech_def *mech_def,
+                    const struct sasl_server_oauth2_funcs *funcs,
+                    const struct sasl_server_oauth2_settings *set)
+{
+       struct sasl_server_mech *mech;
+
+       i_assert(funcs != NULL && funcs->auth_new != NULL);
+
+       mech = sasl_server_mech_register(sinst, mech_def, NULL);
+
+       struct oauth2_auth_mech *oauth2_mech =
+               container_of(mech, struct oauth2_auth_mech, mech);
+
+       oauth2_mech->funcs = funcs;
+
+       if (set != NULL) {
+               oauth2_mech->set.openid_configuration_url =
+                       p_strdup(mech->pool, set->openid_configuration_url);
+       }
+}
+
+void sasl_server_mech_register_oauthbearer(
+       struct sasl_server_instance *sinst,
+       const struct sasl_server_oauth2_funcs *funcs,
+       const struct sasl_server_oauth2_settings *set)
 {
-       sasl_server_mech_register(sinst, &mech_oauthbearer, NULL);
+       mech_oauth2_register(sinst, &mech_oauthbearer, funcs, set);
 }
 
-void sasl_server_mech_register_xoauth2(struct sasl_server_instance *sinst)
+void sasl_server_mech_register_xoauth2(
+       struct sasl_server_instance *sinst,
+       const struct sasl_server_oauth2_funcs *funcs,
+       const struct sasl_server_oauth2_settings *set)
 {
-       sasl_server_mech_register(sinst, &mech_xoauth2, NULL);
+       mech_oauth2_register(sinst, &mech_xoauth2, funcs, set);
 }
index cbe2580566142622794e4a42c07fa934b3a6b347..cf396accb2ddf035f4b3b8ead20eb1e1a18aa2a7 100644 (file)
@@ -6,12 +6,48 @@
 struct sasl_server_oauth2_failure {
        const char *status;
        const char *scope;
-       const char *openid_configuration;
 };
 
+struct sasl_server_oauth2_request {
+       pool_t pool;
+       struct sasl_server_req_ctx *rctx;
+};
+
+struct sasl_server_oauth2_settings {
+       const char *openid_configuration_url;
+};
+
+struct sasl_server_oauth2_funcs {
+       int (*auth_new)(struct sasl_server_req_ctx *rctx, pool_t pool,
+                       const char *token,
+                       struct sasl_server_oauth2_request **req_r);
+       void (*auth_free)(struct sasl_server_oauth2_request *req);
+};
+
+static inline void
+sasl_server_oauth2_request_init(struct sasl_server_oauth2_request *request_r,
+                               pool_t pool, struct sasl_server_req_ctx *srctx)
+{
+       i_zero(request_r);
+       request_r->pool = pool;
+       request_r->rctx = srctx;
+}
+
 void sasl_server_oauth2_request_succeed(struct sasl_server_req_ctx *rctx);
 void sasl_server_oauth2_request_fail(
        struct sasl_server_req_ctx *rctx,
        const struct sasl_server_oauth2_failure *failure);
 
+struct sasl_server_oauth2_request *
+sasl_server_oauth2_request_get(struct sasl_server_req_ctx *rctx);
+
+void sasl_server_mech_register_oauthbearer(
+       struct sasl_server_instance *sinst,
+       const struct sasl_server_oauth2_funcs *funcs,
+       const struct sasl_server_oauth2_settings *set);
+void sasl_server_mech_register_xoauth2(
+       struct sasl_server_instance *sinst,
+       const struct sasl_server_oauth2_funcs *funcs,
+       const struct sasl_server_oauth2_settings *set);
+
 #endif
index 90354dbb49f0f61437ba39156c5a795235c158ce..44810add985b3686eb910a6e2cf55682df2ef502 100644 (file)
@@ -191,11 +191,6 @@ void sasl_server_mech_register_scram_sha256_plus(
 
 void sasl_server_mech_register_otp(struct sasl_server_instance *sinst);
 
-/* OAUTH2 */
-
-void sasl_server_mech_register_oauthbearer(struct sasl_server_instance *sinst);
-void sasl_server_mech_register_xoauth2(struct sasl_server_instance *sinst);
-
 /* Winbind */
 
 struct sasl_server_winbind_settings {