SecureTokenRequest.swift 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright 2023 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. @objc(FIRSecureTokenRequestGrantType) enum SecureTokenRequestGrantType: Int {
  16. case authorizationCode
  17. case refreshToken
  18. var value: String {
  19. switch self {
  20. case .refreshToken:
  21. return kFIRSecureTokenServiceGrantTypeRefreshToken
  22. case .authorizationCode:
  23. return kFIRSecureTokenServiceGrantTypeAuthorizationCode
  24. }
  25. }
  26. }
  27. /** @var kFIRSecureTokenServiceGetTokenURLFormat
  28. @brief The format of the secure token service URLs. Requires string format substitution with
  29. the client's API Key.
  30. */
  31. private let kFIRSecureTokenServiceGetTokenURLFormat = "https://%@/v1/token?key=%@"
  32. /** @var kFIREmulatorURLFormat
  33. @brief The format of the emulated secure token service URLs. Requires string format substitution
  34. with the emulator host, the gAPIHost, and the client's API Key.
  35. */
  36. private let kFIREmulatorURLFormat = "http://%@/%@/v1/token?key=%@"
  37. /** @var kFIRSecureTokenServiceGrantTypeRefreshToken
  38. @brief The string value of the @c FIRSecureTokenRequestGrantTypeRefreshToken request type.
  39. */
  40. private let kFIRSecureTokenServiceGrantTypeRefreshToken = "refresh_token"
  41. /** @var kFIRSecureTokenServiceGrantTypeAuthorizationCode
  42. @brief The string value of the @c FIRSecureTokenRequestGrantTypeAuthorizationCode request type.
  43. */
  44. private let kFIRSecureTokenServiceGrantTypeAuthorizationCode = "authorization_code"
  45. /** @var kGrantTypeKey
  46. @brief The key for the "grantType" parameter in the request.
  47. */
  48. private let kGrantTypeKey = "grantType"
  49. /** @var kScopeKey
  50. @brief The key for the "scope" parameter in the request.
  51. */
  52. private let kScopeKey = "scope"
  53. /** @var kRefreshTokenKey
  54. @brief The key for the "refreshToken" parameter in the request.
  55. */
  56. private let kRefreshTokenKey = "refreshToken"
  57. /** @var kCodeKey
  58. @brief The key for the "code" parameter in the request.
  59. */
  60. private let kCodeKey = "code"
  61. /** @var gAPIHost
  62. @brief Host for server API calls.
  63. */
  64. private var gAPIHost = "securetoken.googleapis.com"
  65. /** @class FIRSecureTokenRequest
  66. @brief Represents the parameters for the token endpoint.
  67. */
  68. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
  69. @objc(FIRSecureTokenRequest) public class SecureTokenRequest: NSObject, AuthRPCRequest {
  70. /** @property grantType
  71. @brief The type of grant requested.
  72. @see FIRSecureTokenRequestGrantType
  73. */
  74. var grantType: SecureTokenRequestGrantType
  75. /** @property scope
  76. @brief The scopes requested (a comma-delimited list of scope strings.)
  77. */
  78. var scope: String?
  79. /** @property refreshToken
  80. @brief The client's refresh token.
  81. */
  82. @objc public var refreshToken: String?
  83. /** @property code
  84. @brief The client's authorization code (legacy Gitkit "ID Token").
  85. */
  86. var code: String?
  87. /** @property APIKey
  88. @brief The client's API Key.
  89. */
  90. @objc public let apiKey: String
  91. /** @var response
  92. @brief The corresponding response for this request
  93. */
  94. @objc public var response: AuthRPCResponse = SecureTokenResponse()
  95. let _requestConfiguration: AuthRequestConfiguration
  96. public func requestConfiguration() -> AuthRequestConfiguration {
  97. _requestConfiguration
  98. }
  99. @objc public static func authCodeRequest(code: String,
  100. requestConfiguration: AuthRequestConfiguration)
  101. -> SecureTokenRequest {
  102. SecureTokenRequest(
  103. grantType: .authorizationCode,
  104. scope: nil,
  105. refreshToken: nil,
  106. code: code,
  107. requestConfiguration: requestConfiguration
  108. )
  109. }
  110. @objc public static func refreshRequest(refreshToken: String,
  111. requestConfiguration: AuthRequestConfiguration)
  112. -> SecureTokenRequest {
  113. SecureTokenRequest(
  114. grantType: .refreshToken,
  115. scope: nil,
  116. refreshToken: refreshToken,
  117. code: nil,
  118. requestConfiguration: requestConfiguration
  119. )
  120. }
  121. init(grantType: SecureTokenRequestGrantType, scope: String?, refreshToken: String?,
  122. code: String?, requestConfiguration: AuthRequestConfiguration) {
  123. self.grantType = grantType
  124. self.scope = scope
  125. self.refreshToken = refreshToken
  126. self.code = code
  127. apiKey = requestConfiguration.apiKey
  128. _requestConfiguration = requestConfiguration
  129. }
  130. public func requestURL() -> URL {
  131. let urlString: String
  132. if let emulatorHostAndPort = _requestConfiguration.emulatorHostAndPort {
  133. urlString = "http://\(emulatorHostAndPort)/\(gAPIHost)/v1/token?key=\(apiKey)"
  134. } else {
  135. urlString = "https://\(gAPIHost)/v1/token?key=\(apiKey)"
  136. }
  137. return URL(string: urlString)!
  138. }
  139. public func containsPostBody() -> Bool { true }
  140. public func unencodedHTTPRequestBody() throws -> [String: AnyHashable] {
  141. var postBody: [String: AnyHashable] = [
  142. kGrantTypeKey: grantType.value,
  143. ]
  144. if let scope = scope {
  145. postBody[kScopeKey] = scope
  146. }
  147. if let refreshToken = refreshToken {
  148. postBody[kRefreshTokenKey] = refreshToken
  149. }
  150. if let code = code {
  151. postBody[kCodeKey] = code
  152. }
  153. return postBody
  154. }
  155. // MARK: Internal API for development
  156. static var host: String { gAPIHost }
  157. static func setHost(_ host: String) {
  158. gAPIHost = host
  159. }
  160. }