Opened 14 months ago

Last modified 14 months ago

#23733 closed defect

JOSM does not send client_secret in oauth2 token request for authorization code grant flow — at Version 2

Reported by: Woazboat Owned by: team
Priority: critical Milestone:
Component: Core Version: latest
Keywords: oauth2, client_secret Cc:

Description (last modified by Woazboat)

Encountered on JOSM v19103 when using a local self-hosted OSM server

oauth2 settings

After pressing the 'Authorize now (Fully automatic)' button, the following HTTP exchange happens:

Authorization request -> OSM server

GET /oauth2/authorize?response_type=code&client_id=Z6bOm_8NT2JIEx5JDpV4iQwy1vD40Pc6HYAu4ugUWgc&redirect_uri=http://127.0.0.1:8111/oauth_authorization&scope=read_gpx%20write_gpx%20read_prefs%20write_prefs%20write_api%20write_notes&state=9c24c6cd-5572-410f-bab3-fa49c91a71cd&code_challenge_method=S256&code_challenge=JjuiikdPYf6hiXWwzZW5ydJur-lqn7AdC_mH0WBORDA HTTP/1.1
Host: localhost:31500
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Cookie: _osm_session=f1dd39db183fe58b9806ee39742ecc9f
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

OSM server sends the authorization code back to JOSM via the remote control url:

HTTP/1.1 302 Found
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
X-Content-Type-Options: nosniff
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Language: en
Location: http://127.0.0.1:8111/oauth_authorization?code=1Zhog9xRXeAsbRwVUgVvtubQkmWeBuY_kr7SY_pkVy8&state=9c24c6cd-5572-410f-bab3-fa49c91a71cd
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Content-Security-Policy-Report-Only: default-src 'self'; child-src 'self'; connect-src 'self'; font-src 'none'; frame-ancestors 'self'; frame-src 'self'; img-src 'self' data: www.gravatar.com *.wp.com tile.openstreetmap.org gps.tile.openstreetmap.org *.tile.thunderforest.com tile.tracestrack.com *.openstreetmap.fr; manifest-src 'self'; media-src 'none'; object-src 'self'; script-src 'self'; style-src 'self' 'nonce-rbBl3U4wpaHEQJMZrruF+qw9tDDD+sXC'; worker-src 'none'
Set-Cookie: _osm_session=f1dd39db183fe58b9806ee39742ecc9f; path=/; expires=Thu, 11 Jul 2024 13:17:31 GMT; HttpOnly; SameSite=Lax
X-Request-Id: cc4fcc48-4d44-4d1c-80b2-600ff2ee7d2f
X-Runtime: 0.120389
Server-Timing: start_processing.action_controller;dur=0.09, cache_read.active_support;dur=0.14, sql.active_record;dur=49.07, instantiation.active_record;dur=2.14, transaction.active_record;dur=16.65, redirect_to.action_controller;dur=0.14, process_action.action_controller;dur=87.95, cache_write.active_support;dur=0.10
vary: Accept-Language, Origin
Content-Length: 0
Date: Thu, 13 Jun 2024 13:17:31 GMT
Server: lighttpd/1.4.64
GET /oauth_authorization?code=1Zhog9xRXeAsbRwVUgVvtubQkmWeBuY_kr7SY_pkVy8&state=9c24c6cd-5572-410f-bab3-fa49c91a71cd HTTP/1.1
Host: 127.0.0.1:8111
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Cookie: _xsrf=2|1ee5c13c|6a4925189a1640610ef6a475ff957ba5|1617984267; CSRF-Token-3KZHS=uydXZvUwRpA3Jud2FgNt4i3QUmFp7PUu; session=eyJjc3JmX3Rva2VuIjoiNWJlYjY1N2I0YTk0OTQwY2Y1M2RlN2EyYmNkMGEyODYxNzkzOTQ5MSJ9.Yq0O7g.ckj-pvRrRe21b4q7kb41nhU9tZQ
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Sec-GPC: 1

In response, JOSM sends a POST request to the token access URL to fetch the token. The body of this request is missing the required client_secret field.

POST /oauth2/token HTTP/1.1
User-Agent: JOSM/1.5 (19103 en) Linux Debian GNU/Linux trixie/sid Java/17.0.11
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Host: localhost:31500
Connection: keep-alive
Content-Length: 238
Cookie: _osm_session=04f15c9d111f742de724847cd34caa4b

grant_type=authorization_code&client_id=Z6bOm_8NT2JIEx5JDpV4iQwy1vD40Pc6HYAu4ugUWgc&redirect_uri=http://127.0.0.1:8111/oauth_authorization&code=1Zhog9xRXeAsbRwVUgVvtubQkmWeBuY_kr7SY_pkVy8&code_verifier=f7cfbb5d-87a2-4169-9cf3-62ed0020a9e4

As a result, the server rejects the token request:

HTTP/1.1 401 Unauthorized
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
X-Content-Type-Options: nosniff
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Cache-Control: no-store
Content-Type: application/json; charset=utf-8
WWW-Authenticate: Bearer realm="Doorkeeper", error="invalid_client", error_description="Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."
Content-Security-Policy-Report-Only: default-src 'self'; child-src 'self'; connect-src 'self'; font-src 'none'; form-action 'self'; frame-ancestors 'self'; frame-src 'self'; img-src 'self' data: www.gravatar.com *.wp.com tile.openstreetmap.org gps.tile.openstreetmap.org *.tile.thunderforest.com tile.tracestrack.com *.openstreetmap.fr; manifest-src 'self'; media-src 'none'; object-src 'self'; script-src 'self'; style-src 'self' 'nonce-XzjPNRrxCTsi4OWcceuk1Z/uJARIa2kH'; worker-src 'none'
X-Request-Id: 1e9532ba-6621-4a14-8eb3-078c28565325
X-Runtime: 0.032401
Server-Timing: start_processing.action_controller;dur=0.02, sql.active_record;dur=1.51, instantiation.active_record;dur=0.29, process_action.action_controller;dur=12.66
vary: Accept, Origin
Content-Length: 173
Date: Thu, 13 Jun 2024 13:17:31 GMT
Server: lighttpd/1.4.64

{"error":"invalid_client","error_description":"Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."}

After manually modifying and re-sending the POST request to include the client_secret field, the request succeeds and the server responds with a token:

(The following request logs for the modified request are from a different attempt, so the authorization codes/nonces are different)

POST /oauth2/token HTTP/1.1
User-Agent: JOSM/1.5 (19103 en) Linux Debian GNU/Linux trixie/sid Java/17.0.11
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Host: localhost:31500
Connection: keep-alive
Content-Length: 296
Cookie: _osm_session=04f15c9d111f742de724847cd34caa4b

grant_type=authorization_code&client_id=Z6bOm_8NT2JIEx5JDpV4iQwy1vD40Pc6HYAu4ugUWgc&client_secret=2TvpyFlxvu0C4b435d3lofB5dY7K4_qSKWoX6C0LEWM&redirect_uri=http://127.0.0.1:8111/oauth_authorization&code=IO4jNs0TqwV4o0Qxc0Itr1k-EzkttoI4s_EiAA5VxeA&code_verifier=bb1210fd-b70f-4d5b-b260-2264a2249f47

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
X-Content-Type-Options: nosniff
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Cache-Control: no-store
Content-Type: application/json; charset=utf-8
ETag: W/"3ac628dafb309e963cfeaf02f5dab579"
Content-Security-Policy-Report-Only: default-src 'self'; child-src 'self'; connect-src 'self'; font-src 'none'; form-action 'self'; frame-ancestors 'self'; frame-src 'self'; img-src 'self' data: www.gravatar.com *.wp.com tile.openstreetmap.org gps.tile.openstreetmap.org *.tile.thunderforest.com tile.tracestrack.com *.openstreetmap.fr; manifest-src 'self'; media-src 'none'; object-src 'self'; script-src 'self'; style-src 'self' 'nonce-i9hz2NMTdzxzWhLUI8Z4eCIksw+JEXzN'; worker-src 'none'
X-Request-Id: b7b5e3e1-84a5-4f58-a090-269eed9e7620
X-Runtime: 0.051822
Server-Timing: start_processing.action_controller;dur=0.02, sql.active_record;dur=13.24, instantiation.active_record;dur=0.73, transaction.active_record;dur=18.50, process_action.action_controller;dur=33.36
vary: Accept, Origin
Content-Length: 182
Date: Thu, 13 Jun 2024 13:30:25 GMT
Server: lighttpd/1.4.64

{"access_token":"oxpk2rfgDuAlRMP0T25b5v3LNXJF99PK1451H8Rm1wM","token_type":"Bearer","scope":"read_gpx write_gpx read_prefs write_prefs write_api write_notes","created_at":1718284075}

The server is only used for local testing, so posting the secrets here is not an issue


References:
https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1
https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type
https://www.oauth.com/playground/authorization-code.html

Change History (3)

by Woazboat, 14 months ago

oauth2 settings

comment:1 by Woazboat, 14 months ago

Description: modified (diff)

comment:2 by Woazboat, 14 months ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.