Configurable CORS credentials (#456)

* Configurable CORS credentials

* update readme
This commit is contained in:
Aine 2025-04-05 18:08:29 +00:00 committed by GitHub
parent f4084969b6
commit 218f0ba03c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 62 additions and 0 deletions

View File

@ -27,6 +27,7 @@
* [Configuration](#configuration) * [Configuration](#configuration)
* [Prefilling login form](#prefilling-login-form) * [Prefilling login form](#prefilling-login-form)
* [Restricting available homeserver](#restricting-available-homeserver) * [Restricting available homeserver](#restricting-available-homeserver)
* [Configuring CORS credentials](#configuring-cors-credentials)
* [Protecting appservice managed users](#protecting-appservice-managed-users) * [Protecting appservice managed users](#protecting-appservice-managed-users)
* [Adding custom menu items](#adding-custom-menu-items) * [Adding custom menu items](#adding-custom-menu-items)
* [Usage](#usage) * [Usage](#usage)
@ -111,6 +112,7 @@ The following changes are already implemented:
* [Respect base url (`BASE_PATH` / `vite build --base`) when loading `config.json`](https://github.com/etkecc/synapse-admin/pull/274) * [Respect base url (`BASE_PATH` / `vite build --base`) when loading `config.json`](https://github.com/etkecc/synapse-admin/pull/274)
* [Add Users' Account Data tab](https://github.com/etkecc/synapse-admin/pull/276) * [Add Users' Account Data tab](https://github.com/etkecc/synapse-admin/pull/276)
* [Make bulk registration CSV import more user-friendly](https://github.com/etkecc/synapse-admin/pull/411) * [Make bulk registration CSV import more user-friendly](https://github.com/etkecc/synapse-admin/pull/411)
* [Configurable CORS Credentials](https://github.com/etkecc/synapse-admin/pull/456)
#### exclusive for [etke.cc](https://etke.cc) customers #### exclusive for [etke.cc](https://etke.cc) customers
@ -180,6 +182,12 @@ You can restrict the homeserver(s), so that the user can no longer define it him
[Documentation](./docs/restrict-hs.md) [Documentation](./docs/restrict-hs.md)
### Configuring CORS credentials
You can configure the CORS credentials mode for the Synapse Admin instance.
[Documentation](./docs/cors-credentials.md)
### Protecting appservice managed users ### Protecting appservice managed users
To avoid accidental adjustments of appservice-managed users (e.g., puppets created by a bridge) and breaking the bridge, To avoid accidental adjustments of appservice-managed users (e.g., puppets created by a bridge) and breaking the bridge,

View File

@ -28,6 +28,12 @@ In this case, you could provide the configuration in the `/.well-known/matrix/cl
The homeserver URL should be the _actual_ homeserver URL, and not the delegated one. The homeserver URL should be the _actual_ homeserver URL, and not the delegated one.
Example: `https://matrix.example.com` or `https://synapse.example.net` Example: `https://matrix.example.com` or `https://synapse.example.net`
[More details](restrict-hs.md) [More details](restrict-hs.md)
* `corsCredentials` - configure the CORS credentials for the Synapse Admin instance.
It accepts the following values:
* `same-origin` (default): Cookies will be sent only if the request is made from the same origin as the server.
* `include`: Cookies will be sent regardless of the origin of the request.
* `omit`: Cookies will not be sent with the request.
[More details](cors-credentials.md)
* `asManagedUsers` - protect system user accounts managed by appservices (such as bridges) / system (such as bots) from accidental changes. * `asManagedUsers` - protect system user accounts managed by appservices (such as bridges) / system (such as bots) from accidental changes.
By defining a list of MXID regex patterns, you can protect these accounts from accidental changes. By defining a list of MXID regex patterns, you can protect these accounts from accidental changes.
Example: `^@baibot:example\\.com$`, `^@slackbot:example\\.com$`, `^@slack_[a-zA-Z0-9\\-]+:example\\.com$`, `^@telegrambot:example\\.com$`, `^@telegram_[a-zA-Z0-9]+:example\\.com$` Example: `^@baibot:example\\.com$`, `^@slackbot:example\\.com$`, `^@slack_[a-zA-Z0-9\\-]+:example\\.com$`, `^@telegrambot:example\\.com$`, `^@telegram_[a-zA-Z0-9]+:example\\.com$`

35
docs/cors-credentials.md Normal file
View File

@ -0,0 +1,35 @@
# CORS Credentials
If you'd like to use cookie-based authentication
(for example, [ForwardAuth with Authelia](https://github.com/Awesome-Technologies/synapse-admin/issues/655)),
you can configure the `corsCredentials` option in the `config.json` file or in the `/.well-known/matrix/client` file.
## Configuration
> [Documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#including_credentials)
The `corsCredentials` option accepts the following values:
* `same-origin` (default): Cookies will be sent only if the request is made from the same origin as the server.
* `include`: Cookies will be sent regardless of the origin of the request.
* `omit`: Cookies will not be sent with the request.
[Configuration options](config.md)
### config.json
```json
{
"corsCredentials": "include"
}
```
### `/.well-known/matrix/client`
```json
{
"cc.etke.synapse-admin": {
"corsCredentials": "include"
}
}
```

View File

@ -35,6 +35,7 @@ describe("authProvider", () => {
Accept: "application/json", Accept: "application/json",
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
credentials: "same-origin",
method: "POST", method: "POST",
}); });
expect(localStorage.getItem("base_url")).toEqual("http://example.com"); expect(localStorage.getItem("base_url")).toEqual("http://example.com");
@ -66,6 +67,7 @@ describe("authProvider", () => {
Accept: "application/json", Accept: "application/json",
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
credentials: "same-origin",
method: "POST", method: "POST",
}); });
expect(localStorage.getItem("base_url")).toEqual("https://example.com"); expect(localStorage.getItem("base_url")).toEqual("https://example.com");
@ -88,6 +90,7 @@ describe("authProvider", () => {
Authorization: "Bearer foo", Authorization: "Bearer foo",
}), }),
method: "POST", method: "POST",
credentials: "same-origin",
user: { authenticated: true, token: "Bearer foo" }, user: { authenticated: true, token: "Bearer foo" },
}); });
expect(localStorage.getItem("access_token")).toBeNull(); expect(localStorage.getItem("access_token")).toBeNull();

View File

@ -23,6 +23,7 @@ const authProvider: AuthProvider = {
console.log("login "); console.log("login ");
let options: Options = { let options: Options = {
method: "POST", method: "POST",
credentials: GetConfig().corsCredentials,
body: JSON.stringify( body: JSON.stringify(
Object.assign( Object.assign(
{ {
@ -151,6 +152,7 @@ const authProvider: AuthProvider = {
const options: Options = { const options: Options = {
method: "POST", method: "POST",
credentials: GetConfig().corsCredentials,
user: { user: {
authenticated: true, authenticated: true,
token: `Bearer ${access_token}`, token: `Bearer ${access_token}`,

View File

@ -14,6 +14,7 @@ import {
} from "react-admin"; } from "react-admin";
import { returnMXID } from "../utils/mxid"; import { returnMXID } from "../utils/mxid";
import { GetConfig } from "../utils/config";
import { MatrixError, displayError } from "../utils/error"; import { MatrixError, displayError } from "../utils/error";
const CACHED_MANY_REF: Record<string, any> = {}; const CACHED_MANY_REF: Record<string, any> = {};
@ -22,6 +23,7 @@ const CACHED_MANY_REF: Record<string, any> = {};
const jsonClient = async (url: string, options: Options = {}) => { const jsonClient = async (url: string, options: Options = {}) => {
const token = localStorage.getItem("access_token"); const token = localStorage.getItem("access_token");
console.log("httpClient " + url); console.log("httpClient " + url);
options.credentials = GetConfig().corsCredentials;
if (token !== null) { if (token !== null) {
options.user = { options.user = {
authenticated: true, authenticated: true,

View File

@ -1,5 +1,6 @@
export interface Config { export interface Config {
restrictBaseUrl: string | string[]; restrictBaseUrl: string | string[];
corsCredentials: string;
asManagedUsers: RegExp[]; asManagedUsers: RegExp[];
menu: MenuItem[]; menu: MenuItem[];
etkeccAdmin?: string; etkeccAdmin?: string;
@ -16,6 +17,7 @@ export const WellKnownKey = "cc.etke.synapse-admin";
// current configuration // current configuration
let config: Config = { let config: Config = {
restrictBaseUrl: "", restrictBaseUrl: "",
corsCredentials: "same-origin",
asManagedUsers: [], asManagedUsers: [],
menu: [], menu: [],
etkeccAdmin: "" etkeccAdmin: ""
@ -69,6 +71,10 @@ export const LoadConfig = (context: any) => {
config.restrictBaseUrl = context.restrictBaseUrl as string | string[]; config.restrictBaseUrl = context.restrictBaseUrl as string | string[];
} }
if (context?.corsCredentials) {
config.corsCredentials = context.corsCredentials;
}
if (context?.asManagedUsers) { if (context?.asManagedUsers) {
config.asManagedUsers = context.asManagedUsers.map((regex: string) => new RegExp(regex)); config.asManagedUsers = context.asManagedUsers.map((regex: string) => new RegExp(regex));
} }