@@ -16,43 +16,40 @@ import Foundation
16
16
17
17
private let kHttpsProtocol = " https: "
18
18
private 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
26
20
private let kFirebaseAuthAPIHost = " www.googleapis.com "
27
- private let kIdentityPlatformAPIHost = " identitytoolkit.googleapis.com "
28
-
29
21
private 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.
34
32
@available ( iOS 13 , tvOS 13 , macOS 10 . 15 , macCatalyst 13 , watchOS 7 , * )
35
33
class IdentityToolkitRequest {
36
- /// Gets the RPC's endpoint.
34
+ /// RPC endpoint name, e.g. "signInWithPassword" or full exchange path
37
35
let endpoint : String
38
-
39
36
/// Gets the client's API key used for the request.
40
37
var apiKey : String
41
-
42
38
/// The tenant ID of the request. nil if none is available.
43
39
let tenantID : String ?
44
-
45
40
/// The toggle of using Identity Platform endpoints.
46
41
let useIdentityPlatform : Bool
47
-
48
42
/// The toggle of using staging endpoints.
49
43
let useStaging : Bool
50
-
51
44
/// The type of the client that the request sent from, which should be CLIENT_TYPE_IOS;
52
45
var clientType : String
53
46
54
- private let _requestConfiguration : AuthRequestConfiguration
47
+ /// Optional local emulator host and port
48
+ var emulatorHostAndPort : String ? {
49
+ return _requestConfiguration. emulatorHostAndPort
50
+ }
55
51
52
+ private let _requestConfiguration : AuthRequestConfiguration
56
53
init ( endpoint: String , requestConfiguration: AuthRequestConfiguration ,
57
54
useIdentityPlatform: Bool = false , useStaging: Bool = false ) {
58
55
self . endpoint = endpoint
@@ -64,57 +61,76 @@ class IdentityToolkitRequest {
64
61
tenantID = requestConfiguration. auth? . tenantID
65
62
}
66
63
64
+ /// Override this if you need query parameters (default none)
67
65
func queryParams( ) -> String {
68
66
return " "
69
67
}
70
68
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.
72
75
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
75
81
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) "
81
93
} else if useStaging {
82
- apiHostAndPathPrefix = kIdentityPlatformStagingAPIHost
83
- apiProtocol = kHttpsProtocol
94
+ protocolScheme = kHttpsProtocol
95
+ hostPrefix = kRegionalGCIPStagingAPIHost
84
96
} else {
85
- apiHostAndPathPrefix = kIdentityPlatformAPIHost
86
- apiProtocol = kHttpsProtocol
97
+ protocolScheme = kHttpsProtocol
98
+ hostPrefix = kRegionalGCIPAPIHost
87
99
}
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) "
90
104
} 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) "
94
109
} else if useStaging {
95
- apiProtocol = kHttpsProtocol
96
- apiHostAndPathPrefix = kFirebaseAuthStagingAPIHost
110
+ protocolScheme = kHttpsProtocol
111
+ hostPrefix = kFirebaseAuthStagingAPIHost
97
112
} else {
98
- apiProtocol = kHttpsProtocol
99
- apiHostAndPathPrefix = kFirebaseAuthAPIHost
113
+ protocolScheme = kHttpsProtocol
114
+ hostPrefix = kFirebaseAuthAPIHost
100
115
}
101
116
urlString =
102
- " \( apiProtocol) // \( apiHostAndPathPrefix) /identitytoolkit/v3/relyingparty/ \( endpoint) ?key= \( apiKey) "
117
+ " \( protocolScheme) // \( hostPrefix) " +
118
+ " /identitytoolkit/v3/relyingparty/ \( endpoint) ?key= \( apiKey) "
103
119
}
104
120
guard let returnURL = URL ( string: " \( urlString) \( queryParams ( ) ) " ) else {
105
121
fatalError ( " Internal Auth error: Failed to generate URL for \( urlString) " )
106
122
}
107
123
return returnURL
108
124
}
109
125
110
- /// Returns the request's configuration.
111
- func requestConfiguration( ) -> AuthRequestConfiguration {
112
- _requestConfiguration
113
- }
126
+ // MARK: - Testing API
114
127
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
+ }
116
133
117
- static var host : String { gAPIHost }
118
134
static func setHost( _ host: String ) {
119
135
gAPIHost = host
120
136
}
0 commit comments