diff --git a/docs/content/docs/integrations/expo.mdx b/docs/content/docs/integrations/expo.mdx
index b44060aefb..3b89e980ab 100644
--- a/docs/content/docs/integrations/expo.mdx
+++ b/docs/content/docs/integrations/expo.mdx
@@ -160,16 +160,16 @@ Expo is a popular framework for building cross-platform apps with React Native.
// Development mode - Expo's exp:// scheme with local IP ranges
...(process.env.NODE_ENV === "development" ? [
- "exp://*/*", // Trust all Expo development URLs
- "exp://10.0.0.*:*/*", // Trust 10.0.0.x IP range
- "exp://192.168.*.*:*/*", // Trust 192.168.x.x IP range
- "exp://172.*.*.*:*/*", // Trust 172.x.x.x IP range
- "exp://localhost:*/*" // Trust localhost
+ "exp://", // Trust all Expo URLs (prefix matching)
+ "exp://**", // Trust all Expo URLs (wildcard matching)
+ "exp://192.168.*.*:*/**", // Trust 192.168.x.x IP range with any port and path
] : [])
]
})
```
+ For more information about trusted origins, see [here](/docs/reference/options#trustedorigins).
+
The wildcard patterns for `exp://` should only be used in development. In production, use your app's specific scheme (e.g., `myapp://`).
diff --git a/docs/content/docs/reference/options.mdx b/docs/content/docs/reference/options.mdx
index 135e69371f..43e6b3d4f3 100644
--- a/docs/content/docs/reference/options.mdx
+++ b/docs/content/docs/reference/options.mdx
@@ -95,8 +95,31 @@ export const auth = betterAuth({
})
```
-
- Make sure to provide the protocol prefix when using wildcard patterns. For example, `https://*.example.com` instead of `*.example.com`.
+#### Pattern Syntax
+
+| Pattern | Description |
+|---------|-------------|
+| `?` | Matches exactly one character (except `/`) |
+| `*` | Matches zero or more characters that don't cross `/` |
+| `**` | Matches zero or more characters including `/` |
+
+#### Pattern Examples
+
+| Pattern | Matches | Does Not Match |
+|---------|---------|----------------|
+| `http://*.example.com` | `http://api.example.com`
`http://app.example.com`
`http://api.app.example.com` | `https://api.example.com`
`http://example.com` |
+| `https://**.example.com` | `https://api.example.com`
`https://api.app.example.com` | `http://api.example.com` |
+| `https://example.com` | `https://example.com`
`https://example.com/path` | `https://api.example.com`
`http://example.com` |
+| `exp://192.168.*.*:*/**` | `exp://192.168.1.100:8081/path`
`exp://192.168.50.200:19000/auth/callback` | `exp://10.0.0.29:8081/path` |
+| `myapp://` | All URLs starting with `myapp://` | - |
+
+
+
+**Notes**
+
+- For `http://` and `https://` URLs, patterns match the full origin. Paths and query strings are ignored.
+- For custom schemes (like `exp://` or `myapp://`), patterns match against the full URL including paths when wildcards are present, or use prefix matching when no wildcards exist.
+- The separator is `/` (forward slash). This means `http://*.example.com` matches both `http://api.example.com` and `http://api.app.example.com`.
## `secret`
diff --git a/docs/content/docs/reference/security.mdx b/docs/content/docs/reference/security.mdx
index 3c8fd3520c..4e401bdd0f 100644
--- a/docs/content/docs/reference/security.mdx
+++ b/docs/content/docs/reference/security.mdx
@@ -161,8 +161,8 @@ Trusted origins also support custom schemes for mobile apps and browser extensio
trustedOrigins: [
"myapp://", // Mobile app scheme
"chrome-extension://YOUR_EXTENSION_ID", // Browser extension
- "exp://*/*", // Trust all Expo development URLs
- "exp://10.0.0.*:*/*", // Trust 10.0.0.x IP range with any port
+ "exp://**", // Trust all Expo development URLs
+ "exp://10.0.0.*:*/**", // Trust 10.0.0.x IP range with any port
]
}
```
diff --git a/packages/better-auth/src/auth/trusted-origins.ts b/packages/better-auth/src/auth/trusted-origins.ts
index fea9e5c097..0ceb8a2886 100644
--- a/packages/better-auth/src/auth/trusted-origins.ts
+++ b/packages/better-auth/src/auth/trusted-origins.ts
@@ -26,7 +26,9 @@ export const matchesOriginPattern = (
return false;
}
- if (pattern.includes("*")) {
+ // Check if pattern contains wildcard characters (*, **, or ?)
+ const hasWildcard = pattern.includes("*") || pattern.includes("?");
+ if (hasWildcard) {
// For protocol-specific wildcards, match the full origin
if (pattern.includes("://")) {
return wildcardMatch(pattern)(getOrigin(url) || url);