swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.32k stars 8.92k forks source link

Auth code not cleared after login, second authorization attempt fails #6034

Open mihalios opened 4 years ago

mihalios commented 4 years ago

Q&A (please complete the following information)

Describe the bug you're encountering (includes steps to re-produce)

  1. Users clicks on 'Authorize' button
  2. OAuth pop-up shows and user clicks on Authorize.
  3. Login succeeds, pop-up now shows the 'Logout' button.
  4. User logs out
  5. Without closing the OAuth pop-up user tries to authorize again
  6. An error is returned, something like "error: invalid_grant, description: Authorization code is invalid or expired."

Expected behavior

User should be able to authorize/logout/authorize/etc in the same pop-up.

Screenshots

Unfortunately I cannot upload the screenshot at the moment. The error appears in the OAuth pop-up, in a red banner above the 'Authorize' and 'Close' buttons.

Additional context or thoughts

I've yet to verify my hypothesis but I suspect that Swagger UI is not clearing the auth code upon logout. So when the user tries to re-authorize, in the same pop-up, Swagger re-uses the auth code, which is only good strictly for one request (the first one).

martinussuherman commented 3 years ago

I think I've found the same problem as @mihalios, using Win 10/Firefox 84.0.2. This is the screenshot of the error message:

swagger-invalid-grant

The Api repo is here

Edit: This is the identity server log:

2021-01-23 11:42:46.069 +07:00 [ERR] Request validation failed
2021-01-23 11:43:18.227 +07:00 [ERR] Invalid authorization code{"code":"Ze3nOl7CzFrgiXo363R88k_uecCR8fOdgz8ZMGQf2cs"}, details: {"ClientId":"JokizillaApiSwagger","ClientName":"Jokizilla Api Swagger","GrantType":"authorization_code","Scopes":null,"AuthorizationCode":"Ze3nOl7CzFrgiXo363R88k_uecCR8fOdgz8ZMGQf2cs","RefreshToken":null,"UserName":null,"AuthenticationContextReferenceClasses":null,"Tenant":null,"IdP":null,"Raw":{"grant_type":"authorization_code","code":"Ze3nOl7CzFrgiXo363R88k_uecCR8fOdgz8ZMGQf2cs","client_id":"JokizillaApiSwagger","redirect_uri":"https://xxx.xxx/swagger/oauth2-redirect.html","code_verifier":"N6llLvrq841it4kwlTYh-Ui4DMv17J8cT5wQmGdyJGE"},"$type":"TokenRequestValidationLog"}

Regards,

Martinus

MikaelElkiaer commented 2 years ago

Does anyone have a fix or workaround? - Besides manually clearing cookies via hard refresh or similar.

miha-lios commented 2 years ago

@MikaelElkiaer you don't need to clear cookies or do a hard refresh. The issue I raised concerns login/logout/re-login from the same OAuth pop-up. If you login, then logout, then close the pop-up and click again on 'Authorize' it'll work.

This is more of a UX bug than anything else.

To answer your question, I'm not aware of a fix/workaround.

MikaelElkiaer commented 2 years ago

@miha-lios The workaround is actually to close and open the pop-up. It seems that the authorization code is not cookie cached, but saved within the pop-up.

Thanks for clarifying that. :)

shijh commented 5 months ago

I met this issue in my development with swagger-ui v5.12.0.

I found the reason behind is that the code of the 1st time authorization is stored and not covered by the code of the 2nd time authn.

I tried authorized.setIn([authorizedName, "code"], "") in customized logout, failed.

Here is the server side log, it shows a new code generated and sent back to frontend, but the old code used in new authn:

swagger-ui-issue-6034

shijh commented 5 months ago

OK, I found this issue could be resolved by emptying the payload.auth.code in authorizeOauth2 as following:

window.onload = function() {
  window.ui = SwaggerUIBundle({
    url: urlParam,
    dom_id: '#swagger-ui',
    deepLinking: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl,
      function() {
        return {
          statePlugins: {
            auth: {
              wrapActions: {
                authorizeOauth2: (oriAction, system) => (payload) => {
                  payload.auth.code = ""
                  return oriAction(payload)
                }
              }
            }
          }
        }
      }
    ],
    layout: "StandaloneLayout",
  });
};