Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: shouldDoInterceptionBasedOnUrl returns true for any valid subdomain #251

Merged
merged 4 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

## [20.0.0] - 2024-04-03

### Breaking changes

- The `shouldDoInterceptionBasedOnUrl` function now returns true if `sessionTokenBackendDomain` is a valid subdomain of the URL's domain. This aligns with the behavior of browsers when sending cookies to subdomains.

**Before:**

```javascript
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "api.example.com") // false
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".api.example.com") // true
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "example.com") // false
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".example.com") // true
```

**After:**

```javascript
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "api.example.com") // true
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".api.example.com") // true
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "example.com") // true
shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".example.com") // true
```

The behavior in previous versions differed, as `shouldDoInterceptionBasedOnUrl` returned `false` unless `sessionTokenBackendDomain` had an explicit leading dot. This breaking change now assumes any subdomain is valid, making the interception consistent with browser cookie policies.

rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
## [19.0.1] - 2024-03-18
- Fixes test server

Expand Down
2 changes: 1 addition & 1 deletion bundle/bundle.js

Large diffs are not rendered by default.

6 changes: 1 addition & 5 deletions lib/build/recipeImplementation.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions lib/build/utils/index.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 20 additions & 1 deletion lib/build/utils/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/build/version.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/build/version.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions lib/ts/recipeImplementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { supported_fdi } from "./version";
import { logDebugMessage } from "./logger";
import { STGeneralError } from "./error";
import { addInterceptorsToXMLHttpRequest } from "./xmlhttprequest";
import { normaliseSessionScopeOrThrowError, normaliseURLDomainOrThrowError } from "./utils";
import { matchesDomainOrSubdomain, normaliseSessionScopeOrThrowError, normaliseURLDomainOrThrowError } from "./utils";
import DateProviderReference from "./utils/dateProvider";

export default function RecipeImplementation(recipeImplInput: {
Expand Down Expand Up @@ -303,11 +303,7 @@ export default function RecipeImplementation(recipeImplInput: {
domain = urlObj.port === "" ? domain : domain + ":" + urlObj.port;
}
}
if (sessionTokenBackendDomain.startsWith(".")) {
rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
return ("." + domain).endsWith(normalisedsessionDomain);
} else {
return domain === normalisedsessionDomain;
}
return matchesDomainOrSubdomain(domain, normalisedsessionDomain);
}
},

Expand Down
20 changes: 20 additions & 0 deletions lib/ts/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,23 @@ export function getNormalisedUserContext(userContext?: any): any {

return userContext;
}

/**
* Checks if a given string matches any subdomain or the main domain of a specified hostname.
*
* @param {string} hostname - The hostname to derive subdomains from.
* @param {string} str - The string to compare against the subdomains.
* @returns {boolean} True if the string matches any subdomain or the main domain, otherwise false.
*/
export function matchesDomainOrSubdomain(hostname: string, str: string): boolean {
const parts = hostname.split(".");

for (let i = 0; i < parts.length; i++) {
const subdomainCandidate = parts.slice(i).join(".");
if (subdomainCandidate === str || `.${subdomainCandidate}` === str) {
return true;
}
}

return false;
}
2 changes: 1 addition & 1 deletion lib/ts/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
export const package_version = "19.0.1";
export const package_version = "20.0.0";

export const supported_fdi = ["1.16", "1.17", "1.18", "1.19"];
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "supertokens-website",
"version": "19.0.1",
"version": "20.0.0",
"description": "frontend sdk for website to be used for auth solution.",
"main": "index.js",
"dependencies": {
Expand Down
11 changes: 8 additions & 3 deletions test/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,22 @@ describe("Config tests", function () {
assert(shouldDoInterceptionBasedOnUrl("api.example.com", "", "api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("http://api.example.com", "", "http://api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("api.example.com", "", ".example.com"));
assert(shouldDoInterceptionBasedOnUrl("api.example.com", "", "example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://api.example.com", "", "http://api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://api.example.com", "", "https://api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".sub.api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "sub.api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", ".example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com", "", "example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", ".example.com:3000"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", "example.com:3000"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", ".example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", "example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", "https://sub.api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://api.example.com:3000", "", ".api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("https://api.example.com:3000", "", "api.example.com"));
assert(shouldDoInterceptionBasedOnUrl("localhost:3000", "", "localhost:3000"));
assert(shouldDoInterceptionBasedOnUrl("https://localhost:3000", "", ".localhost:3000"));
assert(shouldDoInterceptionBasedOnUrl("localhost", "", "localhost"));
Expand Down Expand Up @@ -112,15 +120,12 @@ describe("Config tests", function () {

// false cases with cookieDomain
assert(!shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", ".example.com:3001"));
assert(!shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", "example.com"));
assert(!shouldDoInterceptionBasedOnUrl("https://api.example.com:3000", "", ".a.api.example.com"));
assert(!shouldDoInterceptionBasedOnUrl("https://sub.api.example.com:3000", "", "localhost"));
assert(!shouldDoInterceptionBasedOnUrl("http://127.0.0.1:3000", "", "https://127.0.0.1:3010"));
assert(!shouldDoInterceptionBasedOnUrl(window.location.hostname, "", "localhost"));
assert(!shouldDoInterceptionBasedOnUrl(window.location.hostname, "", ".localhost"));
assert(!shouldDoInterceptionBasedOnUrl(window.location.hostname, "", "localhost:2000"));
assert(!shouldDoInterceptionBasedOnUrl("https://sub.api.example.co.uk:3000", "", "api.example.co.uk"));
assert(!shouldDoInterceptionBasedOnUrl("https://sub.api.example.co.uk", "", "api.example.co.uk"));

// errors in input
try {
rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading