forked from forks/microblog.pub
remote follow: use HTML redirect to work around CSP issue
In Chrome, I get the following when trying to use the remote follow form: Refused to send form data to 'https://example.com/remote_follow' because it violates the following Content Security Policy directive: "form-action 'self'". It seems some browsers (but notably not Firefox) apply the form-action policy to the redirect target in addition to the initial form submission endpoint. See: https://github.com/w3c/webappsec-csp/issues/8 In that thread, this workaround is suggested.
This commit is contained in:
parent
793a939046
commit
9db7bdf0fb
1 changed files with 23 additions and 3 deletions
26
app/main.py
26
app/main.py
|
@ -1,4 +1,5 @@
|
||||||
import base64
|
import base64
|
||||||
|
import html
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
@ -38,6 +39,7 @@ from starlette.background import BackgroundTask
|
||||||
from starlette.datastructures import Headers
|
from starlette.datastructures import Headers
|
||||||
from starlette.datastructures import MutableHeaders
|
from starlette.datastructures import MutableHeaders
|
||||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||||
|
from starlette.responses import HTMLResponse
|
||||||
from starlette.responses import JSONResponse
|
from starlette.responses import JSONResponse
|
||||||
from starlette.types import Message
|
from starlette.types import Message
|
||||||
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware # type: ignore
|
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware # type: ignore
|
||||||
|
@ -254,6 +256,25 @@ class ActivityPubResponse(JSONResponse):
|
||||||
media_type = "application/activity+json"
|
media_type = "application/activity+json"
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLRedirectResponse(HTMLResponse):
|
||||||
|
"""
|
||||||
|
Similar to RedirectResponse, but uses a 200 response with HTML.
|
||||||
|
|
||||||
|
Needed for remote redirects on form submission endpoints,
|
||||||
|
since our CSP policy disallows remote form submission.
|
||||||
|
https://github.com/w3c/webappsec-csp/issues/8#issuecomment-810108984
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
url: str,
|
||||||
|
) -> None:
|
||||||
|
super().__init__(
|
||||||
|
content=f'<a href="{html.escape(url)}">Continue to remote resource</a>',
|
||||||
|
headers={"Refresh": "0;url=" + url},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get(config.NavBarItems.NOTES_PATH)
|
@app.get(config.NavBarItems.NOTES_PATH)
|
||||||
async def index(
|
async def index(
|
||||||
request: Request,
|
request: Request,
|
||||||
|
@ -961,7 +982,7 @@ async def post_remote_follow(
|
||||||
request: Request,
|
request: Request,
|
||||||
csrf_check: None = Depends(verify_csrf_token),
|
csrf_check: None = Depends(verify_csrf_token),
|
||||||
profile: str = Form(),
|
profile: str = Form(),
|
||||||
) -> RedirectResponse:
|
) -> HTMLRedirectResponse:
|
||||||
if not profile.startswith("@"):
|
if not profile.startswith("@"):
|
||||||
profile = f"@{profile}"
|
profile = f"@{profile}"
|
||||||
|
|
||||||
|
@ -970,9 +991,8 @@ async def post_remote_follow(
|
||||||
# TODO(ts): error message to user
|
# TODO(ts): error message to user
|
||||||
raise HTTPException(status_code=404)
|
raise HTTPException(status_code=404)
|
||||||
|
|
||||||
return RedirectResponse(
|
return HTMLRedirectResponse(
|
||||||
remote_follow_template.format(uri=ID),
|
remote_follow_template.format(uri=ID),
|
||||||
status_code=302,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue