Auth microservice

Authentication is managed by auth microservice, that exposes these endpoints:

  • /auth/login: redirects to the OIDC provider where the users can log in. Accepts redirect_on_callback.

Login endpoint implementation

@router.get("/login")
async def login(
    request: Request,
    redirect_on_callback: str,
    current_user: Union[dict, None] = Depends(deps.get_current_user),
):
    if not current_user:
        redirect_uri = f"{settings.COMPLETE_SERVER_NAME}/callback"
        response = await oauth.smartcommunitylab.authorize_redirect(request, redirect_uri)
        response.set_cookie(
            key="redirect_on_callback",
            value=redirect_on_callback,
            httponly=True,
            secure=settings.PRODUCTION_MODE,
        )
        return response
    else:
        # if user already logged in, redirect to redirect_on_callback
        return RedirectResponse(redirect_on_callback)

Callback code implementation

Gets tokens returned by the OIDC provider and sets the access_token to auth_token cookie [samesite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite). Then, redirects the browser to the path specified by the redirect_on_callback cookie after deleting it.

@router.get("/callback")
async def callback(request: Request, redirect_on_callback: Optional[str] = Cookie(None), collection: AsyncIOMotorCollection = Depends(get_collection)):
    token = await oauth.smartcommunitylab.authorize_access_token(request)
    await crud.get_or_create(collection, token["access_token"])

    response = RedirectResponse(redirect_on_callback)

    response.set_cookie(
        key="auth_token",
        value=token["access_token"],
        expires=token["expires_in"],
        httponly=True,
        samesite='strict',
        domain=settings.SERVER_NAME,
        secure=settings.PRODUCTION_MODE,
    )

    response.delete_cookie(key="redirect_on_callback")
    return response

Logout implementation

  • /auth/logout: logouts user. Accepts redirect_on_callback.

@router.get("/logout")
async def logout(redirect_on_callback: str = "/"):
    response = RedirectResponse(url=redirect_on_callback)
    response.delete_cookie(key="auth_token")
    return response