RedditWebAuthHelper.swift 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import Foundation
  2. enum RedditWebAuthHelper {
  3. static let redditHomeURL = URL(string: "https://www.reddit.com")!
  4. static func isOAuthProviderURL(_ url: URL) -> Bool {
  5. guard let host = url.host?.lowercased() else { return false }
  6. let oauthHosts = [
  7. "accounts.google.com",
  8. "appleid.apple.com",
  9. "idmsa.apple.com",
  10. "login.microsoftonline.com",
  11. "login.live.com",
  12. "account.live.com",
  13. "login.microsoft.com",
  14. "www.facebook.com",
  15. "m.facebook.com",
  16. "facebook.com",
  17. "auth0.com",
  18. ]
  19. if oauthHosts.contains(where: { host == $0 || host.hasSuffix(".\($0)") }) {
  20. return true
  21. }
  22. if host == "google.com" || host.hasSuffix(".google.com") {
  23. let path = url.path.lowercased()
  24. return path.contains("oauth")
  25. || path.contains("signin")
  26. || path.contains("gsi")
  27. }
  28. if host == "facebook.com" || host.hasSuffix(".facebook.com") {
  29. let path = url.path.lowercased()
  30. return path.contains("oauth") || path.contains("login") || path.contains("dialog")
  31. }
  32. if host.hasSuffix(".auth0.com") {
  33. return true
  34. }
  35. return false
  36. }
  37. static func isRedditHomeURL(_ url: URL) -> Bool {
  38. guard isRedditURL(url) else { return false }
  39. let host = url.host?.lowercased() ?? ""
  40. let isMainSite = host == "reddit.com"
  41. || host == "www.reddit.com"
  42. || host == "new.reddit.com"
  43. || host == "old.reddit.com"
  44. guard isMainSite else { return false }
  45. let path = url.path.lowercased()
  46. return path.isEmpty || path == "/" || path == "/home"
  47. }
  48. static func isRedditURL(_ url: URL) -> Bool {
  49. guard let host = url.host?.lowercased() else { return false }
  50. let redditHosts = [
  51. "reddit.com",
  52. "www.reddit.com",
  53. "old.reddit.com",
  54. "new.reddit.com",
  55. "accounts.reddit.com",
  56. "oauth.reddit.com",
  57. "reddit.app.link",
  58. "redd.it",
  59. ]
  60. return redditHosts.contains(where: { host == $0 || host.hasSuffix(".\($0)") })
  61. }
  62. static func looksLikeLoggedInURL(_ url: URL) -> Bool {
  63. guard isRedditURL(url) else { return false }
  64. let path = url.path.lowercased()
  65. let blockedPaths = [
  66. "/login",
  67. "/register",
  68. "/password",
  69. "/account/login",
  70. ]
  71. if blockedPaths.contains(where: { path.hasPrefix($0) }) {
  72. return false
  73. }
  74. if url.host?.lowercased() == "accounts.reddit.com" {
  75. return path.isEmpty || path == "/" || path.hasPrefix("/api/")
  76. }
  77. return true
  78. }
  79. static func oauthCallbackHost(for url: URL) -> String {
  80. guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
  81. return "accounts.reddit.com"
  82. }
  83. let redirectURI = components.queryItems?.first(where: { $0.name == "redirect_uri" })?.value
  84. ?? components.queryItems?.first(where: { $0.name == "redirect_url" })?.value
  85. if let redirectURI,
  86. let redirectURL = URL(string: redirectURI),
  87. let host = redirectURL.host?.lowercased(),
  88. isRedditURL(redirectURL) {
  89. return host
  90. }
  91. return "accounts.reddit.com"
  92. }
  93. }