MagicMirrorOrg/MagicMirror · warning
This device is not allowed to access your mirror. <br> Pleas
Error message
This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.
What it means
MagicMirror's `ipAccessControl` middleware (js/ip_access_control.js:79) rejects any HTTP request whose client IP is not in the configured `ipWhitelist`. Instead of proceeding with `next()`, it responds with HTTP 403 and this HTML/text message, and logs a warning via `Log.warn`. This is intentional access control: the mirror only serves devices explicitly allowed by the whitelist (which may include the special value `[]` to allow all, or entries like `127.0.0.1`, `::ffff:127.0.0.1`, subnets, or `ddns` names).
Source
Thrown at js/ip_access_control.js:79
*/
function ipAccessControl (whitelist) {
// Empty whitelist means allow all
if (!Array.isArray(whitelist) || whitelist.length === 0) {
return function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
next();
};
}
return function (req, res, next) {
const clientIp = resolveClientIp(req);
if (isAllowed(clientIp, whitelist)) {
res.header("Access-Control-Allow-Origin", "*");
next();
} else {
Log.warn(`IP ${clientIp} is not allowed to access the mirror`);
res.status(403).send("This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.");
}
};
}
/**
* Creates a Socket.IO `allowRequest` handler that enforces the same IP whitelist as the HTTP middleware.
* This closes the gap where Socket.IO handshakes bypassed the Express-only `ipAccessControl` middleware.
* @param {string[]} whitelist - Array of allowed IP addresses or CIDR ranges
* @returns {(req: object, callback: (err: string | null, success: boolean) => void) => void} Socket.IO allowRequest handler
*/
function socketIpAccessControl (whitelist) {
// Empty whitelist means allow all
if (!Array.isArray(whitelist) || whitelist.length === 0) {
return function (req, callback) {
callback(null, true); // allow the connection
};
}
View on GitHub (pinned to 4b4a59534f)
Solutions
- Add the client's IP (both IPv4 and IPv6-mapped forms, e.g. '192.168.1.10' and '::ffff:192.168.1.10') to `ipWhitelist` in config.js and restart the mirror.
- For a trusted LAN with no access control, set `ipWhitelist: []` — an empty array allows all addresses.
- If behind a reverse proxy, whitelist the proxy address and configure the proxy to pass the real client IP (X-Forwarded-For/Express 'trust proxy'), since the middleware checks the apparent peer IP.
- For dynamic remote access, use a DDNS whitelist entry with `ddns: true` rather than a static IP.
- Check the server log line `IP <address> is not allowed to access the mirror` to learn the exact IP string the server sees, then whitelist that literal.
Example fix
// before (config.js — default, localhost only) ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1', '::1'], // after — allow one LAN device over IPv4+IPv6, or use [] to allow all ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1', '::1', '192.168.1.10', '::ffff:192.168.1.10'], // or: ipWhitelist: [],
Defensive patterns
Strategy: validation
Validate before calling
// Client-side pre-check before loading the mirror:
const WHITELISTED = ['127.0.0.1', '::ffff:127.0.0.1', '::1', '192.168.1.10'];
async function checkAccess(baseUrl) {
const res = await fetch(baseUrl, { redirect: 'manual' });
if (res.status === 403) throw new Error('Device IP not in mirror ipWhitelist');
return res.ok;
} Type guard
function isWhitelistConfig(v) {
return Array.isArray(v) && v.every(e => typeof e === 'string' || (typeof e === 'object' && e !== null && typeof e.ip === 'string'));
} Try / catch
try {
const ok = await checkAccess('http://mirror.local:8080');
} catch (e) {
// e.message mentions ipWhitelist -> fix config.js on the server, not client code
console.error('Access blocked; add this device IP to ipWhitelist in config.js', e);
} Prevention
- Log the exact IP string the server sees (from `IP ... is not allowed`) and whitelist that literal, including the ::ffff: prefix
- Always list both IPv4 and IPv6-mapped forms for each allowed device
- Use `ipWhitelist: []` for trusted LANs to eliminate this class of failure
- When behind a reverse proxy, configure Express `trust proxy` and whitelist accordingly
- After changing ipWhitelist, restart the MagicMirror process — the config is read at startup
When it happens
Trigger: An HTTP request arrives from a client IP that `isAllowed(clientIp, whitelist)` evaluates as not matching any entry in `config.ipWhitelist` — e.g. default whitelist only allows localhost but you browse from another LAN device; IPv6 requests arriving as `::1` or `::ffff:192.168.x.x` while the whitelist only lists IPv4 forms; a reverse proxy forwards so the seen IP is the proxy's; Socket.IO `allowRequest` enforces the same whitelist and rejects the socket handshake.
Common situations: Opening the mirror from a phone/other computer on the LAN while `ipWhitelist` is left at the default `['127.0.0.1', '::ffff:127.0.0.1', '::1']`; Docker/Kubernetes deployments where the container sees the bridge/proxy IP instead of the real client IP; adding an IPv4 entry but the browser connects over IPv6; using a DDNS hostname without the required `ddns: true` flag on the whitelist entry.
Related errors
- CORS proxy is disabled
- Forbidden: domain not in corsDomainWhitelist
- <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8
- Forbidden: private or reserved addresses are not allowed
- [calendar] Your are using the deprecated config values 'colo
AI-assisted analysis of MagicMirrorOrg/MagicMirror@4b4a59534f (2026-08-31).
Data as JSON: /api/errors/8561363a99d1839d.
Report an issue: GitHub.