Skip to content

Commit

Permalink
check access-control-request-headers on options request for creds
Browse files Browse the repository at this point in the history
  • Loading branch information
fredr committed Nov 20, 2024
1 parent e5295b8 commit 0f0683b
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 10 deletions.
23 changes: 19 additions & 4 deletions runtimes/core/src/api/cors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::encore::runtime::v1 as pb;
use crate::encore::runtime::v1::gateway::CorsAllowedOrigins;
use anyhow::Context;
use axum::http::{HeaderName, HeaderValue};
use http::header::{ACCESS_CONTROL_REQUEST_HEADERS, AUTHORIZATION, COOKIE};
use std::collections::HashSet;
use std::str::FromStr;

Expand Down Expand Up @@ -84,14 +85,28 @@ pub fn config(cfg: &pb::gateway::Cors, meta: MetaHeaders) -> anyhow::Result<Cors
}
};

let request_has_creds = |req: &axum::http::request::Parts| -> bool {
if req.headers.contains_key(AUTHORIZATION) || req.headers.contains_key(COOKIE) {
return true;
}

if req.method == http::method::Method::OPTIONS {
return req
.headers
.get(ACCESS_CONTROL_REQUEST_HEADERS)
.and_then(|val| val.to_str().ok())
.map(|val| val.to_lowercase().contains("authorization"))
.unwrap_or(false);
}

false
};

let pred = move |origin: &HeaderValue, req: &axum::http::request::Parts| {
let Ok(origin) = origin.to_str() else {
return false;
};
let headers = &req.headers;
if headers.contains_key(axum::http::header::AUTHORIZATION)
|| headers.contains_key(axum::http::header::COOKIE)
{
if request_has_creds(req) {
with_creds.allows(origin)
} else {
without_creds.allows(origin)
Expand Down
4 changes: 2 additions & 2 deletions runtimes/core/src/api/cors/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ fn check_origins(cors: &CorsHeadersConfig, creds: bool, good: bool, origins: &[H
.expect("insert origin header");

if creds {
req.insert_header(AUTHORIZATION, HeaderValue::from_static("dummy"))
.expect("insert authorization header");
req.insert_header(ACCESS_CONTROL_REQUEST_HEADERS, AUTHORIZATION)
.expect("insert access-control-request-headers");
}

let mut resp = ResponseHeader::build(200, None).expect("construct response");
Expand Down
16 changes: 14 additions & 2 deletions runtimes/go/appruntime/apisdk/cors/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,20 @@ func Options(cfg *config.CORS, staticAllowedHeaders, staticExposedHeaders []stri
AllowOriginRequestFunc: func(r *http.Request, origin string) bool {
// If the request has credentials, look up origins in AllowOriginsWithCredentials.
// Credentials are cookies, authorization headers, or TLS client certificates.
hasCreds := len(r.Cookies()) > 0 || r.Header["Authorization"] != nil || (r.TLS != nil && len(r.TLS.PeerCertificates) > 0)
if hasCreds {
hasCreds := func(r *http.Request) bool {
if len(r.Cookies()) > 0 || r.Header["Authorization"] != nil || (r.TLS != nil && len(r.TLS.PeerCertificates) > 0) {
return true
}

if r.Method == "OPTIONS" {
if val := r.Header.Get("Access-Control-Request-Headers"); val != "" {
return strings.Contains(strings.ToLower(val), "authorization")
}
}

return false
}
if hasCreds(r) {
ok := hasUnsafeWildcardOriginWithCreds || sortedSliceContains(originsCreds, origin)
if !ok {
// Not an exact match. Check any glob origins.
Expand Down
4 changes: 2 additions & 2 deletions runtimes/go/appruntime/apisdk/cors/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ func TestOptions(t *testing.T) {
h := make(http.Header)
h.Set("Origin", o)
if creds {
h.Set("Authorization", "dummy")
h.Set("Access-Control-Request-Headers", "Authorization")
}
allowed := c.OriginAllowed(&http.Request{Header: h})
allowed := c.OriginAllowed(&http.Request{Header: h, Method: "OPTIONS"})
if allowed != good {
t.Fatalf("origin=%s creds=%v: got allowed=%v, want %v", o, creds, allowed, good)
} else {
Expand Down

0 comments on commit 0f0683b

Please sign in to comment.