]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-oauth2, oauth2: Add oauth2_token_expire_grace setting
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 15 Aug 2025 10:36:08 +0000 (13:36 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 26 Aug 2025 07:06:20 +0000 (07:06 +0000)
src/auth/db-oauth2.c
src/auth/db-oauth2.h
src/lib-oauth2/oauth2-jwt.c
src/lib-oauth2/oauth2.h

index 230c6cf7678a5fa356fe38932a41eb0b2d1b63cf..5aa9d0d387dda736fb4a4c20a2ffdb214697491a 100644 (file)
@@ -21,6 +21,8 @@
 #undef DEF
 #define DEF(type, name) \
        SETTING_DEFINE_STRUCT_##type("oauth2_"#name, name, struct auth_oauth2_settings)
+#define DEF_SECS(type, name) \
+       SETTING_DEFINE_STRUCT_##type("oauth2_"#name, name##_secs, struct auth_oauth2_settings)
 
 static const struct setting_define auth_oauth2_setting_defines[] = {
        DEF(STR, tokeninfo_url),
@@ -36,6 +38,7 @@ static const struct setting_define auth_oauth2_setting_defines[] = {
        DEF(STR, client_secret),
        DEF(BOOLLIST, issuers),
        DEF(STR, openid_configuration_url),
+       DEF_SECS(TIME, token_expire_grace),
        DEF(BOOL, force_introspection),
        DEF(BOOL, send_auth_headers),
        DEF(BOOL, use_worker_with_mech),
@@ -60,6 +63,7 @@ static const struct auth_oauth2_settings auth_oauth2_default_settings = {
        .client_secret = "",
        .issuers = ARRAY_INIT,
        .openid_configuration_url = "",
+       .token_expire_grace_secs = 60,
        .send_auth_headers = FALSE,
        .use_worker_with_mech = FALSE,
 };
@@ -195,6 +199,7 @@ static int db_oauth2_setup(struct db_oauth2 *db, const char **error_r)
        db->oauth2_set.client_id = db->set->client_id;
        db->oauth2_set.client_secret = db->set->client_secret;
        db->oauth2_set.send_auth_headers = db->set->send_auth_headers;
+       db->oauth2_set.token_expire_grace_secs = db->set->token_expire_grace_secs;
        if (!array_is_empty(&db->set->scope)) {
                db->oauth2_set.scope =
                        p_array_const_string_join(db->pool, &db->set->scope, " ");
index 3f362c61ddb21629c9f6e32fb0393cb16d31a8f4..9ebc0a4823b94e482978b3890707282c1f11e610 100644 (file)
@@ -43,6 +43,10 @@ struct auth_oauth2_settings {
        */
        const char *openid_configuration_url;
 
+       /* How many seconds after token expiration is it still allowed to
+          succeed the authentication. */
+       unsigned int token_expire_grace_secs;
+
        /* Should introspection be done even if not necessary */
        bool force_introspection;
        /* Should we send service and local/remote endpoints as X-Dovecot-Auth headers */
index 357b92fca2db748c41438e18f9775e5fc25940ed..8ccff8ca144fb8449c482cda039bcfb9aa4f8599 100644 (file)
@@ -514,10 +514,12 @@ oauth2_jwt_body_process(const struct oauth2_settings *set,
                        iat, t0 + 1);
                return -1;
        }
-       if (exp < t0) {
+       /* Allow using slightly expired token, in case client time isn't well
+          synced. */
+       if (exp < t0 - set->token_expire_grace_secs) {
                *error_r = t_strdup_printf(
-                       "Token has expired (exp=%"PRId64" < %"PRId64")",
-                       exp, t0);
+                       "Token has expired (exp=%"PRId64" < %"PRId64" - grace %u)",
+                       exp, t0, set->token_expire_grace_secs);
                return -1;
        }
 
index 9b25ea52f7ba20b70bf29dd77f808942c16dffaa..aadae4a90b97fa9dcf3b6e0f0a6d498b579695b2 100644 (file)
@@ -38,6 +38,9 @@ struct oauth2_settings {
        struct oauth2_validation_key_cache *key_cache;
        /* valid issuer names */
        const char *const *issuers;
+       /* How many seconds after token expiration is it still allowed to
+          succeed the authentication. */
+       unsigned int token_expire_grace_secs;
 
        enum {
                INTROSPECTION_MODE_GET_AUTH,