sftpgo icon indicating copy to clipboard operation
sftpgo copied to clipboard

[Bug]: OAuth 2.0 initialization request doesn't have code_challenge and code_challenge_method

Open heindrickdumdum0217 opened this issue 1 month ago • 0 comments

⚠️ This issue respects the following points: ⚠️

  • [x] This is a bug, not a question or a configuration issue.
  • [x] This issue is not already reported on Github (I've searched it).

Bug description

According to OAuth2.0 docs, it's recommended to use PKCE for confidential clients for security best practice. In this case client must send code_challenge and code_challenge_method to server when initialize request. But I can't see code_challenge and code_challenge_method in initialization request and OIDC login fails.

https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.5.3.1

Steps to reproduce

  1. Configure OIDC authentication in SFTPGo.
  2. Try to login wtih OIDC.
  3. Inspect initialization request.

Expected behavior

It should send code_challenge and code_challenge_method as PKCE is recommended for confidential clients.

SFTPGo version

2.7.0

Data provider

PostgreSQL

Installation method

Community Docker image

Configuration

SFTPGO_HTTPD__BINDINGS__0__DISABLED_LOGIN_METHODS=2
SFTPGO_HTTPD__BINDINGS__0__OIDC__DEBUG=true
SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_ID=redacted
SFTPGO_HTTPD__BINDINGS__0__OIDC__CLIENT_SECRET=redacted
SFTPGO_HTTPD__BINDINGS__0__OIDC__CONFIG_URL=http://localhost:8002/audit/oauth2
SFTPGO_HTTPD__BINDINGS__0__OIDC__SCOPES="openid,profile,email,roles"
SFTPGO_HTTPD__BINDINGS__0__OIDC__REDIRECT_BASE_URL=http://localhost:18080
SFTPGO_HTTPD__BINDINGS__0__OIDC__USERNAME_FIELD=preferred_username
SFTPGO_HTTPD__BINDINGS__0__OIDC__IMPLICIT_ROLES=true

Relevant log output

2025-12-08 17:19:40,284 INFO     middleware:_log:105 GET /audit/oauth2/authorize/?client_id=xxx&nonce=c68cc3424cf7384335081f134250239a6c529c55b12f0528149f6fe853d496b9&redirect_uri=http%3A%2F%2Flocalhost%3A18080%2Fweb%2Foidc%2Fredirect&response_type=code&scope=openid+profile+email+roles&state=e47560a9d1066f7f50e9bc260b67c212ebb314b2e0fe680925dfc1ac1d94e37b
2025-12-08 17:19:40,284 INFO     middleware:_log:105 GET /audit/oauth2/authorize/?client_id=xxx&nonce=c68cc3424cf7384335081f134250239a6c529c55b12f0528149f6fe853d496b9&redirect_uri=http%3A%2F%2Flocalhost%3A18080%2Fweb%2Foidc%2Fredirect&response_type=code&scope=openid+profile+email+roles&state=e47560a9d1066f7f50e9bc260b67c212ebb314b2e0fe680925dfc1ac1d94e37b - 302
2025-12-08 17:19:40,284 INFO     basehttp:log_message:213 "GET /audit/oauth2/authorize/?client_id=xxx&nonce=c68cc3424cf7384335081f134250239a6c529c55b12f0528149f6fe853d496b9&redirect_uri=http%3A%2F%2Flocalhost%3A18080%2Fweb%2Foidc%2Fredirect&response_type=code&scope=openid+profile+email+roles&state=e47560a9d1066f7f50e9bc260b67c212ebb314b2e0fe680925dfc1ac1d94e37b HTTP/1.1" 302 0
2025-12-08 17:19:40,509 INFO     middleware:_log:105 POST /audit/oauth2/token/
2025-12-08 17:19:40,509 ERROR    middleware:_log:105 {'Content-Length': '103', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'localhost:8002', 'User-Agent': 'Go-http-client/1.1', 'Authorization': '*****', 'Accept-Encoding': 'gzip'}
2025-12-08 17:19:40,509 ERROR    middleware:_log:105 b'code=&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A18080%2Fweb%2Foidc%2Fredirect'
2025-12-08 17:19:40,509 INFO     middleware:_log:105 POST /audit/oauth2/token/ - 400
2025-12-08 17:19:40,509 ERROR    middleware:_log:105 {'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'Pragma': 'no-cache'}
2025-12-08 17:19:40,509 ERROR    middleware:_log:105 b'{"error": "invalid_grant"}'
2025-12-08 17:19:40,509 WARNING  log:log_response:253 Bad Request: /audit/oauth2/token/
2025-12-08 17:19:40,510 WARNING  basehttp:log_message:213 "POST /audit/oauth2/token/ HTTP/1.1" 400 26
2025-12-08 17:19:40,729 INFO     middleware:_log:105 POST /audit/oauth2/token/
2025-12-08 17:19:40,729 ERROR    middleware:_log:105 {'Content-Length': '297', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'localhost:8002', 'User-Agent': 'Go-http-client/1.1', 'Accept-Encoding': 'gzip'}
2025-12-08 17:19:40,729 ERROR    middleware:_log:105 b'client_id=xxx&client_secret=xxx&code=&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A18080%2Fweb%2Foidc%2Fredirect'
2025-12-08 17:19:40,729 INFO     middleware:_log:105 POST /audit/oauth2/token/ - 400
2025-12-08 17:19:40,729 ERROR    middleware:_log:105 {'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'Pragma': 'no-cache'}
2025-12-08 17:19:40,729 ERROR    middleware:_log:105 b'{"error": "invalid_grant"}'
2025-12-08 17:19:40,729 WARNING  log:log_response:253 Bad Request: /audit/oauth2/token/
2025-12-08 17:19:40,729 WARNING  basehttp:log_message:213 "POST /audit/oauth2/token/ HTTP/1.1" 400 26

What are you using SFTPGo for?

Medium business

Additional info

I have implemented OIDC server using django-oauth-toolkit 3.1.0

{
      "OAUTH2_VALIDATOR_CLASS": "xxx.utils.oauth2.validators.OAuth2Validator",
      "SCOPES": {
          "openid": "OpenID Connect scope",
          "profile": "Profile",
          "email": "Email",
          "roles": "Roles",
      },
      "ALLOWED_REDIRECT_URI_SCHEMES": ["http", "https"] if STAGE in ["test", "local", "docker", "dev"] else ["https"],
      "ALLOWED_SCHEMES": ["http", "https"] if STAGE in ["test", "local", "docker", "dev"] else ["https"],
      "PKCE_REQUIRED": True,
      "OIDC_ENABLED": True,
      # Explicitly set because django-oauth-toolkit incorrectly guess correct scheme.
      "OIDC_ISS_ENDPOINT": None if STAGE in ["test", "local", "docker"] else f"https://{DOMAIN}/{PRODUCT}/oauth2",
      "OIDC_RSA_PRIVATE_KEY": env.str("OIDC_RSA_PRIVATE_KEY"),
      "OIDC_RP_INITIATED_LOGOUT_ENABLED": True,
      "OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT": True,
  }

heindrickdumdum0217 avatar Dec 08 '25 17:12 heindrickdumdum0217