Skip to content

Commit 3fb2dd7

Browse files
committed
work around the csrf filter for app-to-app requests by sending the requesting app's domain in the Origin header
This makes the request appear like a CORS request sent by a browser, and if the origin is in the CORS whitelist will be accepted by the receiving server without a further CSRF check. CSRF checks are going to be a pain for server-to-server requests (and technically not required, but there's no clear way to safely disable them for server-to-server requests and not browser-to-server requests)
1 parent a70ef81 commit 3fb2dd7

5 files changed

Lines changed: 9 additions & 9 deletions

File tree

common-lib/src/main/scala/com/gu/mediaservice/GridClient.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ object ClientResponse {
3838
case class ClientErrorMessages(errorMessage: String, downstreamErrorMessage: String)
3939

4040
object GridClient extends LazyLogging {
41-
def apply(services: Services)(implicit wsClient: WSClient): GridClient =
42-
new GridClient(services)
41+
def apply(services: Services, originUri: String)(implicit wsClient: WSClient): GridClient =
42+
new GridClient(services, originUri)
4343

4444
sealed trait Response {
4545
def status: Int
@@ -96,7 +96,7 @@ object GridClient extends LazyLogging {
9696

9797
}
9898

99-
class GridClient(services: Services)(implicit wsClient: WSClient) extends LazyLogging {
99+
class GridClient(services: Services, originDomain: String)(implicit wsClient: WSClient) extends LazyLogging {
100100

101101
/*
102102
* `requestTimeout` will set the max duration of the request before timing out. You may also want to increase the
@@ -255,14 +255,14 @@ class GridClient(services: Services)(implicit wsClient: WSClient) extends LazyLo
255255

256256
def postUsage(usageType: String, data: JsObject, authFn: WSRequest => WSRequest)(implicit ec: ExecutionContext) = {
257257
val url = new URL(s"${services.usageBaseUri}/usages/$usageType")
258-
val request: WSRequest = wsClient.url(url.toString)
258+
val request: WSRequest = wsClient.url(url.toString).withHttpHeaders(("Origin", originDomain))
259259
val authorisedRequest = authFn(request)
260260
authorisedRequest.post(Json.obj("data" -> data)).map { response => validateResponse(response, url)}
261261
}
262262

263263
def putArchived(mediaId: String, authFn: WSRequest => WSRequest)(implicit ec: ExecutionContext) = {
264264
val url = new URL(s"${services.metadataBaseUri}/metadata/$mediaId/archived")
265-
val request = authFn(wsClient.url(url.toString))
265+
val request = authFn(wsClient.url(url.toString).withHttpHeaders(("Origin", originDomain)))
266266
request.put(Json.obj("data" -> JsTrue)).map { response => validateResponse(response, url)}
267267
}
268268
}

image-loader/app/ImageLoaderComponents.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class ImageLoaderComponents(context: Context) extends GridComponents(context, ne
2121
logger.info(s" $index -> ${processor.description}")
2222
}
2323

24-
private val gridClient = GridClient(config.services)(wsClient)
24+
private val gridClient = GridClient(config.services, config.services.loaderBaseUri)(wsClient)
2525

2626
val store = new ImageLoaderStore(config)
2727
val maybeIngestQueue = config.maybeIngestSqsQueueUrl.map(queueUrl => new SimpleSqsMessageConsumer(queueUrl, config))

media-api/app/controllers/MediaApi.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class MediaApi(
5050
)(implicit val ec: ExecutionContext) extends BaseController with MessageSubjects with ArgoHelpers with ContentDisposition {
5151

5252
val services: Services = new Services(config.domainRoot, config.serviceHosts, Set.empty)
53-
val gridClient: GridClient = GridClient(services)(ws)
53+
val gridClient: GridClient = GridClient(services, services.apiBaseUri)(ws)
5454

5555
// Process-local cache keyed on normalised query text. Stores the Bedrock Future so that
5656
// concurrent requests for the same query share a single in-flight Bedrock call, and

metadata-editor/app/controllers/EditsController.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class EditsController(
5959
import com.gu.mediaservice.lib.metadata.UsageRightsMetadataMapper.usageRightsToMetadata
6060

6161
val services: Services = new Services(config.domainRoot, config.serviceHosts, Set.empty)
62-
val gridClient: GridClient = GridClient(services)(ws)
62+
val gridClient: GridClient = GridClient(services, services.metadataBaseUri)(ws)
6363

6464
val metadataBaseUri = config.services.metadataBaseUri
6565
private val AuthenticatedAndAuthorised = auth andThen authorisation.CommonActionFilters.authorisedForArchive

thrall/app/ThrallComponents.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ThrallComponents(context: Context) extends GridComponents(context, new Thr
3131
es.ensureIndexExistsAndAliasAssigned()
3232

3333
val services: Services = new Services(config.domainRoot, config.serviceHosts, Set.empty)
34-
val gridClient: GridClient = GridClient(services)(wsClient)
34+
val gridClient: GridClient = GridClient(services, services.thrallBaseUri)(wsClient)
3535

3636
// before firing up anything to consume streams or say we are OK let's do the critical good to go check
3737
private val goodToGoCheckResult = Await.ready(GoodToGoCheck.run(es), 30 seconds)

0 commit comments

Comments
 (0)