# EntraID SignIn Error: oauth2: error validating JWT token: user info JWT token is expired

**URL:** <https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361>\
**Category:** Install/Maintain/Configure\
**Created:** [August 11, 2026, 3:46pm UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361 "2026-08-11T15:46:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexander](https://avatars.discourse-cdn.com/v4/letter/a/bc8723/32.png) [@Alexander](https://forum.gitea.com/u/Alexander)\
**Post date:** [August 11, 2026, 3:46pm UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/1 "2026-08-11T15:46:16Z")

</div>

Hi,

I’m new to Gitea and I’m really struggling to setup an instance on Windows with LetsEncrypt SSL certificate and Entra ID as authentication provider.

By now I have a running instance on an English Windows Server 2025 with an IIS reverse proxy and a Let’s Encrypt Certificate. The server is hardened with most of the CIS recommendations.

I tried to configure Entra ID Sign-In with [this](https://blog.gitea.com/feature-preview-mapping-oidc-groups-to-teams/) (which is exactly what I want) but I get the error:

„There was an error processing the authorization request: oauth2: error validating JWT token: user info JWT token is expired. If this error persists, please contact the site administrator.“

This is my config (domain name redacted):

Gitea located in „C:\program files\gitea\“

Version 1.27

**App.ini**

```auto
APP_NAME = Gitea

RUN_USER = Gitea$

WORK_PATH = C:\Program Files\Gitea

RUN_MODE = prod

[database]

DB_TYPE = sqlite3

HOST = 127.0.0.1:3306

NAME = gitea

USER = gitea

PASSWD =

SCHEMA =

SSL_MODE = disable

PATH = C:\Program Files\Gitea\data\gitea.db

LOG_SQL = false

[repository]

ROOT = C:/Program Files/Gitea/data/gitea-repositories

[server]

SSH_DOMAIN = localhost

DOMAIN = localhost

HTTP_PORT = 3000

ROOT_URL = https://gitea.domain.de/

APP_DATA_PATH = C:\Program Files\Gitea\data

DISABLE_SSH = false

SSH_PORT = 22

LFS_START_SERVER = true

LFS_JWT_SECRET =

OFFLINE_MODE = true

[lfs]

PATH = C:/Program Files/Gitea/data/lfs

[mailer]

ENABLED = false

[service]

REGISTER_EMAIL_CONFIRM = false

ENABLE_NOTIFY_MAIL = false

DISABLE_REGISTRATION = true

ALLOW_ONLY_EXTERNAL_REGISTRATION = true

ENABLE_CAPTCHA = false

REQUIRE_SIGNIN_VIEW = true

DEFAULT_KEEP_EMAIL_PRIVATE = false

DEFAULT_ALLOW_CREATE_ORGANIZATION = false

DEFAULT_ENABLE_TIMETRACKING = true

NO_REPLY_ADDRESS = noreply.localhost

[openid]

ENABLE_OPENID_SIGNIN = false

ENABLE_OPENID_SIGNUP = false

[cron.update_checker]

ENABLED = true

[session]

PROVIDER = file

[log]

MODE = file

LEVEL = debug

ROOT_PATH = C:/Program Files/Gitea/log

LOG_ROTATE = TRUE

DAILY_ROTATE = TRUE

MAX_DAYS = 7

[repository.pull-request]

DEFAULT_MERGE_STYLE = merge

[repository.signing]

DEFAULT_TRUST_MODEL = committer

[security]

INSTALL_LOCK = true

INTERNAL_TOKEN =

PASSWORD_HASH_ALGO = pbkdf2

; ;JWT_SECRET =

; ;ENABLE_AUTO_REGISTRATION = true

; ;ACCESS_TOKEN_EXPIRATION_TIME = 36000

[oauth2]

JWT_SECRET =

; ;ENABLE_AUTO_REGISTRATION = true

; ;USERNAME = prefered_username

; ;ACCOUNT_LINKING = auto

; ;OPENID_CONNECT_SCOPES = openid profile email

[time]

DEFAULT_UI_LOCATION = Europe/Berlin

```

**IIS**

IIS hast he following two options configured:

„system.webServer/proxy“: „preserveHostHeader“ = true

„system.webServer/proxy“: „reverseRewriteHostInResponseHeaders = false

**Web.config**

```auto
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.web>
        <httpRuntime requestPathInvalidCharacters="" />
    </system.web>
    <system.webServer>
        <security>
          <requestFiltering>
            <hiddenSegments>
              <clear />
            </hiddenSegments>
            <denyUrlSequences>
              <clear />
            </denyUrlSequences>
            <fileExtensions allowUnlisted="true">
              <clear />
            </fileExtensions>
          </requestFiltering>
        </security>
        <rewrite>
            <rules useOriginalURLEncoding="false">
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Rewrite" url="http://127.0.0.1:3000{UNENCODED_URL}" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="HTTP_ACCEPT_ENCODING" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                        <set name="HTTP_X_FORWARDED_PROTO" value="https" />			
                    </serverVariables>
                </rule>
            </rules>
            <outboundRules>
                <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
                    <!-- set the pattern correctly here - if you only want to accept http or https -->
                    <!-- change the pattern and the action value as appropriate -->
                    <match filterByTags="A, Form, Img" pattern="^http(s)?://127.0.0.1:3000/(.*)" />
                    <action type="Rewrite" value="https://gitea.domain.de/{R:2}" />
                </rule>
                <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
                    <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                    <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition>
                    <preCondition name="NeedsRestoringAcceptEncoding">
                        <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                    </preCondition>
                </preConditions>
            </outboundRules>
        </rewrite>
        <urlCompression doDynamicCompression="true" />
        <!-- Map all extensions to the same MIME type, so all files can be
               downloaded. -->
        <staticContent>
          <clear />
          <mimeMap fileExtension="*" mimeType="application/octet-stream" />
        </staticContent>
    </system.webServer>
</configuration>

```

**Azure App**

 ![image](https://us1.discourse-cdn.com/flex020/uploads/gitea/original/2X/6/6c4dc5d9dc22d0d43d9d1d5fe63208c9b963e5cf.png)

 ![image](https://us1.discourse-cdn.com/flex020/uploads/gitea/original/2X/1/1a49c446b131f5ec3489026ead74b78ce828f539.png)

API permissions granted.

Gitea Authentication Provider

 ![image](https://us1.discourse-cdn.com/flex020/uploads/gitea/original/2X/5/55eb27f99b2202d9998cbe4c46fb49e5ab648d27.png)

 ![image](https://us1.discourse-cdn.com/flex020/uploads/gitea/original/2X/f/f7c5ffce78a55e1fe4828d122bbca8444db6e271.png)

 ![image](https://us1.discourse-cdn.com/flex020/uploads/gitea/original/2X/0/0d811013453a8195e1c246b172545a9a4753bb7b.png)

I can see successful sign-ins in the Entra log.

I could not find anything on the net which helped me with this problem.

Any suggestions?

Thank you

Alex

---

<div class="post-metadata">

**Author:** ![Blake.Hayes70](https://avatars.discourse-cdn.com/v4/letter/b/e47c2d/32.png) [@Blake.Hayes70](https://forum.gitea.com/u/Blake.Hayes70)\
**Post date:** [August 14, 2026, 7:03am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/2 "2026-08-14T07:03:54Z")

</div>

The exact `oauth2: error validating JWT token: user info JWT token is expired` message is often caused by clock skew between the Gitea host, the reverse proxy, and Entra ID, especially when the token lifetime is short. I would first compare UTC time on the Gitea/IIS host with a trusted time source, then verify that the proxy preserves the original Host and forwards the expected HTTPS/X-Forwarded-\* headers consistently. If the clocks match, capture a fresh token and compare its `exp`, `iat`, and issuer values with the OAuth provider configuration rather than changing token validation broadly. Do you see the same expiry error when accessing Gitea directly without the IIS proxy?

---

<div class="post-metadata">

**Author:** ![Alexander](https://avatars.discourse-cdn.com/v4/letter/a/bc8723/32.png) [@Alexander](https://forum.gitea.com/u/Alexander)\
**Post date:** [August 14, 2026, 10:15am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/3 "2026-08-14T10:15:58Z")

</div>

Hi,

thank you. The time seemed correct but it wasn’t as the time zone of the server was wrong.

Now I can authenticate but the account is neither automatically created, nor linked if I create the account automatically. If I link it manually it is not added to the organization ☹

My last attempt:

 ![image](https://us1.discourse-cdn.com/flex020/uploads/gitea/original/2X/2/2a1ac3b408290ca61288539a744c8a0be632b89a.png)

Any suggestions?

Alex

---

<div class="post-metadata">

**Author:** ![Blake.Hayes70](https://avatars.discourse-cdn.com/v4/letter/b/e47c2d/32.png) [@Blake.Hayes70](https://forum.gitea.com/u/Blake.Hayes70)\
**Post date:** [August 19, 2026, 10:34am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/4 "2026-08-19T10:34:31Z")

</div>

Since sign-in now works after fixing the timezone, the remaining issue is provisioning. Check that Entra claims match Gitea’s OAuth settings, then verify the linked account is invited to the organization.

---

<div class="post-metadata">

**Author:** ![Alexander](https://avatars.discourse-cdn.com/v4/letter/a/bc8723/32.png) [@Alexander](https://forum.gitea.com/u/Alexander)\
**Post date:** [August 19, 2026, 10:48am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/5 "2026-08-19T10:48:02Z")

</div>

Hi,

I opened another post here so that people can find it more easily [Oauth EntraID with automatic user creation](https://forum.gitea.com/t/oauth-entraid-with-automatic-user-creation/12370/1) This post has the current app.ini as well as pictures of the claim configuration. I cannot find the issue

Regards

Alex

---

<div class="post-metadata">

**Author:** ![Blake.Hayes70](https://avatars.discourse-cdn.com/v4/letter/b/e47c2d/32.png) [@Blake.Hayes70](https://forum.gitea.com/u/Blake.Hayes70)\
**Post date:** [August 20, 2026, 7:11am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/6 "2026-08-20T07:11:27Z")

</div>

That separate post is the right place to continue, since it includes the current app.ini and claim screenshots. I’d compare the claim names there with the values Gitea reads for username and email before changing IIS again.

---

<div class="post-metadata">

**Author:** ![Blake.Hayes70](https://avatars.discourse-cdn.com/v4/letter/b/e47c2d/32.png) [@Blake.Hayes70](https://forum.gitea.com/u/Blake.Hayes70)\
**Post date:** [August 21, 2026, 6:32am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/7 "2026-08-21T06:32:26Z")

</div>

I’ll compare those claim names with the username and email settings in the separate post. Is there a Gitea log entry showing the values received during sign-in?

---

<div class="post-metadata">

**Author:** ![Alexander](https://avatars.discourse-cdn.com/v4/letter/a/bc8723/32.png) [@Alexander](https://forum.gitea.com/u/Alexander)\
**Post date:** [August 21, 2026, 7:09am UTC](https://forum.gitea.com/t/entraid-signin-error-oauth2-error-validating-jwt-token-user-info-jwt-token-is-expired/12361/8 "2026-08-21T07:09:44Z")

</div>

I updated the other post with the log

Regards
