@@ -16,43 +16,40 @@ import Foundation
1616
1717private let kHttpsProtocol = " https: "
1818private let kHttpProtocol = " http: "
19-
20- private let kEmulatorHostAndPrefixFormat = " %@/%@ "
21-
22- /// Host for server API calls. This should be changed via
23- /// `IdentityToolkitRequest.setHost(_ host:)` for testing purposes only.
24- private nonisolated ( unsafe) var gAPIHost = " www.googleapis.com "
25-
19+ // Legacy GCIP v1 hosts
2620private let kFirebaseAuthAPIHost = " www.googleapis.com "
27- private let kIdentityPlatformAPIHost = " identitytoolkit.googleapis.com "
28-
2921private let kFirebaseAuthStagingAPIHost = " staging-www.sandbox.googleapis.com "
30- private let kIdentityPlatformStagingAPIHost =
31- " staging-identitytoolkit.sandbox.googleapis.com "
32-
33- /// Represents a request to an identity toolkit endpoint.
22+ // Regional R-GCIP v2 hosts
23+ private let kRegionalGCIPAPIHost = " identityplatform.googleapis.com "
24+ private let kRegionalGCIPStagingAPIHost = " staging-identityplatform.sandbox.googleapis.com "
25+ #if compiler(>=6)
26+ private nonisolated ( unsafe) var gAPIHost = " www.googleapis.com "
27+ #else
28+ private var gAPIHost = " www.googleapis.com "
29+ #endif
30+ /// Represents a request to an Identity Toolkit endpoint, routing either to
31+ /// legacy GCIP v1 or regionalized R-GCIP v2 based on presence of tenantID.
3432@available ( iOS 13 , tvOS 13 , macOS 10 . 15 , macCatalyst 13 , watchOS 7 , * )
3533class IdentityToolkitRequest {
36- /// Gets the RPC's endpoint.
34+ /// RPC endpoint name, e.g. "signInWithPassword" or full exchange path
3735 let endpoint : String
38-
3936 /// Gets the client's API key used for the request.
4037 var apiKey : String
41-
4238 /// The tenant ID of the request. nil if none is available.
4339 let tenantID : String ?
44-
4540 /// The toggle of using Identity Platform endpoints.
4641 let useIdentityPlatform : Bool
47-
4842 /// The toggle of using staging endpoints.
4943 let useStaging : Bool
50-
5144 /// The type of the client that the request sent from, which should be CLIENT_TYPE_IOS;
5245 var clientType : String
5346
54- private let _requestConfiguration : AuthRequestConfiguration
47+ /// Optional local emulator host and port
48+ var emulatorHostAndPort : String ? {
49+ return _requestConfiguration. emulatorHostAndPort
50+ }
5551
52+ private let _requestConfiguration : AuthRequestConfiguration
5653 init ( endpoint: String , requestConfiguration: AuthRequestConfiguration ,
5754 useIdentityPlatform: Bool = false , useStaging: Bool = false ) {
5855 self . endpoint = endpoint
@@ -64,57 +61,76 @@ class IdentityToolkitRequest {
6461 tenantID = requestConfiguration. auth? . tenantID
6562 }
6663
64+ /// Override this if you need query parameters (default none)
6765 func queryParams( ) -> String {
6866 return " "
6967 }
7068
71- /// Returns the request's full URL.
69+ /// Provide the same configuration for AuthBackend
70+ func requestConfiguration( ) -> AuthRequestConfiguration {
71+ return _requestConfiguration
72+ }
73+
74+ /// Build the full URL, branching on whether tenantID is set.
7275 func requestURL( ) -> URL {
73- let apiProtocol : String
74- let apiHostAndPathPrefix : String
76+ guard let auth = _requestConfiguration. auth else {
77+ fatalError ( " Internal Auth error: missing Auth on requestConfiguration " )
78+ }
79+ let protocolScheme : String
80+ let hostPrefix : String
7581 let urlString : String
76- let emulatorHostAndPort = _requestConfiguration. emulatorHostAndPort
77- if useIdentityPlatform {
78- if let emulatorHostAndPort = emulatorHostAndPort {
79- apiProtocol = kHttpProtocol
80- apiHostAndPathPrefix = " \( emulatorHostAndPort) / \( kIdentityPlatformAPIHost) "
82+ // R-GCIP v2 if location is non-nil
83+ let tenant = _requestConfiguration. tenantId
84+ if let region = _requestConfiguration. location {
85+ // Project identifier
86+ guard let project = auth. app? . options. projectID else {
87+ fatalError ( " Internal Auth error: missing projectID " )
88+ }
89+ // Choose emulator, staging, or prod host
90+ if let emu = emulatorHostAndPort {
91+ protocolScheme = kHttpProtocol
92+ hostPrefix = " \( emu) / \( kRegionalGCIPAPIHost) "
8193 } else if useStaging {
82- apiHostAndPathPrefix = kIdentityPlatformStagingAPIHost
83- apiProtocol = kHttpsProtocol
94+ protocolScheme = kHttpsProtocol
95+ hostPrefix = kRegionalGCIPStagingAPIHost
8496 } else {
85- apiHostAndPathPrefix = kIdentityPlatformAPIHost
86- apiProtocol = kHttpsProtocol
97+ protocolScheme = kHttpsProtocol
98+ hostPrefix = kRegionalGCIPAPIHost
8799 }
88- urlString = " \( apiProtocol) // \( apiHostAndPathPrefix) /v2/ \( endpoint) ?key= \( apiKey) "
89-
100+ // Regionalized v2 path
101+ urlString =
102+ " \( protocolScheme) // \( hostPrefix) /v2/projects/ \( project) "
103+ + " /locations/ \( region) /tenants/ \( tenant) /idpConfigs/ \( endpoint) ?key= \( apiKey) "
90104 } else {
91- if let emulatorHostAndPort = emulatorHostAndPort {
92- apiProtocol = kHttpProtocol
93- apiHostAndPathPrefix = " \( emulatorHostAndPort) / \( kFirebaseAuthAPIHost) "
105+ // Legacy GCIP v1 branch
106+ if let emu = emulatorHostAndPort {
107+ protocolScheme = kHttpProtocol
108+ hostPrefix = " \( emu) / \( kFirebaseAuthAPIHost) "
94109 } else if useStaging {
95- apiProtocol = kHttpsProtocol
96- apiHostAndPathPrefix = kFirebaseAuthStagingAPIHost
110+ protocolScheme = kHttpsProtocol
111+ hostPrefix = kFirebaseAuthStagingAPIHost
97112 } else {
98- apiProtocol = kHttpsProtocol
99- apiHostAndPathPrefix = kFirebaseAuthAPIHost
113+ protocolScheme = kHttpsProtocol
114+ hostPrefix = kFirebaseAuthAPIHost
100115 }
101116 urlString =
102- " \( apiProtocol) // \( apiHostAndPathPrefix) /identitytoolkit/v3/relyingparty/ \( endpoint) ?key= \( apiKey) "
117+ " \( protocolScheme) // \( hostPrefix) " +
118+ " /identitytoolkit/v3/relyingparty/ \( endpoint) ?key= \( apiKey) "
103119 }
104120 guard let returnURL = URL ( string: " \( urlString) \( queryParams ( ) ) " ) else {
105121 fatalError ( " Internal Auth error: Failed to generate URL for \( urlString) " )
106122 }
107123 return returnURL
108124 }
109125
110- /// Returns the request's configuration.
111- func requestConfiguration( ) -> AuthRequestConfiguration {
112- _requestConfiguration
113- }
126+ // MARK: - Testing API
114127
115- // MARK: Internal API for development
128+ /// For testing: override the global host for legacy flows
129+ static var host : String {
130+ get { gAPIHost }
131+ set { gAPIHost = newValue }
132+ }
116133
117- static var host : String { gAPIHost }
118134 static func setHost( _ host: String ) {
119135 gAPIHost = host
120136 }
0 commit comments