GithubHelp home page GithubHelp logo

Comments (9)

dantownsend avatar dantownsend commented on May 22, 2024 1

@sinisaos Thanks for sharing that example.

Here's some code from one of my apps which might also be helpful:

import datetime
from fastapi import FastAPI
from piccolo_api.csrf.middleware import CSRFMiddleware
from piccolo_api.openapi.endpoints import swagger_ui
from piccolo_api.session_auth.endpoints import session_login, session_logout
from piccolo_api.session_auth.middleware import SessionsAuthBackend
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.routing import Route

app = FastAPI()

app.mount(
    "/login/",
    session_login(),
)

private_app = FastAPI(
    routes=[
        Route("/logout/", session_logout()),
    ],
    middleware=[
        Middleware(
            AuthenticationMiddleware,
            backend=SessionsAuthBackend(
                increase_expiry=datetime.timedelta(minutes=30)
            ),
        ),
        Middleware(CSRFMiddleware, allow_form_param=True),
    ],
    docs_url=None,
    redoc_url=None,
)

# The Swagger docs which come with FastAPI don't support CSRF middleware, so we mount
# a custom one which Piccolo provides (accessible at /private/docs):
private_app.mount("/docs/", swagger_ui(schema_url="/private/openapi.json"))

@private_app.get('/my-secret-endpoint/')
def my_endpoint():
    # This is just a normal FastAPI endpoint, and is protected by Session Auth
    pass

app.mount("/private/", private_app)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app)

You'll notice that there's basically two FastAPI apps - a root one, which contains anything which should be publicly accessible (such as the login endpoint) and a child app, which contains anything which should be protected by Session Auth.

from piccolo_api.

sinisaos avatar sinisaos commented on May 22, 2024 1

@wmshort This happens because session_logout() uses the HTTP POST method and you access it using GET.
If you try curl curl -X POST --cookie "id=yourcookiesvalue" http://localhost:8000/logout/ (or your request.url) you will see that you Successfully logged out. It's easier for me not to use session_logout() but a logout endpoint that I can access from /docs like in my previous example.

# your imports
from starlette.responses import JSONResponse

app = FastAPI(docs_url=None) 

app.mount("/docs/", swagger_ui(schema_url="../openapi.json"))

@app.post("/logout/", tags=["Logout"])
async def logout(request: Request):
    response = JSONResponse(
        {
            "message": "You are logged out",
        },
        status_code=200,
    )
    response.delete_cookie("id") # or response.delete_cookie("yourcookie")
    return response

from piccolo_api.

dantownsend avatar dantownsend commented on May 22, 2024 1

If you've got a HTML template, you can put something like this in to logout:

<form action="/private/logout/" method="POST">
    <!--
    You need to get the CSRF token. The CSRF middleware adds it to the FastAPI / Starlette request,
     so if you add the request to the Jinja context, you can access the CSRF token from the template.
     Alternatively you can get the csrftoken from the cookie using jQuery or something.
     -->
    <input name="csrftoken" type="hidden" value="{{ request.scope.get('csrftoken') }}" />
    <button>Logout</button>
</form>

An example of adding the request to the Jinja context:

async def my_endpoint(self, request: Request):
    template = ENVIRONMENT.get_template("app.html.jinja")
    content = template.render(request=request)
    return HTMLResponse(content)

from piccolo_api.

sinisaos avatar sinisaos commented on May 22, 2024

@wmshort Piccolo Admin use SessionAuth. You can also try something like this.

auth_middleware = partial(
    AuthenticationMiddleware,
    backend=SessionsAuthBackend(
        auth_table=BaseUser,
        session_table=SessionsBase,
        admin_only=False,
    ),
)

app = FastAPI(docs_url=None) 

app.mount("/docs/", swagger_ui(schema_url="../openapi.json"))
# login endpoint which which provide login form
app.mount(
    path="/login/",
    app=session_login(
        auth_table=BaseUser,
        session_table=SessionsBase,
        redirect_to="/docs/",
    ),
)

@app.post("/logout/", tags=["Logout"])
async def logout(request: Request):
    response = JSONResponse(
        {
            "message": "You are logged out",
        },
        status_code=200,
    )
    response.delete_cookie("id")
    return response

I hope this helps.

from piccolo_api.

wmshort avatar wmshort commented on May 22, 2024

Cool, thanks, I will tinker around with this! Maybe I am being daft, but how, in this example, do you hook up the auth_middleware to app? And are these endpoints the equivalent of what's available from piccolo_api.session_auth.endpoints?

Thanks again for your suggestions!

from piccolo_api.

sinisaos avatar sinisaos commented on May 22, 2024

@wmshort Yes. You need endpoints from piccolo_api.session_auth.endpoints.

from piccolo_api.

wmshort avatar wmshort commented on May 22, 2024

Thanks, both, this really helped! The key was thinking about them as distinct apps and separating out the different endpoints. The only sticky thing remaining is that the session_logout endpoint is giving me a "method not allowed" error, but everything else is running smoothly now.

from piccolo_api.

dantownsend avatar dantownsend commented on May 22, 2024

Yeah, it only supports POST. I had a look at the docs, and this isn't mentioned, so needs adding.

from piccolo_api.

wmshort avatar wmshort commented on May 22, 2024

Closing issue, as the last remaining question appears to be addressed by #82

from piccolo_api.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.