VerifyAssertionResponse.swift 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. /** @class FIRVerifyAssertionResponse
  16. @brief Represents the response from the verifyAssertion endpoint.
  17. @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/verifyAssertion
  18. */
  19. class VerifyAssertionResponse: AuthRPCResponse, AuthMFAResponse {
  20. required init() {}
  21. /** @property federatedID
  22. @brief The unique ID identifies the IdP account.
  23. */
  24. var federatedID: String?
  25. /** @property providerID
  26. @brief The IdP ID. For white listed IdPs it's a short domain name e.g. google.com, aol.com,
  27. live.net and yahoo.com. If the "providerId" param is set to OpenID OP identifer other than
  28. the whilte listed IdPs the OP identifier is returned. If the "identifier" param is federated
  29. ID in the createAuthUri request. The domain part of the federated ID is returned.
  30. */
  31. var providerID: String?
  32. /** @property localID
  33. @brief The RP local ID if it's already been mapped to the IdP account identified by the
  34. federated ID.
  35. */
  36. var localID: String?
  37. /** @property email
  38. @brief The email returned by the IdP. NOTE: The federated login user may not own the email.
  39. */
  40. var email: String?
  41. /** @property inputEmail
  42. @brief It's the identifier param in the createAuthUri request if the identifier is an email. It
  43. can be used to check whether the user input email is different from the asserted email.
  44. */
  45. var inputEmail: String?
  46. /** @property originalEmail
  47. @brief The original email stored in the mapping storage. It's returned when the federated ID is
  48. associated to a different email.
  49. */
  50. var originalEmail: String?
  51. /** @property oauthRequestToken
  52. @brief The user approved request token for the OpenID OAuth extension.
  53. */
  54. var oauthRequestToken: String?
  55. /** @property oauthScope
  56. @brief The scope for the OpenID OAuth extension.
  57. */
  58. var oauthScope: String?
  59. /** @property firstName
  60. @brief The first name of the user.
  61. */
  62. var firstName: String?
  63. /** @property lastName
  64. @brief The last name of the user.
  65. */
  66. var lastName: String?
  67. /** @property fullName
  68. @brief The full name of the user.
  69. */
  70. var fullName: String?
  71. /** @property nickName
  72. @brief The nick name of the user.
  73. */
  74. var nickName: String?
  75. /** @property displayName
  76. @brief The display name of the user.
  77. */
  78. var displayName: String?
  79. /** @property idToken
  80. @brief Either an authorization code suitable for performing an STS token exchange, or the
  81. access token from Secure Token Service, depending on whether @c returnSecureToken is set
  82. on the request.
  83. */
  84. private(set) var idToken: String?
  85. /** @property approximateExpirationDate
  86. @brief The approximate expiration date of the access token.
  87. */
  88. var approximateExpirationDate: Date?
  89. /** @property refreshToken
  90. @brief The refresh token from Secure Token Service.
  91. */
  92. var refreshToken: String?
  93. /** @property action
  94. @brief The action code.
  95. */
  96. var action: String?
  97. /** @property language
  98. @brief The language preference of the user.
  99. */
  100. var language: String?
  101. /** @property timeZone
  102. @brief The timezone of the user.
  103. */
  104. var timeZone: String?
  105. /** @property photoURL
  106. @brief The URI of the accessible profile picture.
  107. */
  108. var photoURL: URL?
  109. /** @property dateOfBirth
  110. @brief The birth date of the IdP account.
  111. */
  112. var dateOfBirth: String?
  113. /** @property context
  114. @brief The opaque value used by the client to maintain context info between the authentication
  115. request and the IDP callback.
  116. */
  117. var context: String?
  118. /** @property verifiedProvider
  119. @brief When action is 'map', contains the idps which can be used for confirmation.
  120. */
  121. var verifiedProvider: [String]?
  122. /** @property needConfirmation
  123. @brief Whether the assertion is from a non-trusted IDP and need account linking confirmation.
  124. */
  125. var needConfirmation: Bool = false
  126. /** @property emailRecycled
  127. @brief It's true if the email is recycled.
  128. */
  129. var emailRecycled: Bool = false
  130. /** @property emailVerified
  131. @brief The value is true if the IDP is also the email provider. It means the user owns the
  132. email.
  133. */
  134. var emailVerified: Bool = false
  135. /** @property isNewUser
  136. @brief Flag indicating that the user signing in is a new user and not a returning user.
  137. */
  138. var isNewUser: Bool = false
  139. /** @property profile
  140. @brief Dictionary containing the additional IdP specific information.
  141. */
  142. var profile: [String: Any]?
  143. /** @property username
  144. @brief The name of the user.
  145. */
  146. var username: String?
  147. /** @property oauthIDToken
  148. @brief The ID token for the OpenID OAuth extension.
  149. */
  150. var oauthIDToken: String?
  151. /** @property oauthExpirationDate
  152. @brief The approximate expiration date of the oauth access token.
  153. */
  154. var oauthExpirationDate: Date?
  155. /** @property oauthAccessToken
  156. @brief The access token for the OpenID OAuth extension.
  157. */
  158. var oauthAccessToken: String?
  159. /** @property oauthSecretToken
  160. @brief The secret for the OpenID OAuth extention.
  161. */
  162. var oauthSecretToken: String?
  163. /** @property pendingToken
  164. @brief The pending ID Token string.
  165. */
  166. var pendingToken: String?
  167. // MARK: - AuthMFAResponse
  168. private(set) var mfaPendingCredential: String?
  169. private(set) var mfaInfo: [AuthProtoMFAEnrollment]?
  170. func setFields(dictionary: [String: AnyHashable]) throws {
  171. federatedID = dictionary["federatedId"] as? String
  172. providerID = dictionary["providerId"] as? String
  173. localID = dictionary["localId"] as? String
  174. emailRecycled = dictionary["emailRecycled"] as? Bool ?? false
  175. emailVerified = dictionary["emailVerified"] as? Bool ?? false
  176. email = dictionary["email"] as? String
  177. inputEmail = dictionary["inputEmail"] as? String
  178. originalEmail = dictionary["originalEmail"] as? String
  179. oauthRequestToken = dictionary["oauthRequestToken"] as? String
  180. oauthScope = dictionary["oauthScope"] as? String
  181. firstName = dictionary["firstName"] as? String
  182. lastName = dictionary["lastName"] as? String
  183. fullName = dictionary["fullName"] as? String
  184. nickName = dictionary["nickName"] as? String
  185. displayName = dictionary["displayName"] as? String
  186. idToken = dictionary["idToken"] as? String
  187. if let expiresIn = dictionary["expiresIn"] as? String {
  188. approximateExpirationDate = Date(timeIntervalSinceNow: (expiresIn as NSString)
  189. .doubleValue)
  190. }
  191. refreshToken = dictionary["refreshToken"] as? String
  192. isNewUser = dictionary["isNewUser"] as? Bool ?? false
  193. if let rawUserInfo = dictionary["rawUserInfo"] as? String,
  194. let data = rawUserInfo.data(using: .utf8) {
  195. if let info = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves),
  196. let profile = info as? [String: Any] {
  197. self.profile = profile
  198. }
  199. } else if let profile = dictionary["rawUserInfo"] as? [String: Any] {
  200. self.profile = profile
  201. }
  202. username = dictionary["username"] as? String
  203. action = dictionary["action"] as? String
  204. language = dictionary["language"] as? String
  205. timeZone = dictionary["timeZone"] as? String
  206. photoURL = URL(string: dictionary["photoUrl"] as? String ?? "")
  207. dateOfBirth = dictionary["dateOfBirth"] as? String
  208. context = dictionary["context"] as? String
  209. needConfirmation = dictionary["needConfirmation"] as? Bool ?? false
  210. if let verifiedProvider = dictionary["verifiedProvider"] as? String,
  211. let data = verifiedProvider.data(using: .utf8) {
  212. if let decoded = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves),
  213. let provider = decoded as? [String] {
  214. self.verifiedProvider = provider
  215. }
  216. } else if let verifiedProvider = dictionary["verifiedProvider"] as? [String] {
  217. self.verifiedProvider = verifiedProvider
  218. }
  219. oauthIDToken = dictionary["oauthIdToken"] as? String
  220. if let oauthExpirationDate = dictionary["oauthExpireIn"] as? String {
  221. self
  222. .oauthExpirationDate = Date(timeIntervalSinceNow: (oauthExpirationDate as NSString)
  223. .doubleValue)
  224. }
  225. oauthAccessToken = dictionary["oauthAccessToken"] as? String
  226. oauthSecretToken = dictionary["oauthTokenSecret"] as? String
  227. pendingToken = dictionary["pendingToken"] as? String
  228. if let mfaInfoDicts = dictionary["mfaInfo"] as? [[String: AnyHashable]] {
  229. mfaInfo = mfaInfoDicts.map {
  230. AuthProtoMFAEnrollment(dictionary: $0)
  231. }
  232. }
  233. mfaPendingCredential = dictionary["mfaPendingCredential"] as? String
  234. }
  235. }