diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/PovioKitAuth-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/PovioKitAuth-Package.xcscheme index c920580..d279f7c 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/PovioKitAuth-Package.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/PovioKitAuth-Package.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/Demo/PovioKitAuthDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Demo/PovioKitAuthDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Demo/PovioKitAuthDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Demo/PovioKitAuthDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Demo/PovioKitAuthDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..60af7e5 --- /dev/null +++ b/Demo/PovioKitAuthDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,68 @@ +{ + "pins" : [ + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire", + "state" : { + "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a", + "version" : "5.9.1" + } + }, + { + "identity" : "appauth-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/openid/AppAuth-iOS.git", + "state" : { + "revision" : "c89ed571ae140f8eb1142735e6e23d7bb8c34cb2", + "version" : "1.7.5" + } + }, + { + "identity" : "facebook-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/facebook/facebook-ios-sdk", + "state" : { + "revision" : "9b89497b97ef043991862c9a8c5bb7fffaf31988", + "version" : "17.0.1" + } + }, + { + "identity" : "googlesignin-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleSignIn-iOS", + "state" : { + "revision" : "a7965d134c5d3567026c523e0a8a583f73b62b0d", + "version" : "7.1.0" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "0382ca27f22fb3494cf657d8dc356dc282cd1193", + "version" : "3.4.1" + } + }, + { + "identity" : "gtmappauth", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GTMAppAuth.git", + "state" : { + "revision" : "5d7d66f647400952b1758b230e019b07c0b4b22a", + "version" : "4.1.1" + } + }, + { + "identity" : "poviokit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/poviolabs/PovioKit", + "state" : { + "revision" : "96fa97cffa12ff644f10008133da062bec463ff8", + "version" : "4.0.0" + } + } + ], + "version" : 2 +} diff --git a/Demo/PovioKitAuthDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/Demo/PovioKitAuthDemo/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Demo/PovioKitAuthDemo/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/PovioKitAuthDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Demo/PovioKitAuthDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..532cd72 --- /dev/null +++ b/Demo/PovioKitAuthDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,63 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/PovioKitAuthDemo/Assets.xcassets/Contents.json b/Demo/PovioKitAuthDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Demo/PovioKitAuthDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/PovioKitAuthDemo/DemoApp.swift b/Demo/PovioKitAuthDemo/DemoApp.swift new file mode 100644 index 0000000..d880eda --- /dev/null +++ b/Demo/PovioKitAuthDemo/DemoApp.swift @@ -0,0 +1,18 @@ +// +// DemoApp.swift +// PovioKitAuthDemo +// +// Created by Borut Tomazin on 10/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +@main +struct DemoApp: App { + var body: some Scene { + WindowGroup { + SignInView(viewModel: .init()) + } + } +} diff --git a/Demo/PovioKitAuthDemo/PovioKitAuthDemo.entitlements b/Demo/PovioKitAuthDemo/PovioKitAuthDemo.entitlements new file mode 100644 index 0000000..4210463 --- /dev/null +++ b/Demo/PovioKitAuthDemo/PovioKitAuthDemo.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Demo/PovioKitAuthDemo/Preview Content/Preview Assets.xcassets/Contents.json b/Demo/PovioKitAuthDemo/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Demo/PovioKitAuthDemo/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/PovioKitAuthDemo/SignInView.swift b/Demo/PovioKitAuthDemo/SignInView.swift new file mode 100644 index 0000000..33fc2f3 --- /dev/null +++ b/Demo/PovioKitAuthDemo/SignInView.swift @@ -0,0 +1,60 @@ +// +// SignInView.swift +// PovioKitAuthDemo +// +// Created by Borut Tomazin on 10/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +struct SignInView: View { + let viewModel: SignInViewModel + @State private var showErrorAlert: Bool = false + @State private var showSuccessAlert: Bool = false + + var body: some View { + VStack(spacing: 20) { + Button { + viewModel.signInWithApple() + } label: { + Text("SignIn with Apple") + } + Button { + viewModel.signInWithGoogle() + } label: { + Text("SignIn with Google") + } + Button { + viewModel.signInWithFacebook() + } label: { + Text("SignIn with Facebook") + } + Button { + viewModel.signInWithLinkedIn() + } label: { + Text("SignIn with LinkedIn") + } + } + .onChange(of: viewModel.error) { oldValue, newValue in + showErrorAlert = true + } + .onChange(of: viewModel.success) { oldValue, newValue in + showSuccessAlert = true + } + .alert("Error", isPresented: $showErrorAlert) { + Button("Ok", action: {}) + } message: { + Text(viewModel.error) + } + .alert("Success", isPresented: $showSuccessAlert) { + Button("Ok", action: {}) + } message: { + Text(viewModel.success) + } + } +} + +#Preview { + SignInView(viewModel: .init()) +} diff --git a/Demo/PovioKitAuthDemo/SignInViewModel.swift b/Demo/PovioKitAuthDemo/SignInViewModel.swift new file mode 100644 index 0000000..b431c56 --- /dev/null +++ b/Demo/PovioKitAuthDemo/SignInViewModel.swift @@ -0,0 +1,105 @@ +// +// SignInViewModel.swift +// PovioKitAuthDemo +// +// Created by Borut Tomazin on 10/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import UIKit +import SwiftUI +import PovioKitCore +import PovioKitAuthCore +import PovioKitAuthApple +import PovioKitAuthGoogle +import PovioKitAuthFacebook +import PovioKitAuthLinkedIn +import Observation + +@Observable +final class SignInViewModel { + private let socialAuthManager: SocialAuthenticationManager + + var error: String = "" + var success: String = "" + + init() { + socialAuthManager = SocialAuthenticationManager(authenticators: [ + AppleAuthenticator(), + GoogleAuthenticator(), + FacebookAuthenticator(), + LinkedInAuthenticator() + ]) + } +} + +extension SignInViewModel { + func signInWithApple() { + guard let auth = socialAuthManager.authenticator(for: AppleAuthenticator.self) else { return } + + Task { @MainActor in + do { + _ = try await auth.signIn(from: UIViewController()) + self.success = "SignIn with Apple succeeded." + } catch AppleAuthenticator.Error.cancelled { + Logger.debug("Apple Auth cancelled.") + } catch { + Logger.error(error.localizedDescription) + self.error = error.localizedDescription + } + } + } + + // TODO: provide `GoogleService-Info.plist` configuration file + func signInWithGoogle() { + guard let auth = socialAuthManager.authenticator(for: GoogleAuthenticator.self) else { return } + + Task { @MainActor in + do { + _ = try await auth.signIn(from: UIViewController()) + self.success = "SignIn with Google succeeded." + } catch GoogleAuthenticator.Error.cancelled { + Logger.debug("Apple Auth cancelled.") + } catch { + Logger.error(error.localizedDescription) + self.error = error.localizedDescription + } + } + } + + // TODO: provide `FacebookAppID` to the `Info.plist` + func signInWithFacebook() { + guard let auth = socialAuthManager.authenticator(for: FacebookAuthenticator.self) else { return } + + Task { @MainActor in + do { + _ = try await auth.signIn(from: UIViewController()) + self.success = "SignIn with Facebook succeeded." + } catch FacebookAuthenticator.Error.cancelled { + Logger.debug("Apple Auth cancelled.") + } catch { + Logger.error(error.localizedDescription) + self.error = error.localizedDescription + } + } + } + + // TODO: provide configuration details + func signInWithLinkedIn() { + guard let auth = socialAuthManager.authenticator(for: LinkedInAuthenticator.self) else { return } + + Task { @MainActor in + do { + _ = try await auth.signIn(authCode: "...", configuration: .init( + clientId: "...", + clientSecret: "...", + permissions: "email profile openid offline_access", + redirectUrl: "...")) + self.success = "SignIn with LinkedIn succeeded." + } catch { + Logger.error(error.localizedDescription) + self.error = error.localizedDescription + } + } + } +}