| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- // 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
- /// The "verifyAssertion" endpoint.
- private let kVerifyAssertionEndpoint = "verifyAssertion"
- /// The key for the "providerId" value in the request.
- private let kProviderIDKey = "providerId"
- /// The key for the "id_token" value in the request.
- private let kProviderIDTokenKey = "id_token"
- /// The key for the "nonce" value in the request.
- private let kProviderNonceKey = "nonce"
- /// The key for the "access_token" value in the request.
- private let kProviderAccessTokenKey = "access_token"
- /// The key for the "oauth_token_secret" value in the request.
- private let kProviderOAuthTokenSecretKey = "oauth_token_secret"
- /// The key for the "identifier" value in the request.
- private let kIdentifierKey = "identifier"
- /// The key for the "requestUri" value in the request.
- private let kRequestURIKey = "requestUri"
- /// The key for the "postBody" value in the request.
- private let kPostBodyKey = "postBody"
- /// The key for the "pendingToken" value in the request.
- private let kPendingTokenKey = "pendingToken"
- /// The key for the "autoCreate" value in the request.
- private let kAutoCreateKey = "autoCreate"
- /// 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 "returnSecureToken" value in the request.
- private let kReturnSecureTokenKey = "returnSecureToken"
- /// The key for the "returnIdpCredential" value in the request.
- private let kReturnIDPCredentialKey = "returnIdpCredential"
- /// The key for the "sessionID" value in the request.
- private let kSessionIDKey = "sessionId"
- /// The key for the tenant id value in the request.
- private let kTenantIDKey = "tenantId"
- /// The key for the "user" value in the request. The value is a JSON object that contains the
- /// name of the user.
- private let kUserKey = "user"
- /// The key for the "name" value in the request. The value is a JSON object that contains the
- /// first and/or last name of the user.
- private let kNameKey = "name"
- /// The key for the "firstName" value in the request.
- private let kFirstNameKey = "firstName"
- /// The key for the "lastName" value in the request.
- private let kLastNameKey = "lastName"
- /// Represents the parameters for the verifyAssertion endpoint.
- /// See https://developers.google.com/identity/toolkit/web/reference/relyingparty/verifyAssertion
- @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
- class VerifyAssertionRequest: IdentityToolkitRequest, AuthRPCRequest {
- typealias Response = VerifyAssertionResponse
- /// The URI to which the IDP redirects the user back. It may contain federated login result
- /// params added by the IDP.
- var requestURI: String?
- /// The Firebase ID Token for the IDP pending to be confirmed by the user.
- var pendingToken: String?
- /// The STS Access Token for the authenticated user, only needed for linking the user.
- var accessToken: String?
- /// Whether the response should return access token and refresh token directly.
- /// The default value is `true` .
- var returnSecureToken: Bool = true
- // MARK: - Components of "postBody"
- /// The ID of the IDP whose credentials are being presented to the endpoint.
- let providerID: String
- /// An access token from the IDP.
- var providerAccessToken: String?
- /// An ID Token from the IDP.
- var providerIDToken: String?
- /// An raw nonce from the IDP.
- var providerRawNonce: String?
- /// Whether the response should return the IDP credential directly.
- var returnIDPCredential: Bool = true
- /// A session ID used to map this request to a headful-lite flow.
- var sessionID: String?
- /// An OAuth client secret from the IDP.
- var providerOAuthTokenSecret: String?
- /// The originally entered email in the UI.
- var inputEmail: String?
- /// A flag that indicates whether or not the user should be automatically created.
- var autoCreate: Bool = true
- /// A full name from the IdP.
- var fullName: PersonNameComponents?
- init(providerID: String, requestConfiguration: AuthRequestConfiguration) {
- self.providerID = providerID
- super.init(endpoint: kVerifyAssertionEndpoint, requestConfiguration: requestConfiguration)
- }
- func unencodedHTTPRequestBody() throws -> [String: AnyHashable] {
- var components = URLComponents()
- var queryItems: [URLQueryItem] = [URLQueryItem(name: kProviderIDKey, value: providerID)]
- if let providerIDToken = providerIDToken {
- queryItems.append(URLQueryItem(name: kProviderIDTokenKey, value: providerIDToken))
- }
- if let providerRawNonce = providerRawNonce {
- queryItems.append(URLQueryItem(name: kProviderNonceKey, value: providerRawNonce))
- }
- if let providerAccessToken = providerAccessToken {
- queryItems
- .append(URLQueryItem(name: kProviderAccessTokenKey, value: providerAccessToken))
- }
- guard providerIDToken != nil || providerAccessToken != nil || pendingToken != nil ||
- requestURI != nil else {
- fatalError("One of IDToken, accessToken, pendingToken, or requestURI must be supplied.")
- }
- if let providerOAuthTokenSecret = providerOAuthTokenSecret {
- queryItems
- .append(URLQueryItem(name: kProviderOAuthTokenSecretKey,
- value: providerOAuthTokenSecret))
- }
- if let inputEmail = inputEmail {
- queryItems.append(URLQueryItem(name: kIdentifierKey, value: inputEmail))
- }
- if fullName?.givenName != nil || fullName?.familyName != nil {
- var nameDict = [String: String]()
- if let given = fullName?.givenName {
- nameDict[kFirstNameKey] = given
- }
- if let lastName = fullName?.familyName {
- nameDict[kLastNameKey] = lastName
- }
- let userDict = [kNameKey: nameDict]
- do {
- let encoder = JSONEncoder()
- encoder.outputFormatting = .sortedKeys
- let userJson = try encoder.encode(userDict)
- let jsonString = String(data: userJson, encoding: .utf8)
- queryItems.append(URLQueryItem(name: kUserKey, value: jsonString))
- } catch {
- fatalError("Auth Internal error: failed to serialize dictionary to json: \(error)")
- }
- }
- components.queryItems = queryItems
- var body: [String: AnyHashable] = [
- kRequestURIKey: requestURI ?? "http://localhost", // Unused by server, but required
- ]
- if let query = components.query {
- body[kPostBodyKey] = query
- }
- if let pendingToken = pendingToken {
- body[kPendingTokenKey] = pendingToken
- }
- if let accessToken = accessToken {
- body[kIDTokenKey] = accessToken
- }
- if returnSecureToken {
- body[kReturnSecureTokenKey] = true
- }
- if returnIDPCredential {
- body[kReturnIDPCredentialKey] = true
- }
- if let sessionID = sessionID {
- body[kSessionIDKey] = sessionID
- }
- if let tenantID = tenantID {
- body[kTenantIDKey] = tenantID
- }
- body[kAutoCreateKey] = autoCreate
- return body
- }
- }
|