Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/swiftui-auth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
unit-tests:
name: Package Unit Tests
runs-on: macos-15
timeout-minutes: 20
timeout-minutes: 15
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938

Expand Down Expand Up @@ -129,7 +129,7 @@ jobs:
ui-tests:
name: UI Tests
runs-on: macos-15
timeout-minutes: 30
timeout-minutes: 40
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938

Expand Down Expand Up @@ -179,16 +179,16 @@ jobs:
-enableCodeCoverage YES \
-resultBundlePath FirebaseSwiftUIExampleUITests.xcresult | tee FirebaseSwiftUIExampleUITests.log | xcpretty --test --color --simple

- name: Upload test logs
- name: Upload Firebase Emulator logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: ui-tests-logs
path: samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests.log
name: firebase-emulator-logs
path: samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExample/firebase-debug.log

- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: ui-tests-results
name: FirebaseSwiftUIExampleUITests.xcresult
path: samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExampleUITests.xcresult
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"images" : [
{
"filename" : "ic_github.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_github@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_github@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"images" : [
{
"filename" : "ic_microsoft.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_microsoft@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_microsoft@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"images" : [
{
"filename" : "ic_yahoo.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_yahoo@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_yahoo@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// AccountService+OAuth.swift
// FirebaseUI
//
// Created by Russell Wheatley on 21/10/2025.
//

@preconcurrency import FirebaseAuth
import FirebaseAuthSwiftUI
import Observation

protocol OAuthOperationReauthentication {
var oauthProvider: OAuthProviderSwift { get }
}

extension OAuthOperationReauthentication {
@MainActor func reauthenticate() async throws -> AuthenticationToken {
guard let user = Auth.auth().currentUser else {
throw AuthServiceError.reauthenticationRequired("No user currently signed-in")
}

do {
let credential = try await oauthProvider.createAuthCredential()
try await user.reauthenticate(with: credential)

return .firebase("")
} catch {
throw AuthServiceError.signInFailed(underlying: error)
}
}
}

@MainActor
class OAuthDeleteUserOperation: AuthenticatedOperation,
@preconcurrency OAuthOperationReauthentication {
let oauthProvider: OAuthProviderSwift
init(oauthProvider: OAuthProviderSwift) {
self.oauthProvider = oauthProvider
}

func callAsFunction(on user: User) async throws {
try await callAsFunction(on: user) {
try await user.delete()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2025 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.

//
// AuthService+OAuth.swift
// FirebaseUI
//
// Created by Russell Wheatley on 21/10/2025.
//

import FirebaseAuthSwiftUI

public extension AuthService {
@discardableResult
func withOAuthSignIn(_ provider: OAuthProviderSwift) -> AuthService {
registerProvider(providerWithButton: OAuthProviderAuthUI(provider: provider))
return self
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2025 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 SwiftUI

/// Preset configurations for common OAuth providers
public extension OAuthProviderSwift {
/// GitHub OAuth provider
/// - Parameters:
/// - scopes: GitHub scopes (default: ["user"])
/// - Returns: Configured GitHub provider
static func github(scopes: [String] = ["user"]) -> OAuthProviderSwift {
return OAuthProviderSwift(
providerId: "github.com",
scopes: scopes,
displayName: "Sign in with GitHub",
buttonIcon: Image("github_logo", bundle: .module),
buttonBackgroundColor: .black,
buttonForegroundColor: .white
)
}

/// Microsoft OAuth provider
/// - Parameters:
/// - scopes: Microsoft scopes (default: ["user.readwrite"])
/// - Returns: Configured Microsoft provider
static func microsoft(scopes: [String] = ["user.readwrite"]) -> OAuthProviderSwift {
return OAuthProviderSwift(
providerId: "microsoft.com",
scopes: scopes,
customParameters: ["prompt": "consent"],
displayName: "Sign in with Microsoft",
buttonIcon: Image("microsoft_logo", bundle: .module),
buttonBackgroundColor: Color(red: 0 / 255, green: 120 / 255, blue: 212 / 255),
buttonForegroundColor: .white
)
}

/// Yahoo OAuth provider
/// - Parameters:
/// - scopes: Yahoo scopes (default: ["user.readwrite"])
/// - Returns: Configured Yahoo provider
static func yahoo(scopes: [String] = ["user.readwrite"]) -> OAuthProviderSwift {
return OAuthProviderSwift(
providerId: "yahoo.com",
scopes: scopes,
customParameters: ["prompt": "consent"],
displayName: "Sign in with Yahoo",
buttonIcon: Image("yahoo_logo", bundle: .module),
buttonBackgroundColor: Color(red: 80 / 255, green: 0 / 255, blue: 155 / 255),
buttonForegroundColor: .white
)
}
}
Loading
Loading