| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- // Copyright 2023 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- import Foundation
- enum GetOOBConfirmationCodeRequestType: Int {
- /// Requests a password reset code.
- case passwordReset
- /// Requests an email verification code.
- case verifyEmail
- /// Requests an email sign-in link.
- case emailLink
- /// Requests a verify before update email.
- case verifyBeforeUpdateEmail
- var value: String {
- switch self {
- case .passwordReset:
- return kPasswordResetRequestTypeValue
- case .verifyEmail:
- return kVerifyEmailRequestTypeValue
- case .emailLink:
- return kEmailLinkSignInTypeValue
- case .verifyBeforeUpdateEmail:
- return kVerifyBeforeUpdateEmailRequestTypeValue
- }
- }
- }
- private let kGetOobConfirmationCodeEndpoint = "getOobConfirmationCode"
- /// The name of the required "requestType" property in the request.
- private let kRequestTypeKey = "requestType"
- /// The name of the "email" property in the request.
- private let kEmailKey = "email"
- /// The name of the "newEmail" property in the request.
- private let kNewEmailKey = "newEmail"
- /// The key for the "idToken" value in the request. This is actually the STS Access Token,
- /// despite its confusing (backwards compatible) parameter name.
- private let kIDTokenKey = "idToken"
- /// The key for the "continue URL" value in the request.
- private let kContinueURLKey = "continueUrl"
- /// The key for the "iOS Bundle Identifier" value in the request.
- private let kIosBundleIDKey = "iOSBundleId"
- /// The key for the "Android Package Name" value in the request.
- private let kAndroidPackageNameKey = "androidPackageName"
- /// The key for the request parameter indicating whether the android app should be installed or not.
- private let kAndroidInstallAppKey = "androidInstallApp"
- /// The key for the "minimum Android version supported" value in the request.
- private let kAndroidMinimumVersionKey = "androidMinimumVersion"
- /// The key for the request parameter indicating whether the action code can be handled in the app
- /// or not.
- private let kCanHandleCodeInAppKey = "canHandleCodeInApp"
- /// The key for the "link domain" value in the request.
- private let kLinkDomainKey = "linkDomain"
- /// The value for the "PASSWORD_RESET" request type.
- private let kPasswordResetRequestTypeValue = "PASSWORD_RESET"
- /// The value for the "EMAIL_SIGNIN" request type.
- private let kEmailLinkSignInTypeValue = "EMAIL_SIGNIN"
- /// The value for the "VERIFY_EMAIL" request type.
- private let kVerifyEmailRequestTypeValue = "VERIFY_EMAIL"
- /// The value for the "VERIFY_AND_CHANGE_EMAIL" request type.
- private let kVerifyBeforeUpdateEmailRequestTypeValue = "VERIFY_AND_CHANGE_EMAIL"
- /// The key for the tenant id value in the request.
- private let kTenantIDKey = "tenantId"
- /// The key for the "captchaResponse" value in the request.
- private let kCaptchaResponseKey = "captchaResp"
- /// The key for the "clientType" value in the request.
- private let kClientType = "clientType"
- /// The key for the "recaptchaVersion" value in the request.
- private let kRecaptchaVersion = "recaptchaVersion"
- @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
- class GetOOBConfirmationCodeRequest: IdentityToolkitRequest, AuthRPCRequest {
- typealias Response = GetOOBConfirmationCodeResponse
- /// The types of OOB Confirmation Code to request.
- private let requestType: GetOOBConfirmationCodeRequestType
- /// The email of the user for password reset.
- let email: String?
- /// The new email to be updated for verifyBeforeUpdateEmail.
- private let updatedEmail: String?
- /// The STS Access Token of the authenticated user for email change.
- private let accessToken: String?
- /// This URL represents the state/Continue URL in the form of a universal link.
- let continueURL: String?
- /// The iOS bundle Identifier, if available.
- private let iOSBundleID: String?
- /// The Android package name, if available.
- private let androidPackageName: String?
- /// The minimum Android version supported, if available.
- private let androidMinimumVersion: String?
- /// Indicates whether or not the Android app should be installed if not already available.
- private let androidInstallApp: Bool
- /// Indicates whether the action code link will open the app directly or after being
- /// redirected from a Firebase owned web widget.
- let handleCodeInApp: Bool
- /// The Firebase Hosting domain used for out of band code flow.
- private(set) var linkDomain: String?
- /// Response to the captcha.
- var captchaResponse: String?
- /// The reCAPTCHA version.
- var recaptchaVersion: String?
- /// Designated initializer.
- /// - Parameter requestType: The types of OOB Confirmation Code to request.
- /// - Parameter email: The email of the user.
- /// - Parameter newEmail: The email of the user to be updated.
- /// - Parameter accessToken: The STS Access Token of the currently signed in user.
- /// - Parameter actionCodeSettings: An object of FIRActionCodeSettings which specifies action code
- /// settings to be applied to the OOB code request.
- /// - Parameter requestConfiguration: An object containing configurations to be added to the
- /// request.
- required init(requestType: GetOOBConfirmationCodeRequestType,
- email: String?,
- newEmail: String?,
- accessToken: String?,
- actionCodeSettings: ActionCodeSettings?,
- requestConfiguration: AuthRequestConfiguration) {
- self.requestType = requestType
- self.email = email
- updatedEmail = newEmail
- self.accessToken = accessToken
- continueURL = actionCodeSettings?.url?.absoluteString
- iOSBundleID = actionCodeSettings?.iOSBundleID
- androidPackageName = actionCodeSettings?.androidPackageName
- androidMinimumVersion = actionCodeSettings?.androidMinimumVersion
- androidInstallApp = actionCodeSettings?.androidInstallIfNotAvailable ?? false
- handleCodeInApp = actionCodeSettings?.handleCodeInApp ?? false
- linkDomain = actionCodeSettings?.linkDomain
- super.init(
- endpoint: kGetOobConfirmationCodeEndpoint,
- requestConfiguration: requestConfiguration
- )
- }
- static func passwordResetRequest(email: String,
- actionCodeSettings: ActionCodeSettings?,
- requestConfiguration: AuthRequestConfiguration) ->
- GetOOBConfirmationCodeRequest {
- Self(requestType: .passwordReset,
- email: email,
- newEmail: nil,
- accessToken: nil,
- actionCodeSettings: actionCodeSettings,
- requestConfiguration: requestConfiguration)
- }
- static func verifyEmailRequest(accessToken: String,
- actionCodeSettings: ActionCodeSettings?,
- requestConfiguration: AuthRequestConfiguration) ->
- GetOOBConfirmationCodeRequest {
- Self(requestType: .verifyEmail,
- email: nil,
- newEmail: nil,
- accessToken: accessToken,
- actionCodeSettings: actionCodeSettings,
- requestConfiguration: requestConfiguration)
- }
- static func signInWithEmailLinkRequest(_ email: String,
- actionCodeSettings: ActionCodeSettings?,
- requestConfiguration: AuthRequestConfiguration)
- -> Self {
- Self(requestType: .emailLink,
- email: email,
- newEmail: nil,
- accessToken: nil,
- actionCodeSettings: actionCodeSettings,
- requestConfiguration: requestConfiguration)
- }
- static func verifyBeforeUpdateEmail(accessToken: String,
- newEmail: String,
- actionCodeSettings: ActionCodeSettings?,
- requestConfiguration: AuthRequestConfiguration)
- -> Self {
- Self(requestType: .verifyBeforeUpdateEmail,
- email: nil,
- newEmail: newEmail,
- accessToken: accessToken,
- actionCodeSettings: actionCodeSettings,
- requestConfiguration: requestConfiguration)
- }
- var unencodedHTTPRequestBody: [String: AnyHashable]? {
- var body: [String: AnyHashable] = [
- kRequestTypeKey: requestType.value,
- ]
- // For password reset requests, we only need an email address in addition to the already
- // required fields.
- if case .passwordReset = requestType {
- body[kEmailKey] = email
- }
- // For verify email requests, we only need an STS Access Token in addition to the already
- // required fields.
- if case .verifyEmail = requestType {
- body[kIDTokenKey] = accessToken
- }
- // For email sign-in link requests, we only need an email address in addition to the already
- // required fields.
- if case .emailLink = requestType {
- body[kEmailKey] = email
- }
- // For email sign-in link requests, we only need an STS Access Token, a new email address in
- // addition to the already required fields.
- if case .verifyBeforeUpdateEmail = requestType {
- body[kNewEmailKey] = updatedEmail
- body[kIDTokenKey] = accessToken
- }
- if let continueURL = continueURL {
- body[kContinueURLKey] = continueURL
- }
- if let iOSBundleID = iOSBundleID {
- body[kIosBundleIDKey] = iOSBundleID
- }
- if let androidPackageName = androidPackageName {
- body[kAndroidPackageNameKey] = androidPackageName
- }
- if let androidMinimumVersion = androidMinimumVersion {
- body[kAndroidMinimumVersionKey] = androidMinimumVersion
- }
- if androidInstallApp {
- body[kAndroidInstallAppKey] = true
- }
- if handleCodeInApp {
- body[kCanHandleCodeInAppKey] = true
- }
- if let linkDomain {
- body[kLinkDomainKey] = linkDomain
- }
- if let captchaResponse {
- body[kCaptchaResponseKey] = captchaResponse
- }
- body[kClientType] = clientType
- if let recaptchaVersion {
- body[kRecaptchaVersion] = recaptchaVersion
- }
- if let tenantID {
- body[kTenantIDKey] = tenantID
- }
- return body
- }
- func injectRecaptchaFields(recaptchaResponse: String?, recaptchaVersion: String) {
- captchaResponse = recaptchaResponse
- self.recaptchaVersion = recaptchaVersion
- }
- }
|