Skip to content

Commit

Permalink
makes code and version changes
Browse files Browse the repository at this point in the history
  • Loading branch information
rishabhpoddar committed May 7, 2024
1 parent eee14d5 commit 817f5d1
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 56 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.0] - 2024-05-07

### Breaking change

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.
- Even if the ports of the URL you are querying are different compared to the `apiDomain`'s port ot the `sessionTokenBackendDomain` port (as long as the hostname is the same, or a subdomain of the `sessionTokenBackendDomain`): https://github.com/supertokens/supertokens-website/issues/217

## [0.2.7] - 2024-03-14

- New FDI version support: 1.19
Expand Down
2 changes: 1 addition & 1 deletion SuperTokensIOS.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = 'SuperTokensIOS'
s.version = "0.2.7"
s.version = "0.3.0"
s.summary = 'SuperTokens SDK for using login and session management functionality in iOS apps'

# This description is used to generate tags and improve search results.
Expand Down
83 changes: 39 additions & 44 deletions SuperTokensIOS/Classes/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,44 +63,38 @@ class NormalisedInputType {
}

internal static func sessionScopeHelper(sessionScope: String) throws -> String {
var trimmedSessionScope = sessionScope.trim()
var trimmedSessionScope = sessionScope.trim().lowercased()

if trimmedSessionScope.starts(with: ".") {
trimmedSessionScope = trimmedSessionScope.substring(fromIndex: 1)
}

if !trimmedSessionScope.starts(with: "http://") && !trimmedSessionScope.starts(with: "https://") {
trimmedSessionScope = "http://" + trimmedSessionScope
}

do {
guard let url: URL = URL(string: trimmedSessionScope), let host: String = url.host else {
throw SDKFailableError.failableError
}

trimmedSessionScope = host

if trimmedSessionScope.starts(with: ".") {
trimmedSessionScope = trimmedSessionScope.substring(fromIndex: 1)
}

return trimmedSessionScope

return host
} catch {
throw SuperTokensError.initError(message: "Please provide a valid sessionScope")
}
}

internal static func normaliseSessionScopeOrThrowError(sessionScope: String) throws -> String {
let noDotNormalised = try sessionScopeHelper(sessionScope: sessionScope)

if noDotNormalised == "localhost" || Utils.isIpAddress(input: noDotNormalised) {
return noDotNormalised
}

if sessionScope.starts(with: ".") {
return "." + noDotNormalised
}

return noDotNormalised
}

Expand Down Expand Up @@ -156,42 +150,43 @@ class NormalisedInputType {

internal class Utils {
internal static func shouldDoInterception(toCheckURL: String, apiDomain: String, cookieDomain: String?) throws -> Bool {
let _toCheckURL: String = try NormalisedURLDomain.normaliseUrlDomainOrThrowError(input: toCheckURL)
var _apiDomain: String = apiDomain

guard let urlObj: URL = URL(string: _toCheckURL), let hostname: String = urlObj.host else {
let normalizedToCheckURL = try NormalisedURLDomain.normaliseUrlDomainOrThrowError(input: toCheckURL)
guard let urlObj = URL(string: normalizedToCheckURL), let hostname = urlObj.host else {
throw SDKFailableError.failableError
}

var domain = hostname

if cookieDomain == nil {
domain = urlObj.port == nil ? domain : domain + ":" + "\(urlObj.port!)"
_apiDomain = try NormalisedURLDomain.normaliseUrlDomainOrThrowError(input: apiDomain)

guard let apiUrlObj: URL = URL(string: _apiDomain), let apiHostName: String = apiUrlObj.host else {
var apiDomainAndInputDomainMatch = false
if !apiDomain.isEmpty {
let normalizedApiDomain = try NormalisedURLDomain.normaliseUrlDomainOrThrowError(input: apiDomain)
guard let apiUrlObj = URL(string: normalizedApiDomain), let apiHostName = apiUrlObj.host else {
throw SDKFailableError.failableError
}

return domain == (apiUrlObj.port == nil ? apiHostName : apiHostName + ":" + "\(apiUrlObj.port!)")
apiDomainAndInputDomainMatch = domain == apiHostName
}

if cookieDomain == nil || apiDomainAndInputDomainMatch {
// even if cookieDomain isn't undefined, if there is an exact match
// of api domain, ignoring the port, we return true
return apiDomainAndInputDomainMatch
} else {
var normalisedCookieDomain = try NormalisedInputType.normaliseSessionScopeOrThrowError(sessionScope: cookieDomain!)

if cookieDomain!.split(separator: ":").count > 1 {
let portString: String = String(cookieDomain!.split(separator: ":")[cookieDomain!.split(separator: ":").count - 1])

if portString.isNumeric {
normalisedCookieDomain = normalisedCookieDomain + ":" + portString
domain = urlObj.port == nil ? domain : domain + ":" + "\(urlObj.port!)"
}
}

if cookieDomain!.starts(with: ".") {
return ("." + domain).hasSuffix(normalisedCookieDomain)
} else {
return domain == normalisedCookieDomain
let normalisedSessionDomain = try NormalisedInputType.normaliseSessionScopeOrThrowError(sessionScope: cookieDomain!)
// Using the matchesDomainOrSubdomain function to determine match
return matchesDomainOrSubdomain(domain: domain, str: normalisedSessionDomain)
}
}

private static func matchesDomainOrSubdomain(domain: String, str: String) -> Bool {
let parts = domain.split(separator: ".").map(String.init)

for i in 0..<parts.count {
let subdomainCandidate = parts[i...].joined(separator: ".")
if subdomainCandidate == str || ".\(subdomainCandidate)" == str {
return true
}
}

return false
}

internal static func isIpAddress(input: String) -> Bool {
Expand Down
2 changes: 1 addition & 1 deletion SuperTokensIOS/Classes/Version.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import Foundation

internal class Version {
static let supported_fdi: [String] = ["1.16", "1.17", "1.18", "1.19"]
static let sdkVersion = "0.2.7"
static let sdkVersion = "0.3.0"
}
50 changes: 40 additions & 10 deletions testHelpers/testapp/Tests/config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class ConfigTests: XCTestCase {
);
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3000", apiDomain: "localhost:3000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://localhost:3000", apiDomain: "https://localhost:3000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://localhost:3000", apiDomain: "https://localhost:3001", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost:3000", apiDomain: "http://localhost:3001", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3000", apiDomain: "localhost:3001", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost:3000", apiDomain: "http://localhost:3000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3000", apiDomain: "https://localhost:3000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost", apiDomain: "https://localhost", cookieDomain: nil));
Expand All @@ -31,19 +34,27 @@ class ConfigTests: XCTestCase {
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "127.0.0.1:3000", apiDomain: "https://127.0.0.1:3000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://127.0.0.1:3000", apiDomain: "https://127.0.0.1:3000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://127.0.0.1", apiDomain: "https://127.0.0.1", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost.org", apiDomain: "localhost.org", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost.org", apiDomain: "http://localhost.org", cookieDomain: nil));

// true cases with cookieDomain
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "api.example.com", apiDomain: "", cookieDomain: "api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://api.example.com", apiDomain: "", cookieDomain: "http://api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "api.example.com", apiDomain: "", cookieDomain: ".example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "api.example.com", apiDomain: "", cookieDomain: "example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "", cookieDomain: "http://api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "", cookieDomain: "https://api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: ".sub.api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: "sub.api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: ".api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: "api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: ".example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: "example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: ".example.com:3000"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: ".example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: "https://sub.api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com:3000", apiDomain: "", cookieDomain: ".api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com:3000", apiDomain: "", cookieDomain: "api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3000", apiDomain: "", cookieDomain: "localhost:3000"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://localhost:3000", apiDomain: "", cookieDomain: ".localhost:3000"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost", apiDomain: "", cookieDomain: "localhost"));
Expand All @@ -59,27 +70,46 @@ class ConfigTests: XCTestCase {
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub1.api.example.co.uk:3000", apiDomain: "", cookieDomain: ".api.example.co.uk"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.co.uk:3000", apiDomain: "", cookieDomain: ".api.example.co.uk"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.co.uk:3000", apiDomain: "", cookieDomain: "api.example.co.uk"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "", cookieDomain: "example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: ".sub.api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: "sub.api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: "api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com", apiDomain: "", cookieDomain: "example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: "example.com:3000"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "", cookieDomain: "api.example.com"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3000", apiDomain: "localhost:8080", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3001", apiDomain: "localhost", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com:3002", apiDomain: "https://api.example.com:3001", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost.org", apiDomain: "localhost.org:2000", cookieDomain: nil));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost.org", apiDomain: "localhost", cookieDomain: "localhost.org"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost", apiDomain: "localhost", cookieDomain: "localhost.org"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost", apiDomain: "", cookieDomain: "localhost:8080"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://localhost:80", apiDomain: "", cookieDomain: "localhost:8080"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "localhost:3000", apiDomain: "", cookieDomain: "localhost:8080"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: ".example.com:3001"));
XCTAssertTrue(try Utils.shouldDoInterception(toCheckURL: "http://127.0.0.1:3000", apiDomain: "", cookieDomain: "https://127.0.0.1:3010"));

// false cases with api
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "localhost:3001", apiDomain: "localhost:3000", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "localhost:3001", apiDomain: "example.com", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "localhost:3001", apiDomain: "localhost", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "localhost", apiDomain: "localhost.org", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "google.com", apiDomain: "localhost.org", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "http://google.com", apiDomain: "localhost.org", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://google.com", apiDomain: "localhost.org", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://google.com:8080", apiDomain: "localhost.org", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "https://a.api.example.com:3000", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://example.com", apiDomain: "https://api.example.com", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "https://a.api.example.com", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com", apiDomain: "https://example.com", cookieDomain: nil)));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://example.com:3001", apiDomain: "https://api.example.com:3001", cookieDomain: nil)));
XCTAssertTrue(
!(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com:3002", apiDomain: "https://api.example.com:3001", cookieDomain: nil))
);

// false cases with cookieDomain
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: ".example.com:3001")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: "example.com")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "localhost", apiDomain: "", cookieDomain: "localhost.org")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "google.com", apiDomain: "", cookieDomain: "localhost.org")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "http://google.com", apiDomain: "", cookieDomain: "localhost.org")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://google.com", apiDomain: "", cookieDomain: "localhost.org")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://google.com:8080", apiDomain: "", cookieDomain: "localhost.org")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://api.example.com:3000", apiDomain: "", cookieDomain: ".a.api.example.com")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.com:3000", apiDomain: "", cookieDomain: "localhost")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "http://127.0.0.1:3000", apiDomain: "", cookieDomain: "https://127.0.0.1:3010")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.co.uk:3000", apiDomain: "", cookieDomain: "api.example.co.uk")));
XCTAssertTrue(!(try Utils.shouldDoInterception(toCheckURL: "https://sub.api.example.co.uk", apiDomain: "", cookieDomain: "api.example.co.uk")));

// errors in input
do {
Expand Down

0 comments on commit 817f5d1

Please sign in to comment.