/* * Copyright 2020 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 import FirebaseAuth import GTMSessionFetcher import XCTest class GoogleTests: TestsBase { func testSignInWithGoogle() throws { let auth = Auth.auth() let userInfoDict = getGoogleAccessToken() let googleAccessToken: String = try XCTUnwrap(userInfoDict["access_token"] as? String) let googleIDToken: String = try XCTUnwrap(userInfoDict["id_token"] as? String) let credential = GoogleAuthProvider.credential(withIDToken: googleIDToken, accessToken: googleAccessToken) let expectation = self.expectation(description: "Signing in with Google finished.") auth.signIn(with: credential) { result, error in if let error = error { print("Signing in with Google had error: \(error)") } expectation.fulfill() } waitForExpectations(timeout: TestsBase.kExpectationsTimeout) } #if compiler(>=5.5.2) && canImport(_Concurrency) @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) func testSignInWithGoogleAsync() async throws { let auth = Auth.auth() let userInfoDict = try await getGoogleAccessTokenAsync() let googleAccessToken: String = try XCTUnwrap(userInfoDict["access_token"] as? String) let googleIDToken: String = try XCTUnwrap(userInfoDict["id_token"] as? String) let credential = GoogleAuthProvider.credential(withIDToken: googleIDToken, accessToken: googleAccessToken) _ = try await auth.signIn(with: credential) } #endif /// Sends http request to Google OAuth2 token server to use refresh token to exchange for Google /// access token. /// Returns a dictionary that constains "access_token", "token_type", "expires_in" and sometimes /// the "id_token". (The id_token is not guaranteed to be returned during a refresh exchange; see /// https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse) func getGoogleAccessToken() -> [String: Any] { var returnValue: [String: Any] = [:] let googleOauth2TokenServerUrl = "https://www.googleapis.com/oauth2/v4/token" let bodyString = "client_id=\(Credentials.kGoogleClientID)&grant_type=refresh_token" + "&refresh_token=\(Credentials.kGoogleTestAccountRefreshToken)" let postData = bodyString.data(using: .utf8) let service = GTMSessionFetcherService() let fetcher = service.fetcher(withURLString: googleOauth2TokenServerUrl) fetcher.bodyData = postData fetcher.setRequestValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") let expectation = self.expectation(description: "Exchanging Google account tokens finished.") fetcher.beginFetch { data, error in if let error = error { XCTFail("Exchanging Google account tokens finished with error: \(error)") } else { do { let data = try XCTUnwrap(data) returnValue = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] } catch { XCTFail("Failed to unwrap data \(error)") } } expectation.fulfill() } waitForExpectations(timeout: TestsBase.kExpectationsTimeout) return returnValue } #if compiler(>=5.5.2) && canImport(_Concurrency) @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) /// Sends http request to Google OAuth2 token server to use refresh token to exchange for Google /// access token. /// Returns a dictionary that constains "access_token", "token_type", "expires_in" and sometimes /// the "id_token". (The id_token is not guaranteed to be returned during a refresh exchange; /// see https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse) func getGoogleAccessTokenAsync() async throws -> [String: Any] { let googleOauth2TokenServerUrl = "https://www.googleapis.com/oauth2/v4/token" let bodyString = "client_id=\(Credentials.kGoogleClientID)&grant_type=refresh_token" + "&refresh_token=\(Credentials.kGoogleTestAccountRefreshToken)" let postData = bodyString.data(using: .utf8) let service = GTMSessionFetcherService() let fetcher = service.fetcher(withURLString: googleOauth2TokenServerUrl) fetcher.bodyData = postData fetcher.setRequestValue( "application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type" ) let data = try await fetcher.beginFetch() guard let returnValue = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { XCTFail("Failed to serialize userInfo as a Dictionary") fatalError() } return returnValue } #endif }