diff --git a/app/backend/app.py b/app/backend/app.py index 8ab388fee3..1b2ee4a0d5 100644 --- a/app/backend/app.py +++ b/app/backend/app.py @@ -677,6 +677,8 @@ def create_app(): logging.basicConfig(level=os.getenv("APP_LOG_LEVEL", default_level)) if allowed_origin := os.getenv("ALLOWED_ORIGIN"): - app.logger.info("CORS enabled for %s", allowed_origin) - cors(app, allow_origin=allowed_origin, allow_methods=["GET", "POST"]) + allowed_origin = allowed_origin.split(";") + if len(allowed_origin) > 0: + app.logger.info("CORS enabled for %s", allowed_origin) + cors(app, allow_origin=allowed_origin, allow_methods=["GET", "POST"]) return app diff --git a/infra/core/host/appservice.bicep b/infra/core/host/appservice.bicep index 20ef5707e7..7f8363cb27 100644 --- a/infra/core/host/appservice.bicep +++ b/infra/core/host/appservice.bicep @@ -49,11 +49,6 @@ param authenticationIssuerUri string = '' param publicNetworkAccess string = 'Enabled' param enableUnauthenticatedAccess bool = false -var msftAllowedOrigins = [ 'https://portal.azure.com', 'https://ms.portal.azure.com' ] -var loginEndpoint = environment().authentication.loginEndpoint -var loginEndpointFixed = lastIndexOf(loginEndpoint, '/') == length(loginEndpoint) - 1 ? substring(loginEndpoint, 0, length(loginEndpoint) - 1) : loginEndpoint -var allMsftAllowedOrigins = !(empty(clientAppId)) ? union(msftAllowedOrigins, [ loginEndpointFixed ]) : msftAllowedOrigins - // .default must be the 1st scope for On-Behalf-Of-Flow combined consent to work properly // Please see https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow#default-and-combined-consent var requiredScopes = [ 'api://${serverAppId}/.default', 'openid', 'profile', 'email', 'offline_access' ] @@ -71,7 +66,7 @@ var coreConfig = { functionAppScaleLimit: functionAppScaleLimit != -1 ? functionAppScaleLimit : null healthCheckPath: healthCheckPath cors: { - allowedOrigins: union(allMsftAllowedOrigins, allowedOrigins) + allowedOrigins: allowedOrigins } } diff --git a/infra/main.bicep b/infra/main.bicep index 4d9de25ec4..22fb7ce2c5 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -191,6 +191,16 @@ var tags = { 'azd-env-name': environmentName } var tenantIdForAuth = !empty(authTenantId) ? authTenantId : tenantId var authenticationIssuerUri = '${environment().authentication.loginEndpoint}${tenantIdForAuth}/v2.0' +// Configure CORS for allowing different web apps to use the backend +// For more information please see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +var msftAllowedOrigins = [ 'https://portal.azure.com', 'https://ms.portal.azure.com' ] +var loginEndpoint = environment().authentication.loginEndpoint +var loginEndpointFixed = lastIndexOf(loginEndpoint, '/') == length(loginEndpoint) - 1 ? substring(loginEndpoint, 0, length(loginEndpoint) - 1) : loginEndpoint +var allMsftAllowedOrigins = !(empty(clientAppId)) ? union(msftAllowedOrigins, [ loginEndpointFixed ]) : msftAllowedOrigins +var allowedOrigins = union(split(allowedOrigin, ';'), allMsftAllowedOrigins) +// Filter out any empty origin strings and remove any duplicate origins +var allowedOriginsEnv = join(reduce(filter(allowedOrigins, o => length(trim(o)) > 0), [], (cur, next) => union(cur, [next])), ';') + @description('Whether the deployment is running on GitHub Actions') param runningOnGh string = '' @@ -283,7 +293,7 @@ module backend 'core/host/appservice.bicep' = { managedIdentity: true virtualNetworkSubnetId: isolation.outputs.appSubnetId publicNetworkAccess: publicNetworkAccess - allowedOrigins: [ allowedOrigin ] + allowedOrigins: allowedOrigins clientAppId: clientAppId serverAppId: serverAppId enableUnauthenticatedAccess: enableUnauthenticatedAccess @@ -336,7 +346,7 @@ module backend 'core/host/appservice.bicep' = { AZURE_AUTH_TENANT_ID: tenantIdForAuth AZURE_AUTHENTICATION_ISSUER_URI: authenticationIssuerUri // CORS support, for frontends on other hosts - ALLOWED_ORIGIN: allowedOrigin + ALLOWED_ORIGIN: allowedOriginsEnv USE_VECTORS: useVectors USE_GPT4V: useGPT4V USE_USER_UPLOAD: useUserUpload @@ -868,4 +878,5 @@ output AZURE_USERSTORAGE_RESOURCE_GROUP string = storageResourceGroup.name output AZURE_USE_AUTHENTICATION bool = useAuthentication +output ALLOWED_ORIGIN string = allowedOriginsEnv output BACKEND_URI string = backend.outputs.uri