Embedding and cross-origin access
Use this guide if you administer Posit Connect and need to control which sites can embed content or make cross-origin requests. Before you begin, identify the external sites that need to embed Connect content or access resources from Connect. For related guidance, see Embedding content and the Configuration appendix.
Control which sites can embed content
The X-Frame-Options HTTP header controls which content a web browser can embed inside other content. This header defends against clickjack attacks, in which an attacker has your users interact with a sensitive service without their knowledge.
For the X-Frame-Options header, Connect distinguishes between “dashboard” and “user” content. The dashboard includes the internal services and assets shipped with Connect. User content includes anything a user uploads, such as reports, applications, and APIs.
Server.FrameOptionsContent sets the X-Frame-Options header value for user-uploaded content. The default, NONE, omits the header so that other sites, such as intranet portals, can embed user content in an iframe. If other sites do not need to embed your content, set this option to SAMEORIGIN. Only sites on the same server can then embed that content. The Connect dashboard uses iframes to present user content, so avoid setting this option to DENY.
Server.FrameOptionsDashboard configures the X-Frame-Options header value for internal services and assets provided with Connect. Its default is DENY. This prevents other sites from embedding the Connect dashboard. This setting adds protection against clickjacking attacks on the Connect dashboard. If you plan to embed the dashboard elsewhere, you might need to tune this setting.
Some browsers do not support all advertised values for this header, as the MDN documentation explains. Connect does not restrict the values of these headers.
Authenticate embedded content
You can embed Connect content in other websites with an iframe. Connect access controls still govern embedded content, and users might need to authenticate if they are not already signed in to Connect. To support a smooth redirect, configure both Connect and the embedded content to redirect users to the original site after authentication.
Server.TrustedRedirectlists the domains that Connect can redirect users to after a successful authentication attempt. By default, the list is empty, so Connect trusts no external domains. Add this setting multiple times, as in this example:
/etc/rstudio-connect/rstudio-connect.gcfg
[Server]
TrustedRedirect = "https://parent-site.com"
TrustedRedirect = "https://another-site.com"- Add the full redirect URL to the iframe source as a query parameter named
framesource. Use this example:
<iframe src="https://connect-site.com/app?framesource=https://parent-site.com/connectStuff">Browsers can restrict or omit the Referer header based on the embedding page’s Referrer-Policy settings. The framesource parameter explicitly provides the embedding page’s URL so Connect can reliably redirect back after authentication completes.
Enable CORS
Cross-Origin Resource Sharing (CORS) is a security standard that lets web applications on one domain access resources from a server on a different domain. This standard is especially important when web applications on different domains use the API in Connect.
Understand how CORS works
When a web application requests resources from a different domain, the following steps occur:
- The browser first sends a preflight request using HTTP OPTIONS to check whether the server allows cross-origin requests.
- The server responds with CORS headers that indicate what it allows:
- Which origins can access the resources
- Which HTTP methods the server permits (GET, POST, etc.)
- Which headers the request can include
- Whether requests can send credentials (cookies, HTTP authentication)
Configure CORS in Connect
Connect disables CORS support by default. To enable CORS, follow these steps:
- Set
CORS.Enabled = truein your configuration. - Configure allowed origins with
CORS.AllowOrigin. - Connect preconfigures other CORS headers for common use cases:
- Connect sets
Access-Control-Allow-MethodstoGET, POST, PUT, PATCH, DELETE, HEAD. - Connect sets
Access-Control-Allow-HeaderstoOrigin, Content-Length, Content-Type. - Connect sets
Access-Control-Allow-Credentialstotrue. - Connect sets
Access-Control-Max-Ageto 12 hours.
- Connect sets
For configuration details, see the CORS Configuration section.
CORS matches allowed origins by scheme, hostname, and port. If you omit the scheme from an AllowOrigin value, Connect assumes http. If you omit the port, Connect assumes port 80.
Add CORS support in your application
Your application might also need CORS handling in its own code, in addition to CORS.Enabled = true. Add OPTIONS as a supported HTTP method. The OPTIONS response must return status code 200 and include the following headers:
"Access-Control-Allow-Origin: *"
"Access-Control-Allow-Methods: DELETE, POST, GET, OPTIONS, PUT, HEAD"
"Access-Control-Allow-Headers: *"
Using * allows all domains or headers, respectively. You can narrow the list as required by your organization’s security policies.
Customize this Plumber API example for your code and use case.
plumber.R
#' @filter cors
cors <- function(req, res) {
res$setHeader("Access-Control-Allow-Origin", "*")
if (req$REQUEST_METHOD == "OPTIONS") {
res$setHeader("Access-Control-Allow-Methods","*")
res$setHeader("Access-Control-Allow-Headers", "*")
res$setHeader("Access-Control-Allow-Credentials", "true")
res$status <- 200
return(list())
} else {
plumber::forward()
}
}