Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Is it possible to get "Django Login" button like in drf-yasg? #1099

Closed
karambaq opened this issue Nov 3, 2023 · 5 comments
Closed

Comments

@karambaq
Copy link

karambaq commented Nov 3, 2023

In drf-yasg you can specify LOGIN_URL and LOGOUT_URL, and there is this a button to login/logout to django admin, so you don't need to get any tokens by yourself, is it possible with drf-spectacular?

image
@tfranzel
Copy link
Owner

tfranzel commented Nov 3, 2023

Hi! No we do not support this. drf-yasg manually patches in this feature and we follow the approach of least change with regards to SwaggerUI. That is the reason their SwaggerUI is usually severely outdated.

possible? probably, since we do some patching with regards to authentication. However, I don't think it is worth the effort given this is just a button with a link (I believe). The main description is markdown. you could put a link in there if you like.

@karambaq
Copy link
Author

karambaq commented Nov 4, 2023

Thanks for quick answer!

I might be missing something, but what are the options for logging in on this page right now? Is there a way to synchronize it with the current authentication state in the admin panel, apart from obtaining a token and manually inserting it?

@tfranzel
Copy link
Owner

tfranzel commented Nov 5, 2023

The process of logging-in is out of scope for SwaggerUI. You usually just enter the thing that the API needs. However, that is different for OAuth2, where the login process can be done though SwaggerUI. Every other methoid is "manual" or implicit.

In the implicit case of Django Admin, the admin login page (on success) merely sets a cookie and nothing more. If you switch tabs in the same browser to SwaggerUI, that cookie will get used automatically (due to same domain). If you have CookieAuth on your endpoints, things should just work.

drf-yasg is just adding a button with a link to the admin and there is no hidden magic going on afaik.

@karambaq
Copy link
Author

karambaq commented Nov 7, 2023

Thank you.

@karambaq karambaq closed this as completed Nov 7, 2023
@callumgare
Copy link
Contributor

callumgare commented Feb 1, 2024

This doesn't quite do the same thing as this ticket is asking for but I think I found the next best thing.

I wasn't happy with the workaround of relying on the browser to automatically include the sessionid cookie when making api calls with Swagger UI because:

a) The behaviour is not clear for people who are not already familiar with it.
b) You can't copy the generated curl command and have it just work as it does not include the sessionid cookie.

The solution I came up with is to have def-spectacular include a snippit of js that automaticity configures swagger authentication on load with the session id included in the request (assuming the user is currently logged in). This means when a user is logged in Swagger will actually show the session id authorisation as configured and will include the cookie in the generated curl commands. To do this I made a new class that inherits SpectacularSwaggerView and overrides it's get function to set the onComplete property of SWAGGER_UI_SETTINGS.

from drf_spectacular.views import SpectacularSwaggerView
from drf_spectacular.utils import extend_schema

class SpectacularSwaggerAutoAuthView(SpectacularSwaggerView):
    @extend_schema(exclude=True)
    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        session_id = request.session.session_key
        if session_id:
            response.data["settings"] = f"""{{
                deepLinking: true,
                onComplete: function() {{
                    // Note the first arg must match whatever name of your cookie session id security scheme
                    ui.preauthorizeApiKey("Session ID", "{session_id}");
                }},
            }}"""
        return response

Then in my urls.py file instead of using the SpectacularSwaggerView directly for rendering the swagger ui I used SpectacularSwaggerAutoAuthView.

path("swagger-ui/", SpectacularSwaggerAutoAuthView.as_view(url_name="schema"), name="swagger-ui"),

To describe to the reader this behaviour and to give them an easy link to login if they haven't already I've overridden the SessionSchema extension to modify the description that shows up for the cookie/sessionid authentiction method in the Authorisation dialog in Swagger UI.

# This can be saved anywhere as long as it's in a file that is imported by python at some point
from drf_spectacular.authentication import SessionScheme
from textwrap import dedent

class SessionSchemeModified(SessionScheme):
    # Note that the list of available authorisations is sorted alphabetically by name 
    # so if you want the authorisations options to show up in a particular order in 
    # Swagger UI you must name them accordingly.
    name = "Session ID"
    priority = 1

    def get_security_definition(self, auto_schema):
        return {
            **super().get_security_definition(auto_schema),
            "description": dedent("""
                **This will be configured automatically in the Swagger UI
                documentation if there is currently a user logged in via the [login page](/login).**
            """)
        }

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants