navikt / mock-oauth2-server

A scriptable/customizable web server for testing HTTP clients using OAuth2/OpenID Connect or applications with a dependency to a running OAuth2 server (i.e. APIs requiring signed JWTs from a known issuer)
MIT License
248 stars 59 forks source link

URL-encoded parameters are dropped from the state parameter during login #773

Open abias opened 4 days ago

abias commented 4 days ago

Thank you very much for this helpful project! I would like to use it to mock a OAuth2 provider to automatically test a OAuth2 plugin in Moodle LMS.

However, I had to see that logins with the mocked OAuth2 provider always fail, obviously due to the fact that URL-encoded parameters are dropped from the state parameter when redirecting back to the Moodle application.

This is what happens in my test setup:


  1. The application redirects the user to the OAuth2 server on 8080 with this URL:

https://localhost:8080/default/authorize?client_id=foo&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A61504%2Fadmin%2Foauth2callback.php&state=%2Fauth%2Foauth2%2Flogin.php%3Fwantsurl%3Dhttp%253A%252F%252Flocalhost%253A61504%252F%26sesskey%3DRQ9OUF5ATR%26id%3D2&scope=openid%20profile%20email

Please note that the state parameter contains a URL with URL-encoded parameters wantsurl, sesskey and id. This state should make it back to the application as-is when the OAuth2 server redirects the user back to the application.


  1. On the OAuth2 server login page, I see this at the bottom of the page:
Authorization Request
----------------------
client_id = foo
response_type = code
redirect_uri = http://localhost:61504/admin/oauth2callback.php
state = /auth/oauth2/login.php?wantsurl
sesskey = RQ9OUF5ATR
id = 2
scope = openid profile email

This is already wrong, the OAuth2 server seems to have split up the URL-encoded parameters.


  1. Then I log in by entering this data into the OAuth2 server login form:

User: john Claims:

{
    "lastname": "Doe",
    "firstname": "John",
    "email": "john.doe@example.com",
    "username": "john",
    "sub": "john",
    "updated_at": 1490198843,
}

  1. The login form sends a POST request to the OAuth2 server to this URL:

https://localhost:8080/default/authorize?client_id=foo&response_type=code&redirect_uri=http://localhost:61504/admin/oauth2callback.php&state=/auth/oauth2/login.php?wantsurl=http%3A%2F%2Flocalhost%3A61504%2F&sesskey=RQ9OUF5ATR&id=2&scope=openid profile email

And the OAuth2 server redirects the user to this URL:

http://localhost:61504/admin/oauth2callback.php?code=e8Bx2HKPMfGh4-zOr4xGOEIS_gzdv5Qjnh07wKduiXE&state=%2Fauth%2Foauth2%2Flogin.php%3Fwantsurl%3Dhttp%253A%252F%252Flocalhost%253A61504%252F

You can see the request and the answer in this screenshot here as well:

grafik

You can see that, in the POST URL, the sesskey and id parameters are added with a real & instead of a URL-encoded %26 to the URL. And because of that, they are not part of the state parameter anymore and are missing when the OAuth2 server adds the state parameter to the redirect URL.

Unfortunately, as my application needs this sesskey parameter, the login fails.


I would highly appreciate if you could check if this behaviour is a bug in the OAuth2 server which can be fixed. Or if I am doing anything wrong when using the OAuth2 server.