CORS & Auth Basics AI-generated
CORS
CORS is on by default for every mock service (turn it off via Generate CORS Headers: Disabled under a Service's Fine-Tuning section, see Services - useful if you want to author the headers yourself, or deliberately test a client against a CORS-non-compliant backend). Response headers are only ever generated when the request itself carries an Origin header - non-browser calls (plain SOAP, server-to-server) are unaffected either way. Exact behavior depends on the request shape:
- Every request with an
OrigingetsAccess-Control-Allow-Originset to that exact origin (never*),Access-Control-Allow-Credentials: true(so thatfetch()withcredentials: "include"works; no credentials are ever sent back), andAccess-Control-Allow-Methodswith the method of the request. AnOPTIONSthat does not say which method it asks about gets all the methods:GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS. - Preflight requests - a browser's
OPTIONSprobe ahead of a non-simple method/header - getAccess-Control-Allow-MethodsandAccess-Control-Allow-Headersechoing back exactly what the browser asked for, plusAccess-Control-Max-Age: 7200so that the browser remembers the answer for two hours (the longest time every browser honours) instead of asking before each call. A preflight for a private network (Access-Control-Request-Private-Network) is answered withAccess-Control-Allow-Private-Network: true. A request that carriesAuthorizationalso getsAuthorizationinAccess-Control-Allow-Headers, which the*wildcard would not cover. - Other requests get
Access-Control-Expose-Headerslisting the headers of the response that the page script could not read otherwise: every one except the always readable ones (Cache-Control,Content-Language,Content-Length,Content-Type,Expires,Last-Modified,Pragma),Set-Cookieand the connection-level ones. Your own custom headers and the generatedETagare in the list. Varyis*unless the reaction sets its own, which means that nothing is cached (the generatedETagis random). If the reaction sets its ownVarywithoutOrigin,Originis added to it, since the answer depends on the origin.- Forwarded responses - a reaction that forwards to another server - have the upstream
Access-Control-Allow-Originreplaced by the origin of the caller. What the upstream server allows is of no use to this caller; everything else the upstream says stays. - Errors - a script error or any other HTTP 500 raised by MockMotor - carry the same headers as the successful answers of a service with CORS enabled, so that the page can read the error. A service with Generate CORS Headers: Disabled gets none, errors included.
To override the automatically-generated headers for a specific reaction, set them explicitly in that reaction's Custom Headers section (see Reactions) - an explicit header there wins over the automatic one, except in a forwarded response, whose Access-Control-Allow-Origin is always the caller's. If the reaction sets Access-Control-Allow-Origin: *, Access-Control-Allow-Credentials is not added: browsers reject that combination.
Basic HTTP Authentication
To mock an endpoint that requires HTTP Basic Auth, match on the presence/value of the Authorization header in a reaction's Match Options script (e.g. http.headers['Authorization']==null for the "missing credentials" case), and set that reaction's status to 401 with a WWW-Authenticate response header - ordinary reaction authoring, no special Basic Auth feature needed.
JWT-secured mocks
MockMotor has a native JWT object available to JavaScript reactions (not XQuery ones) for signing, decoding and verifying tokens, using the HS256, HS384 or HS512 algorithms - enough to build a small, fully self-contained mock login+authenticated-endpoint flow without any external auth service.
| Function | Does |
|---|---|
JWT.encode(header, payload, secret) | Signs a new token. var token = JWT.encode(header, payload, "password123"); |
JWT.decode(token, secret) | Parses a token to JSON without verifying it - adds an error field if it's malformed. |
JWT.verify(token, secret) | Decodes and validates - a bad signature or unsupported algorithm is a hard error (HTTP 500), not a soft failure. |
Three fields are auto-populated from an incoming Authorization: Bearer <token> header, so you rarely need to parse it yourself: JWT.token (the raw token string, or null), JWT.header and JWT.payload (parsed objects, or {} if there's no token). Common uses: generate a token as part of a mocked login response; read JWT.payload fields to drive account selection/routing on a subsequent "authenticated" request; check standard claims like exp (expiration) or nbf (not-before) to simulate an expired- or not-yet-valid-token error.