From fe6c62b60f16ebf3c0e02061dcdb809b13fcc942 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 5 May 2026 14:07:06 +0100 Subject: [PATCH] Rename OIDC to OAuth. (#5525) * Rename OIDC to OAuth. * Update the enterprise submodule. --- ElementX.xcodeproj/project.pbxproj | 32 ++++----- .../Sources/Application/AppCoordinator.swift | 6 +- .../Application/Navigation/AppRoutes.swift | 16 ++--- .../Application/Settings/AppSettings.swift | 26 ++++---- .../Settings/OAuthConfiguration.swift | 36 ++++++++++ .../Settings/OIDCConfiguration.swift | 35 ---------- .../AuthenticationFlowCoordinator.swift | 50 +++++++------- .../ChatsTabFlowCoordinator.swift | 2 +- .../EncryptionResetFlowCoordinator.swift | 16 ++--- .../EncryptionSettingsFlowCoordinator.swift | 2 +- .../LinkNewDeviceFlowCoordinator.swift | 6 +- .../RoomFlowCoordinator.swift | 2 +- .../RoomMembersFlowCoordinator.swift | 2 +- .../SettingsFlowCoordinator.swift | 18 ++--- .../UserSessionFlowCoordinator.swift | 2 +- ...thenticationClientBuilderFactoryMock.swift | 16 ++--- .../Sources/Mocks/SDK/ClientSDKMock.swift | 10 +-- .../LoginScreen/LoginHomeserver.swift | 10 +-- .../LoginScreen/LoginMode.swift | 6 +- .../LoginScreen/LoginScreenCoordinator.swift | 8 +-- .../LoginScreen/LoginScreenModels.swift | 8 +-- .../LoginScreen/LoginScreenViewModel.swift | 4 +- .../LoginScreen/View/LoginScreen.swift | 4 +- ...ift => OAuthAuthenticationPresenter.swift} | 42 ++++++------ .../ServerConfirmationScreenCoordinator.swift | 6 +- .../ServerConfirmationScreenModels.swift | 8 +-- .../ServerConfirmationScreenViewModel.swift | 8 +-- .../MockSoftLogoutScreenState.swift | 6 +- .../SoftLogoutScreenCoordinator.swift | 42 ++++++------ .../SoftLogoutScreenModels.swift | 16 ++--- .../SoftLogoutScreenViewModel.swift | 4 +- .../View/SoftLogoutScreen.swift | 12 ++-- ...AuthenticationStartScreenCoordinator.swift | 6 +- .../AuthenticationStartScreenModels.swift | 6 +- .../AuthenticationStartScreenViewModel.swift | 8 +-- .../EncryptionResetScreenCoordinator.swift | 6 +- .../EncryptionResetScreenModels.swift | 2 +- .../EncryptionResetScreenViewModel.swift | 6 +- .../QRCodeLoginScreenCoordinator.swift | 8 +-- .../QRCodeLoginScreenModels.swift | 4 +- .../QRCodeLoginScreenViewModel.swift | 14 ++-- ...ft => OAuthAccountSettingsPresenter.swift} | 14 ++-- .../AuthenticationService.swift | 44 ++++++------- .../AuthenticationServiceProtocol.swift | 26 ++++---- .../Sources/Services/Client/ClientProxy.swift | 2 +- .../UserSession/RestorationToken.swift | 7 +- .../UITests/UITestsAppCoordinator.swift | 4 +- Enterprise | 2 +- .../AuthenticationFlowCoordinatorTests.swift | 14 ++-- .../Sources/AppRouteURLParserTests.swift | 18 ++--- .../Sources/AuthenticationServiceTests.swift | 4 +- ...henticationStartScreenViewModelTests.swift | 52 +++++++-------- .../Sources/LoginScreenViewModelTests.swift | 12 ++-- .../QRCodeLoginScreenViewModelTests.swift | 4 +- ...verConfigurationScreenViewStateTests.swift | 8 +-- ...rverConfirmationScreenViewModelTests.swift | 66 +++++++++---------- .../SoftLogoutScreenViewModelTests.swift | 4 +- 57 files changed, 402 insertions(+), 400 deletions(-) create mode 100644 ElementX/Sources/Application/Settings/OAuthConfiguration.swift delete mode 100644 ElementX/Sources/Application/Settings/OIDCConfiguration.swift rename ElementX/Sources/Screens/Authentication/{OIDCAuthenticationPresenter.swift => OAuthAuthenticationPresenter.swift} (83%) rename ElementX/Sources/Screens/Settings/AccountSettings/{OIDCAccountSettingsPresenter.swift => OAuthAccountSettingsPresenter.swift} (85%) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index f62ae9e3d..9a741847a 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -488,7 +488,6 @@ 513AF15E0E84711B80D04B1B /* ReportRoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3E9684DCE6B66BD0B5DF67 /* ReportRoomScreenViewModelTests.swift */; }; 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; }; 522269133E6F65F68482F4F4 /* RemotePreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181CF280BC8E3F335AFCB4B8 /* RemotePreferenceTests.swift */; }; - 523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */; }; 52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 530C2238E40F71223327FC95 /* MockTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BA8082E26C77A2C587B34B3 /* MockTimelineController.swift */; }; 5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */; }; @@ -634,6 +633,7 @@ 6A5FDF9306CBD62C7EDDB552 /* CLLocationManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C723327DC4A3093CD9675B27 /* CLLocationManagerMock.swift */; }; 6A64546ABE648ED9E6DBB459 /* RemoteSettingsHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D186A6DB8FAC5C9D0E4D61 /* RemoteSettingsHook.swift */; }; 6AB306367E56A6F6DFA0E2FF /* RoomSummaryProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46E441BA50705E6CEC89FE0 /* RoomSummaryProviderTests.swift */; }; + 6AC798F52571BE495E6AA1CE /* OAuthAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21819C86A022D6ADBA7A7A15 /* OAuthAccountSettingsPresenter.swift */; }; 6AD722DD92E465E56D2885AB /* BugReportScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */; }; 6AEB650311F694A5702255C9 /* UserProfileScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B4932E4EFBC8FAC10972CD /* UserProfileScreenCoordinator.swift */; }; 6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */; }; @@ -680,7 +680,6 @@ 726AA74DF4E5EFCEBD78CE3F /* RoomMembersFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A70B03471F6027C90EE868C /* RoomMembersFlowCoordinator.swift */; }; 72D2298DE695A6797CDA1A2A /* SpaceScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B223FA339BF53085328DEE /* SpaceScreenViewModelTests.swift */; }; 733E2B19AB1FDA3B93293A28 /* AppLockSetupPINScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */; }; - 7366E5783D1871D42CF99D34 /* OIDCConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D354D4232DED9649FD0FF4 /* OIDCConfiguration.swift */; }; 738288EAEE235CAC0893AB9E /* ThreadTimelineScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C9ACDD96F36510C1FC0836B /* ThreadTimelineScreenViewModel.swift */; }; 73DBE886625AF56FF08D7F76 /* CoordinateAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA74F57B0DA3B9A9DD51F691 /* CoordinateAnimator.swift */; }; 73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */; }; @@ -697,7 +696,6 @@ 756EA0D663261889EF64E6D4 /* VoiceMessageRecordingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */; }; 7573D682F089205F7F1D96CF /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 757862045774A0F458357E19 /* RoomThreadListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544B9262E1BC6F489C03FFFA /* RoomThreadListScreen.swift */; }; - 75AD7C09BD604A68E2FAA1D9 /* OIDCConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D354D4232DED9649FD0FF4 /* OIDCConfiguration.swift */; }; 75ED4B73983228BB6922CE3C /* KnockRequestsListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A5C217DD0749EC709EED028 /* KnockRequestsListScreenViewModelProtocol.swift */; }; 761EA50B2619307AB30891B8 /* PhishingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB07F03461023BC39C730922 /* PhishingDetector.swift */; }; 7624B61D0A3EFEC69C666609 /* SpaceAddRoomsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB74D407F0E413E7593B369 /* SpaceAddRoomsScreenViewModelTests.swift */; }; @@ -797,6 +795,7 @@ 859E2CA2EDF343BD24DE52EB /* RoomDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */; }; 85BD82E144AB99518A57DDEC /* preview_avatar_room.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */; }; 85F89F3F320F4FADCFFFE68B /* ServerSelectionScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */; }; + 86320FDBD2F12A0225B1BCBE /* OAuthConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */; }; 864C0D3A4077BF433DBC691F /* PollRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */; }; 8658F5034EAD7357CE7F9AC7 /* MatrixUserShareLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */; }; 865DD5CA474C6AE6C2BC008E /* NetworkMonitorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */; }; @@ -929,7 +928,6 @@ 99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D661CAB418C075A94306A792 /* AnalyticsEvents */; }; 9A0326D2375075871D2AB537 /* ResolveVerifiedUserSendFailureScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574CB70E82D7EAEA538E4135 /* ResolveVerifiedUserSendFailureScreenViewModel.swift */; }; 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; - 9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */; }; 9A8E6FCD86B89970EC72EFD8 /* BugReportServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7FC9580CABF797A2E6213A /* BugReportServiceMock.swift */; }; 9AC47275B8E1EB0976BA7A80 /* MapTilerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */; }; 9AC5F8142413862A9E3A2D98 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; }; @@ -1005,7 +1003,6 @@ A5B455D1A6DADF7476F7B417 /* EmojiProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BCCE3D12B0A9C6E559B5B5A /* EmojiProviderProtocol.swift */; }; A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */; }; A5D551E5691749066E0E0C44 /* RoomDetailsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */; }; - A5F50F36E56E5D3C241E2BE3 /* OIDCConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D354D4232DED9649FD0FF4 /* OIDCConfiguration.swift */; }; A5FD8284744E2FECFC842FC1 /* TraceLogPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7149BDDE47F8AD104E644E2 /* TraceLogPack.swift */; }; A64B52D9F73F9A6B95AF24FE /* UserDetailsEditScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */; }; A6B83EB78F025D21B6EBA90C /* CompoundIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044E501B8331B339874D1B96 /* CompoundIcon.swift */; }; @@ -1171,6 +1168,7 @@ C4D2BCAA54E2C62B94B24AF4 /* InviteUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E9B841EE4878283ECDB554 /* InviteUsersScreen.swift */; }; C4E0D03DF88242697545A9B7 /* UserIndicatorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1275D9CE0FFBA6E8E85426 /* UserIndicatorController.swift */; }; C4FE0E11A907C8999F92D5A8 /* TimelineStartRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F5F9E02B1AB5350B1815E7 /* TimelineStartRoomTimelineItem.swift */; }; + C525F6C2892CB0640E776B3D /* OAuthConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */; }; C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; }; C5627BCC3EBBB96A943B6D93 /* RestorationTokenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */; }; C58E305C380D3ADDF7912180 /* StickerRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */; }; @@ -1344,6 +1342,7 @@ E323A54F317604BDD6968D79 /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; }; E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */; }; E32A18802EB37EEE3EF7B965 /* GlobalSearchScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */; }; + E32E71A1AF5E5E69E8363B26 /* OAuthAuthenticationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEA11EF88B2848B12FA6FA36 /* OAuthAuthenticationPresenter.swift */; }; E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */; }; E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */; }; E3E1E255DC8CB34BD8573E0D /* UserIndicatorControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */; }; @@ -1453,6 +1452,7 @@ F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; }; F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */; }; F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */; }; + F43564003B017DB148DB1503 /* OAuthConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */; }; F4582042AA4225CC1E4B8A1E /* landscape_test_video.mov in Resources */ = {isa = PBXBuildFile; fileRef = 78BBDF7A05CF53B5CDC13682 /* landscape_test_video.mov */; }; F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; }; F4C005F006FC3657B9F0A31D /* BugReportHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */; }; @@ -1613,6 +1613,7 @@ /* Begin PBXFileReference section */ 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreen.swift; sourceTree = ""; }; 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = ""; }; + 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthConfiguration.swift; sourceTree = ""; }; 007C16779FDCF10DA4F1A510 /* LinkNewDeviceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceService.swift; sourceTree = ""; }; 008D864B3F51B41DF483B860 /* RoomThreadListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListScreenViewModelProtocol.swift; sourceTree = ""; }; 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = ""; }; @@ -1814,6 +1815,7 @@ 2141693488CE5446BB391964 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = ""; }; 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItemContent.swift; sourceTree = ""; }; 2178B951602AA921A5FD9DC8 /* MediaEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineFlowCoordinator.swift; sourceTree = ""; }; + 21819C86A022D6ADBA7A7A15 /* OAuthAccountSettingsPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthAccountSettingsPresenter.swift; sourceTree = ""; }; 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = ""; }; 21BA866267F84BF4350B0CB7 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Localizable.stringsdict"; sourceTree = ""; }; 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserFlowTests.swift; sourceTree = ""; }; @@ -2438,7 +2440,6 @@ 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = ""; }; 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = ""; }; 922E498EB74CF6F5CC236F81 /* AdvancedSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenModels.swift; sourceTree = ""; }; - 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCAuthenticationPresenter.swift; sourceTree = ""; }; 92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScannerView.swift; sourceTree = ""; }; 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = ""; }; 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaFrame.swift; sourceTree = ""; }; @@ -2602,6 +2603,7 @@ AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancellableTask.swift; sourceTree = ""; }; AE5DDBEBBA17973ED4638823 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = ""; }; AE739A6836E86E3780748477 /* TimelineItemBubbleBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbleBackground.swift; sourceTree = ""; }; + AEA11EF88B2848B12FA6FA36 /* OAuthAuthenticationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthAuthenticationPresenter.swift; sourceTree = ""; }; AEB5FF7A09B79B0C6B528F7C /* SFNumberedListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SFNumberedListView.swift; sourceTree = ""; }; AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilderTests.swift; sourceTree = ""; }; AEF2C15634499348A512A93A /* ChatsSpaceFiltersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsSpaceFiltersScreenModels.swift; sourceTree = ""; }; @@ -2713,7 +2715,6 @@ C142248014E08E885E323E56 /* Avatars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Avatars.swift; sourceTree = ""; }; C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutDirection.swift; sourceTree = ""; }; C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationModeProxy.swift; sourceTree = ""; }; - C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCAccountSettingsPresenter.swift; sourceTree = ""; }; C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeView.swift; sourceTree = ""; }; C258C9C815272911A5B132C3 /* FormattedBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyText.swift; sourceTree = ""; }; C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenModels.swift; sourceTree = ""; }; @@ -2924,7 +2925,6 @@ E8495F37D6245AD0CFA1F60B /* AppLockTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTests.swift; sourceTree = ""; }; E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProvider.swift; sourceTree = ""; }; E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicator.swift; sourceTree = ""; }; - E8D354D4232DED9649FD0FF4 /* OIDCConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCConfiguration.swift; sourceTree = ""; }; E944F717FC10A428D027074D /* RoomPowerLevelsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxyMock.swift; sourceTree = ""; }; E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = ""; }; E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; @@ -6519,7 +6519,7 @@ 0A2074C0449B83D5858BD2D7 /* FrequentlyUsedEmoji.swift */, DA2FEFA393FC7D2870263012 /* LiveLocationSession.swift */, 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */, - E8D354D4232DED9649FD0FF4 /* OIDCConfiguration.swift */, + 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */, 8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */, 69A05E85E4872C3221C5C287 /* RemotePreference.swift */, A5DA892E8643240C7BC41900 /* RoomListActivityVisibility.swift */, @@ -6805,7 +6805,7 @@ E74CD7681375AD2EAA34D66B /* Authentication */ = { isa = PBXGroup; children = ( - 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */, + AEA11EF88B2848B12FA6FA36 /* OAuthAuthenticationPresenter.swift */, 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */, 90F48FEF84016ED42A94BA24 /* LoginScreen */, BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */, @@ -6839,7 +6839,7 @@ EB5B1119B5AD79297F1D49EB /* AccountSettings */ = { isa = PBXGroup; children = ( - C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */, + 21819C86A022D6ADBA7A7A15 /* OAuthAccountSettingsPresenter.swift */, ); path = AccountSettings; sourceTree = ""; @@ -7804,7 +7804,7 @@ 5415236FA271AF7885D4995E /* NotificationItemProxy.swift in Sources */, CBBBE597BE74A2DF68DE2209 /* NotificationItemProxyProtocol.swift in Sources */, B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */, - A5F50F36E56E5D3C241E2BE3 /* OIDCConfiguration.swift in Sources */, + 86320FDBD2F12A0225B1BCBE /* OAuthConfiguration.swift in Sources */, 761EA50B2619307AB30891B8 /* PhishingDetector.swift in Sources */, 5DFC2A889D3B39DD47AC63A8 /* PillUtilities.swift in Sources */, 55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */, @@ -8020,7 +8020,7 @@ 0638CBDE3098B1C3F23AFCFA /* MXLog.swift in Sources */, 074F741578307EF0179EE47C /* MapTilerConfiguration.swift in Sources */, 1A3783005E6945F8583AF997 /* NSItemProvider.swift in Sources */, - 75AD7C09BD604A68E2FAA1D9 /* OIDCConfiguration.swift in Sources */, + F43564003B017DB148DB1503 /* OAuthConfiguration.swift in Sources */, BE8E5985771DF9137C6CE89A /* ProcessInfo.swift in Sources */, 58F357A9D130A654ABCB1638 /* RageshakeConfiguration.swift in Sources */, 24C32D7EF94ECF9081638DF6 /* RemotePreference.swift in Sources */, @@ -8602,9 +8602,9 @@ D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */, 7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */, CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */, - 523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */, - 9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */, - 7366E5783D1871D42CF99D34 /* OIDCConfiguration.swift in Sources */, + 6AC798F52571BE495E6AA1CE /* OAuthAccountSettingsPresenter.swift in Sources */, + E32E71A1AF5E5E69E8363B26 /* OAuthAuthenticationPresenter.swift in Sources */, + C525F6C2892CB0640E776B3D /* OAuthConfiguration.swift in Sources */, FD573B5D665824EB79EABF06 /* Observable.swift in Sources */, 11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */, 3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */, diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 212288fab..5eb7cf26a 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -276,11 +276,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg case .accountProvisioningLink: handleAppRoute(route, windowType: windowType) - case .oidcCallback(let url): + case .oAuthCallback(let url): if stateMachine.state == .softLogout { - softLogoutCoordinator?.handleOIDCRedirectURL(url) + softLogoutCoordinator?.handleOAuthCallbackURL(url) } else { - authenticationFlowCoordinator?.handleOIDCRedirectURL(url) + authenticationFlowCoordinator?.handleOAuthCallbackURL(url) } case .userProfile(let userID): if isExternalURL { diff --git a/ElementX/Sources/Application/Navigation/AppRoutes.swift b/ElementX/Sources/Application/Navigation/AppRoutes.swift index b9734d720..de57cde51 100644 --- a/ElementX/Sources/Application/Navigation/AppRoutes.swift +++ b/ElementX/Sources/Application/Navigation/AppRoutes.swift @@ -14,9 +14,9 @@ import MatrixRustSDK enum AppRoute: Hashable { /// An account provisioning link generated externally. case accountProvisioningLink(AccountProvisioningParameters) - /// An external callback used to complete login with OIDC. This is only used when authentication - /// requires an external app so cannot be done within the built in web authentication session. - case oidcCallback(url: URL) + /// An external callback used to complete login with OAuth. This is only used when authentication + /// requires an external app so cannot be handled directly by the web authentication session. + case oAuthCallback(url: URL) /// The app's home screen. case roomList @@ -61,7 +61,7 @@ enum AppRoute: Hashable { var isAuthenticationRoute: Bool { switch self { case .accountProvisioningLink: true - case .oidcCallback: true + case .oAuthCallback: true default: false } } @@ -87,7 +87,7 @@ struct AppRouteURLParser { MatrixPermalinkParser(), ElementWebURLParser(domains: appSettings.elementWebHosts), AccountProvisioningURLParser(domain: appSettings.accountProvisioningHost), - OIDCCallbackURLParser(redirectURL: appSettings.oidcRedirectURL) + OAuthCallbackURLParser(redirectURL: appSettings.oAuthRedirectURL) ] } @@ -204,12 +204,12 @@ private struct AccountProvisioningURLParser: URLParser { } } -/// The parser for the OIDC callback URL. This always returns a `.oidcCallback`. -struct OIDCCallbackURLParser: URLParser { +/// The parser for the OAuth callback URL. This always returns an `.oAuthCallback`. +struct OAuthCallbackURLParser: URLParser { let redirectURL: URL func route(from url: URL) -> AppRoute? { guard url.absoluteString.starts(with: redirectURL.absoluteString) else { return nil } - return .oidcCallback(url: url) + return .oAuthCallback(url: url) } } diff --git a/ElementX/Sources/Application/Settings/AppSettings.swift b/ElementX/Sources/Application/Settings/AppSettings.swift index 76423c0f5..fc6e06e03 100644 --- a/ElementX/Sources/Application/Settings/AppSettings.swift +++ b/ElementX/Sources/Application/Settings/AppSettings.swift @@ -135,7 +135,7 @@ final class AppSettings { allowOtherAccountProviders: Bool, hideBrandChrome: Bool, pushGatewayBaseURL: URL, - oidcRedirectURL: URL, + oAuthRedirectURL: URL, websiteURL: URL, logoURL: URL, copyrightURL: URL, @@ -155,7 +155,7 @@ final class AppSettings { self.allowOtherAccountProviders = allowOtherAccountProviders self.hideBrandChrome = hideBrandChrome self.pushGatewayBaseURL = pushGatewayBaseURL - self.oidcRedirectURL = oidcRedirectURL + self.oAuthRedirectURL = oAuthRedirectURL self.websiteURL = websiteURL self.logoURL = logoURL self.copyrightURL = copyrightURL @@ -249,19 +249,19 @@ final class AppSettings { // MARK: - Authentication - /// Any pre-defined static client registrations for OIDC issuers. - let oidcStaticRegistrations: [URL: String] = ["https://id.thirdroom.io/realms/thirdroom": "elementx"] - /// The redirect URL used for OIDC. For the normal case we don't actually need the bundle ID as the web authentication session handles the redirect internally. + /// Any pre-defined static client registrations for OAuth issuers. + let oAuthStaticRegistrations: [URL: String] = ["https://id.thirdroom.io/realms/thirdroom": "elementx"] + /// The redirect URL used for OAuth. For the normal case we don't actually need the bundle ID as the web authentication session handles the redirect internally. /// However in the case where MAS sends the user to an external app, we need to make sure that the system will open the correct variant of the app (e.g. Nightly). - private(set) var oidcRedirectURL: URL! = URL(string: "https://element.io/oauth/ios/\(InfoPlistReader.main.bundleIdentifier)") + private(set) var oAuthRedirectURL: URL! = URL(string: "https://element.io/oauth/ios/\(InfoPlistReader.main.bundleIdentifier)") - private(set) lazy var oidcConfiguration = OIDCConfiguration(clientName: InfoPlistReader.main.bundleDisplayName, - redirectURI: oidcRedirectURL, - clientURI: websiteURL, - logoURI: logoURL, - tosURI: acceptableUseURL, - policyURI: privacyURL, - staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString }) + private(set) lazy var oAuthConfiguration = OAuthConfiguration(clientName: InfoPlistReader.main.bundleDisplayName, + redirectURI: oAuthRedirectURL, + clientURI: websiteURL, + logoURI: logoURL, + tosURI: acceptableUseURL, + policyURI: privacyURL, + staticRegistrations: oAuthStaticRegistrations.mapKeys { $0.absoluteString }) /// Whether or not the Create Account button is shown on the start screen. /// diff --git a/ElementX/Sources/Application/Settings/OAuthConfiguration.swift b/ElementX/Sources/Application/Settings/OAuthConfiguration.swift new file mode 100644 index 000000000..7b0030741 --- /dev/null +++ b/ElementX/Sources/Application/Settings/OAuthConfiguration.swift @@ -0,0 +1,36 @@ +// +// Copyright 2025 Element Creations Ltd. +// Copyright 2024-2025 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +struct OAuthConfiguration { + let clientName: String + let redirectURI: URL + let clientURI: URL + let logoURI: URL + let tosURI: URL + let policyURI: URL + let staticRegistrations: [String: String] +} + +#if canImport(MatrixRustSDK) +import MatrixRustSDK + +extension OAuthConfiguration { + var rustValue: MatrixRustSDK.OAuthConfiguration { + MatrixRustSDK.OAuthConfiguration(clientName: clientName, + redirectUri: redirectURI.absoluteString, + clientUri: clientURI.absoluteString, + logoUri: logoURI.absoluteString, + tosUri: tosURI.absoluteString, + policyUri: policyURI.absoluteString, + staticRegistrations: staticRegistrations) + } +} +#endif diff --git a/ElementX/Sources/Application/Settings/OIDCConfiguration.swift b/ElementX/Sources/Application/Settings/OIDCConfiguration.swift deleted file mode 100644 index c621657c9..000000000 --- a/ElementX/Sources/Application/Settings/OIDCConfiguration.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2025 Element Creations Ltd. -// Copyright 2024-2025 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. -// Please see LICENSE files in the repository root for full details. -// - -import Foundation - -struct OIDCConfiguration { - let clientName: String - let redirectURI: URL - let clientURI: URL - let logoURI: URL - let tosURI: URL - let policyURI: URL - let staticRegistrations: [String: String] -} - -#if canImport(MatrixRustSDK) -import MatrixRustSDK - -extension OIDCConfiguration { - var rustValue: OAuthConfiguration { - OAuthConfiguration(clientName: clientName, - redirectUri: redirectURI.absoluteString, - clientUri: clientURI.absoluteString, - logoUri: logoURI.absoluteString, - tosUri: tosURI.absoluteString, - policyUri: policyURI.absoluteString, - staticRegistrations: staticRegistrations) - } -} -#endif diff --git a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift index 75d6e7e16..de12f30c1 100644 --- a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift @@ -96,7 +96,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { private let stateMachine: StateMachine private var cancellables = Set() - private var oidcPresenter: OIDCAuthenticationPresenter? + private var oAuthPresenter: OAuthAuthenticationPresenter? // periphery:ignore - retaining purpose private var bugReportFlowCoordinator: BugReportFlowCoordinator? @@ -151,7 +151,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { } func clearRoute(animated: Bool) { - oidcPresenter?.cancel() // Handle ongoing OIDC authentication first. + oAuthPresenter?.cancel() // Handle ongoing OAuth authentication first. switch stateMachine.state { case .initial, .startScreen: @@ -175,13 +175,13 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { } } - func handleOIDCRedirectURL(_ url: URL) { - guard let oidcPresenter else { - MXLog.error("Failed to find an OIDC request in progress.") + func handleOAuthCallbackURL(_ url: URL) { + guard let oAuthPresenter else { + MXLog.error("Failed to find an OAuth request in progress.") return } - oidcPresenter.handleUniversalLinkCallback(url) + oAuthPresenter.handleUniversalLinkCallback(url) } // MARK: - Setup @@ -247,8 +247,8 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { // Completion stateMachine.addRoutes(event: .signedIn, transitions: [.qrCodeLoginScreen => .complete, - .serverConfirmationScreen => .complete, // OIDC authentication - .startScreen => .complete, // Direct OIDC authentication + .serverConfirmationScreen => .complete, // OAuth authentication + .startScreen => .complete, // Direct OAuth authentication .loginScreen => .complete]) { [weak self] context in guard let userSession = context.userInfo as? UserSessionProtocol else { fatalError("The user session wasn't included in the context") } self?.userHasSignedIn(userSession: userSession) @@ -300,8 +300,8 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { case .register: stateMachine.tryEvent(.confirmServer(.register)) - case .loginDirectlyWithOIDC(let oidcData, let window): - showOIDCAuthentication(oidcData: oidcData, presentationAnchor: window) + case .loginDirectlyWithOAuth(let oAuthData, let window): + showOAuthAuthentication(oAuthData: oAuthData, presentationAnchor: window) case .loginDirectlyWithPassword(let loginHint): stateMachine.tryEvent(.continueWithPassword, userInfo: loginHint) @@ -335,8 +335,8 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { switch action { case .startOver: fatalError("QR code login shouldn't request to start over as it's handled within the screen.") - case .requestOIDCAuthorisation, .linkedDevice: - fatalError("QR code login shouldn't request an OIDC flow or link a device.") + case .requestOAuthAuthorisation, .linkedDevice: + fatalError("QR code login shouldn't request an OAuth flow or link a device.") case .signInManually: navigationStackCoordinator.setSheetCoordinator(nil) stateMachine.tryEvent(.cancelledLoginWithQR) @@ -374,8 +374,8 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { - case .continueWithOIDC(let oidcData, let window): - showOIDCAuthentication(oidcData: oidcData, presentationAnchor: window) + case .continueWithOAuth(let oAuthData, let window): + showOAuthAuthentication(oAuthData: oAuthData, presentationAnchor: window) case .continueWithPassword: stateMachine.tryEvent(.continueWithPassword) case .changeServer: @@ -420,22 +420,22 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { /// **Note:** We have intentionally excluded this presentation from the state machine as it doesn't mutate our navigation stack and there /// isn't a robust way to detect why the user returned to the app when the MAS URL directly opens an external app for authentication without /// presenting a web authentication session. - private func showOIDCAuthentication(oidcData: OIDCAuthorizationDataProxy, presentationAnchor: UIWindow) { - let presenter = OIDCAuthenticationPresenter(authenticationService: authenticationService, - oidcRedirectURL: appSettings.oidcRedirectURL, - presentationAnchor: presentationAnchor, - appMediator: appMediator, - userIndicatorController: userIndicatorController) - oidcPresenter = presenter + private func showOAuthAuthentication(oAuthData: OAuthAuthorizationDataProxy, presentationAnchor: UIWindow) { + let presenter = OAuthAuthenticationPresenter(authenticationService: authenticationService, + redirectURL: appSettings.oAuthRedirectURL, + presentationAnchor: presentationAnchor, + appMediator: appMediator, + userIndicatorController: userIndicatorController) + oAuthPresenter = presenter Task { - switch await presenter.authenticate(using: oidcData) { + switch await presenter.authenticate(using: oAuthData) { case .success(let userSession): stateMachine.tryEvent(.signedIn, userInfo: userSession) case .failure: break // Nothing to do, any alerts will be handled by the presenter. } - oidcPresenter = nil + oAuthPresenter = nil } } @@ -454,8 +454,8 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { switch action { case .signedIn(let userSession): stateMachine.tryEvent(.signedIn, userInfo: userSession) - case .configuredForOIDC: - // Pop back to the confirmation screen for OIDC login to continue. + case .configuredForOAuth: + // Pop back to the confirmation screen for OAuth login to continue. navigationStackCoordinator.pop(animated: false) } } diff --git a/ElementX/Sources/FlowCoordinators/ChatsTabFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/ChatsTabFlowCoordinator.swift index 175c64693..2629b21c9 100644 --- a/ElementX/Sources/FlowCoordinators/ChatsTabFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/ChatsTabFlowCoordinator.swift @@ -174,7 +174,7 @@ class ChatsTabFlowCoordinator: FlowCoordinatorProtocol { } case .globalSearch: presentGlobalSearch() - case .accountProvisioningLink, .oidcCallback, .settings, .chatBackupSettings, .call: + case .accountProvisioningLink, .oAuthCallback, .settings, .chatBackupSettings, .call: break // These routes cannot be handled. } } diff --git a/ElementX/Sources/FlowCoordinators/EncryptionResetFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/EncryptionResetFlowCoordinator.swift index b3fc7bf93..3e4993866 100644 --- a/ElementX/Sources/FlowCoordinators/EncryptionResetFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/EncryptionResetFlowCoordinator.swift @@ -122,8 +122,8 @@ class EncryptionResetFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { - case .requestOIDCAuthorisation(let url): - presentOIDCAuthorization(for: url) + case .requestOAuthAuthorisation(let url): + presentOAuthAuthorization(for: url) case .requestPassword(let passwordPublisher): stateMachine.tryEvent(.confirmPassword, userInfo: passwordPublisher) case .cancel: @@ -155,14 +155,14 @@ class EncryptionResetFlowCoordinator: FlowCoordinatorProtocol { } } - private var accountSettingsPresenter: OIDCAccountSettingsPresenter? - private func presentOIDCAuthorization(for url: URL) { + private var accountSettingsPresenter: OAuthAccountSettingsPresenter? + private func presentOAuthAuthorization(for url: URL) { // Note to anyone in the future if you come back here to make this open in Safari instead of a WAS. // As of iOS 16, there is an issue on the simulator with accessing the cookie but it works on a device. 🤷‍♂️ - accountSettingsPresenter = OIDCAccountSettingsPresenter(accountURL: url, - presentationAnchor: windowManager.mainWindow, - appMediator: appMediator, - appSettings: appSettings) + accountSettingsPresenter = OAuthAccountSettingsPresenter(accountURL: url, + presentationAnchor: windowManager.mainWindow, + appMediator: appMediator, + appSettings: appSettings) accountSettingsPresenter?.start() } } diff --git a/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift index 889b46688..e103f996a 100644 --- a/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift @@ -80,7 +80,7 @@ class EncryptionSettingsFlowCoordinator: FlowCoordinatorProtocol { MXLog.info("Handling app route: \(appRoute)") switch appRoute { - case .accountProvisioningLink, .oidcCallback: + case .accountProvisioningLink, .oAuthCallback: break // We always ignore these flows when logged in. case .roomList, .room, .roomAlias, .childRoom, .childRoomAlias, .roomDetails, .roomMemberDetails, .userProfile, .thread, diff --git a/ElementX/Sources/FlowCoordinators/LinkNewDeviceFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/LinkNewDeviceFlowCoordinator.swift index 4fe880e07..1e1504a66 100644 --- a/ElementX/Sources/FlowCoordinators/LinkNewDeviceFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/LinkNewDeviceFlowCoordinator.swift @@ -9,7 +9,7 @@ import Combine import Foundation enum LinkNewDeviceFlowCoordinatorAction { - case requestOIDCAuthorisation(URL, OIDCAccountSettingsPresenter.Continuation) + case requestOAuthAuthorisation(URL, OAuthAccountSettingsPresenter.Continuation) case dismiss } @@ -77,8 +77,8 @@ class LinkNewDeviceFlowCoordinator: FlowCoordinatorProtocol { fatalError("QR linking shouldn't send sign-in actions.") case .startOver: navigationStackCoordinator.pop() // Pops back to the LinkNewDeviceScreen. - case .requestOIDCAuthorisation(let url, let continuation): - actionsSubject.send(.requestOIDCAuthorisation(url, continuation)) + case .requestOAuthAuthorisation(let url, let continuation): + actionsSubject.send(.requestOAuthAuthorisation(url, continuation)) case .linkedDevice: actionsSubject.send(.dismiss) case .cancel: diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index daf5b1f43..12491212f 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -201,7 +201,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } case .roomAlias, .childRoomAlias, .eventOnRoomAlias, .childEventOnRoomAlias: break // These are converted to a room ID route one level above. - case .accountProvisioningLink, .oidcCallback, .roomList, .userProfile, .call, .settings, .chatBackupSettings, .globalSearch: + case .accountProvisioningLink, .oAuthCallback, .roomList, .userProfile, .call, .settings, .chatBackupSettings, .globalSearch: break // These routes can't be handled. case .transferOwnership(let roomID): guard self.roomID == roomID else { fatalError("Navigation route doesn't belong to this room flow.") } diff --git a/ElementX/Sources/FlowCoordinators/RoomMembersFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomMembersFlowCoordinator.swift index cd240760c..ede424562 100644 --- a/ElementX/Sources/FlowCoordinators/RoomMembersFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomMembersFlowCoordinator.swift @@ -120,7 +120,7 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol { } case .roomAlias, .childRoomAlias, .eventOnRoomAlias, .childEventOnRoomAlias: break // These are converted to a room ID route one level above. - case .accountProvisioningLink, .oidcCallback, + case .accountProvisioningLink, .oAuthCallback, .roomList, .room, .roomDetails, .event, .userProfile, .call, .settings, .chatBackupSettings, .share, .transferOwnership, .thread, .globalSearch: diff --git a/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift index 3d0a3d94a..e0304967f 100644 --- a/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift @@ -188,7 +188,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol { switch action { case .dismiss: navigationStackCoordinator.setSheetCoordinator(nil) - case .requestOIDCAuthorisation(let url, let continuation): + case .requestOAuthAuthorisation(let url, let continuation): presentAccountManagementURL(url, continuation: continuation) } } @@ -295,17 +295,17 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol { navigationStackCoordinator.push(coordinator) } - // MARK: OIDC Account Management + // MARK: OAuth Account Management - private var accountSettingsPresenter: OIDCAccountSettingsPresenter? - private func presentAccountManagementURL(_ url: URL, continuation: OIDCAccountSettingsPresenter.Continuation? = nil) { + private var accountSettingsPresenter: OAuthAccountSettingsPresenter? + private func presentAccountManagementURL(_ url: URL, continuation: OAuthAccountSettingsPresenter.Continuation? = nil) { // Note to anyone in the future if you come back here to make this open in Safari instead of a WAS. // As of iOS 16, there is an issue on the simulator with accessing the cookie but it works on a device. 🤷‍♂️ - accountSettingsPresenter = OIDCAccountSettingsPresenter(accountURL: url, - presentationAnchor: flowParameters.windowManager.mainWindow, - appMediator: flowParameters.appMediator, - appSettings: flowParameters.appSettings, - continuation: continuation) + accountSettingsPresenter = OAuthAccountSettingsPresenter(accountURL: url, + presentationAnchor: flowParameters.windowManager.mainWindow, + appMediator: flowParameters.appMediator, + appSettings: flowParameters.appSettings, + continuation: continuation) accountSettingsPresenter?.start() } } diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 4cfb22cf4..ddb677a57 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -121,7 +121,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { MXLog.info("Handling app route: \(appRoute)") switch appRoute { - case .accountProvisioningLink, .oidcCallback: + case .accountProvisioningLink, .oAuthCallback: break // We always ignore these flows when logged in. case .settings, .chatBackupSettings: if ProcessInfo.processInfo.isiOSAppOnMac, flowParameters.windowManager.secondaryWindowsEnabled { diff --git a/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift b/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift index 0127360a6..b3ff45c78 100644 --- a/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift +++ b/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift @@ -18,26 +18,26 @@ extension AuthenticationClientFactoryMock { "example.com": ClientSDKMock(configuration: .init(serverAddress: "example.com", homeserverURL: "https://matrix.example.com", slidingSyncVersion: .native, - oidcLoginURL: nil, - supportsOIDCCreatePrompt: false, + oAuthLoginURL: nil, + supportsOAuthCreatePrompt: false, supportsPasswordLogin: true)), "company.com": ClientSDKMock(configuration: .init(serverAddress: "company.com", homeserverURL: "https://matrix.company.com", slidingSyncVersion: .native, - oidcLoginURL: "https://auth.company.com/oidc", - supportsOIDCCreatePrompt: false, + oAuthLoginURL: "https://auth.company.com/login", + supportsOAuthCreatePrompt: false, supportsPasswordLogin: false)), "server.net": ClientSDKMock(configuration: .init(serverAddress: "server.net", homeserverURL: "https://matrix.server.net", slidingSyncVersion: .native, - oidcLoginURL: nil, - supportsOIDCCreatePrompt: false, + oAuthLoginURL: nil, + supportsOAuthCreatePrompt: false, supportsPasswordLogin: false)), "secure.gov": ClientSDKMock(configuration: .init(serverAddress: "secure.gov", homeserverURL: "https://ess.secure.gov", slidingSyncVersion: .native, - oidcLoginURL: "https://auth.secure.gov/oidc", - supportsOIDCCreatePrompt: false, + oAuthLoginURL: "https://auth.secure.gov/login", + supportsOAuthCreatePrompt: false, supportsPasswordLogin: false, elementWellKnown: "{\"version\":1,\"enforce_element_pro\":true}")) ] diff --git a/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift b/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift index b7960b943..9d139c151 100644 --- a/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift +++ b/ElementX/Sources/Mocks/SDK/ClientSDKMock.swift @@ -17,8 +17,8 @@ extension ClientSDKMock { var serverAddress = "matrix.org" var homeserverURL = "https://matrix-client.matrix.org" var slidingSyncVersion = SlidingSyncVersion.native - var oidcLoginURL: String? = "https://account.matrix.org/authorize" - var supportsOIDCCreatePrompt = true + var oAuthLoginURL: String? = "https://account.matrix.org/authorize" + var supportsOAuthCreatePrompt = true var supportsPasswordLogin = true var elementWellKnown: String? var validCredentials = (username: "alice", password: "12345678") @@ -77,8 +77,8 @@ extension HomeserverLoginDetailsSDKMock { slidingSyncVersionReturnValue = configuration.slidingSyncVersion supportsPasswordLoginReturnValue = configuration.supportsPasswordLogin - supportsOauthLoginReturnValue = configuration.oidcLoginURL != nil - supportedOauthPromptsReturnValue = switch (configuration.oidcLoginURL, configuration.supportsOIDCCreatePrompt) { + supportsOauthLoginReturnValue = configuration.oAuthLoginURL != nil + supportedOauthPromptsReturnValue = switch (configuration.oAuthLoginURL, configuration.supportsOAuthCreatePrompt) { case (.none, _): [] case (.some, true): [.consent, .create] case (.some, false): [.consent] @@ -91,6 +91,6 @@ extension OAuthAuthorizationDataSDKMock { convenience init(configuration: ClientSDKMock.Configuration) { self.init() - loginUrlReturnValue = configuration.oidcLoginURL + loginUrlReturnValue = configuration.oAuthLoginURL } } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift index b5662186d..2aaba760e 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginHomeserver.swift @@ -46,17 +46,17 @@ struct LoginHomeserver: Equatable { extension LoginHomeserver { /// A mock homeserver that is configured just like matrix.org. static var mockMatrixDotOrg: LoginHomeserver { - LoginHomeserver(address: "matrix.org", loginMode: .oidc(supportsCreatePrompt: true)) + LoginHomeserver(address: "matrix.org", loginMode: .oAuth(supportsCreatePrompt: true)) } - /// A mock homeserver that supports login and registration via a password but has no SSO providers. + /// A mock homeserver that supports login and registration via a password but has no OAuth support. static var mockBasicServer: LoginHomeserver { LoginHomeserver(address: "example.com", loginMode: .password) } - /// A mock homeserver that supports only supports authentication via a single SSO provider. - static var mockOIDC: LoginHomeserver { - LoginHomeserver(address: "company.com", loginMode: .oidc(supportsCreatePrompt: false)) + /// A mock homeserver that supports only supports authentication via OAuth. + static var mockOAuth: LoginHomeserver { + LoginHomeserver(address: "company.com", loginMode: .oAuth(supportsCreatePrompt: false)) } /// A mock homeserver that only with no supported login flows. diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift index 8fd9b82c0..fc2875a36 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginMode.swift @@ -13,15 +13,15 @@ enum LoginMode: Equatable { /// The login mode hasn't been determined yet. case unknown /// The homeserver supports login via OpenID Connect. - case oidc(supportsCreatePrompt: Bool) + case oAuth(supportsCreatePrompt: Bool) /// The homeserver supports login with a password. case password /// The homeserver only allows login with unsupported mechanisms. Use fallback instead. case unsupported - var supportsOIDCFlow: Bool { + var supportsOAuthFlow: Bool { switch self { - case .oidc: true + case .oAuth: true default: false } } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift index baa44f891..49380f7c4 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift @@ -20,8 +20,8 @@ struct LoginScreenCoordinatorParameters { } enum LoginScreenCoordinatorAction { - /// The homeserver was updated to one that supports OIDC. - case configuredForOIDC + /// The homeserver was updated to one that supports OAuth. + case configuredForOAuth /// Login was successful. case signedIn(UserSessionProtocol) } @@ -62,8 +62,8 @@ final class LoginScreenCoordinator: CoordinatorProtocol { guard let self else { return } switch action { - case .configuredForOIDC: - actionsSubject.send(.configuredForOIDC) + case .configuredForOAuth: + actionsSubject.send(.configuredForOAuth) case .signedIn(let userSession): actionsSubject.send(.signedIn(userSession)) } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift index 6096794a9..43d3fe049 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift @@ -9,14 +9,14 @@ import Foundation enum LoginScreenViewModelAction { - /// The homeserver was updated to one that supports OIDC. - case configuredForOIDC + /// The homeserver was updated to one that supports OAuth. + case configuredForOAuth /// Login was successful. case signedIn(UserSessionProtocol) - var isConfiguredForOIDC: Bool { + var isConfiguredForOAuth: Bool { switch self { - case .configuredForOIDC: true + case .configuredForOAuth: true default: false } } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift index cd9f0a64a..9019e275f 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift @@ -78,8 +78,8 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc Task { switch await authenticationService.configure(for: homeserverDomain, flow: .login) { case .success: - if authenticationService.homeserver.value.loginMode.supportsOIDCFlow { - actionsSubject.send(.configuredForOIDC) + if authenticationService.homeserver.value.loginMode.supportsOAuthFlow { + actionsSubject.send(.configuredForOAuth) } stopLoading() case .failure(let error): diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift index 5a9b1f80c..47fc6171d 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift @@ -27,7 +27,7 @@ struct LoginScreen: View { switch context.viewState.loginMode { case .password: loginForm - case .oidc: + case .oAuth: // This should never be shown. ProgressView() default: @@ -102,7 +102,7 @@ struct LoginScreen: View { } } - /// Text shown if neither password or OIDC login is supported. + /// Text shown if neither password or OAuth login is supported. var loginUnavailableText: some View { Text(L10n.screenLoginErrorUnsupportedAuthentication) .font(.body) diff --git a/ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift b/ElementX/Sources/Screens/Authentication/OAuthAuthenticationPresenter.swift similarity index 83% rename from ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift rename to ElementX/Sources/Screens/Authentication/OAuthAuthenticationPresenter.swift index 9769198ca..7c2fe0f18 100644 --- a/ElementX/Sources/Screens/Authentication/OIDCAuthenticationPresenter.swift +++ b/ElementX/Sources/Screens/Authentication/OAuthAuthenticationPresenter.swift @@ -8,15 +8,15 @@ import AuthenticationServices -/// Presents a web authentication session for an OIDC request. +/// Presents a web authentication session for an OAuth request. /// /// In certain instances the URL may require opening an external app instead of using a WAS. Because of this -/// it is recommended to not encode the OIDC authentication within any state machines, as there is no guarantee +/// it is recommended to not encode the OAuth authentication within any state machines, as there is no guarantee /// that any cancellations/failures will be communicated upwards. @MainActor -class OIDCAuthenticationPresenter: NSObject { +class OAuthAuthenticationPresenter: NSObject { private let authenticationService: AuthenticationServiceProtocol - private let oidcRedirectURL: URL + private let redirectURL: URL private let presentationAnchor: UIWindow private let appMediator: AppMediatorProtocol private let userIndicatorController: UserIndicatorControllerProtocol @@ -36,12 +36,12 @@ class OIDCAuthenticationPresenter: NSObject { private var activeRequest: Request? init(authenticationService: AuthenticationServiceProtocol, - oidcRedirectURL: URL, + redirectURL: URL, presentationAnchor: UIWindow, appMediator: AppMediatorProtocol, userIndicatorController: UserIndicatorControllerProtocol) { self.authenticationService = authenticationService - self.oidcRedirectURL = oidcRedirectURL + self.redirectURL = redirectURL self.presentationAnchor = presentationAnchor self.appMediator = appMediator self.userIndicatorController = userIndicatorController @@ -53,11 +53,11 @@ class OIDCAuthenticationPresenter: NSObject { /// **Note:** The failure case cannot be relied upon as a signal that the authentication has ended. /// In particular if the authentication URL requires opening an external app, then the user may return /// to the app without completing (or cancelling) the authentication. - func authenticate(using oidcData: OIDCAuthorizationDataProxy) async -> Result { + func authenticate(using oAuthData: OAuthAuthorizationDataProxy) async -> Result { let response = await withCheckedContinuation { continuation in - let authenticationURL = oidcData.url + let authenticationURL = oAuthData.url - let session = ASWebAuthenticationSession(url: authenticationURL, callback: .oidcRedirectURL(oidcRedirectURL)) { url, error in + let session = ASWebAuthenticationSession(url: authenticationURL, callback: .oAuthRedirectURL(redirectURL)) { url, error in MXLog.info("Handling callback from the session.") continuation.resume(returning: Response(url: url, isExternal: false, error: error)) } @@ -86,30 +86,30 @@ class OIDCAuthenticationPresenter: NSObject { guard let url = response.url else { // Check for user cancellation (on the WAS sheet) to avoid showing an alert in that instance. - if response.error?.isOIDCUserCancellation == true { + if response.error?.isOAuthUserCancellation == true { // No need to show an error here, just abort and return a failure. - await authenticationService.abortOIDCLogin(data: oidcData) - return .failure(.oidcError(.userCancellation)) + await authenticationService.abortOAuthLogin(data: oAuthData) + return .failure(.oAuthError(.userCancellation)) } let errorDescription = response.error.map(String.init(describing:)) ?? "Unknown error" MXLog.error("Missing callback URL from the web authentication session: \(errorDescription)") showFailureIndicator() - await authenticationService.abortOIDCLogin(data: oidcData) - return .failure(.oidcError(.unknown)) + await authenticationService.abortOAuthLogin(data: oAuthData) + return .failure(.oAuthError(.unknown)) } // Exchanging the callback with the homeserver can be slow, so show the loading indicator while we wait (the modal has already been dismissed). startLoading(delay: .milliseconds(50)) // Small delay to handle a cancellation callback without the indicator showing. defer { stopLoading() } - switch await authenticationService.loginWithOIDCCallback(url) { + switch await authenticationService.loginWithOAuthCallback(url) { case .success(let userSession): return .success(userSession) - case .failure(.oidcError(.userCancellation)): // Check for user cancellation (on the MAS web page) + case .failure(.oAuthError(.userCancellation)): // Check for user cancellation (on the MAS web page) // No need to show an error here, just return the failure. - return .failure(.oidcError(.userCancellation)) + return .failure(.oAuthError(.userCancellation)) case .failure(let error): MXLog.error("Error occurred: \(error)") showFailureIndicator() @@ -163,20 +163,20 @@ class OIDCAuthenticationPresenter: NSObject { // MARK: ASWebAuthenticationPresentationContextProviding -extension OIDCAuthenticationPresenter: ASWebAuthenticationPresentationContextProviding { +extension OAuthAuthenticationPresenter: ASWebAuthenticationPresentationContextProviding { func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { presentationAnchor } } extension ASWebAuthenticationSession.Callback { - static func oidcRedirectURL(_ url: URL) -> Self { + static func oAuthRedirectURL(_ url: URL) -> Self { if url.scheme == "https", let host = url.host() { .https(host: host, path: url.path()) } else if let scheme = url.scheme { .customScheme(scheme) } else { - fatalError("Invalid OIDC redirect URL: \(url)") + fatalError("Invalid OAuth redirect URL: \(url)") } } } @@ -184,7 +184,7 @@ extension ASWebAuthenticationSession.Callback { // MARK: - Helpers extension Error { - var isOIDCUserCancellation: Bool { + var isOAuthUserCancellation: Bool { let nsError = self as NSError if nsError.domain == ASWebAuthenticationSessionErrorDomain, diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift index f69e5d5af..5c4c71c31 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift @@ -17,7 +17,7 @@ struct ServerConfirmationScreenCoordinatorParameters { } enum ServerConfirmationScreenCoordinatorAction { - case continueWithOIDC(data: OIDCAuthorizationDataProxy, window: UIWindow) + case continueWithOAuth(data: OAuthAuthorizationDataProxy, window: UIWindow) case continueWithPassword case changeServer } @@ -50,8 +50,8 @@ final class ServerConfirmationScreenCoordinator: CoordinatorProtocol { guard let self else { return } switch action { - case .continueWithOIDC(let oidcData, let window): - actionsSubject.send(.continueWithOIDC(data: oidcData, window: window)) + case .continueWithOAuth(let oAuthData, let window): + actionsSubject.send(.continueWithOAuth(data: oAuthData, window: window)) case .continueWithPassword: actionsSubject.send(.continueWithPassword) case .changeServer: diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift index 6f0c8df6b..0af2c6bef 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift @@ -9,8 +9,8 @@ import SwiftUI enum ServerConfirmationScreenViewModelAction { - /// Continue the flow using the provided OIDC parameters. - case continueWithOIDC(data: OIDCAuthorizationDataProxy, window: UIWindow) + /// Continue the flow using the provided OAuth parameters. + case continueWithOAuth(data: OAuthAuthorizationDataProxy, window: UIWindow) /// Continue the flow using password authentication. case continueWithPassword /// The user would like to change to a different homeserver. @@ -29,7 +29,7 @@ struct ServerConfirmationScreenViewState: BindableState { var mode: ServerConfirmationScreenMode /// The flow being attempted on the selected homeserver. let authenticationFlow: AuthenticationFlow - /// The presentation anchor used for OIDC authentication. + /// The presentation anchor used for OAuth authentication. var window: UIWindow? var bindings = ServerConfirmationScreenBindings() @@ -76,7 +76,7 @@ struct ServerConfirmationScreenBindings { } enum ServerConfirmationScreenViewAction { - /// Updates the window used as the OIDC presentation anchor. + /// Updates the window used as the OAuth presentation anchor. case updateWindow(UIWindow) /// The user would like to continue with the current homeserver. case confirm diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift index cc1380228..396b9a27e 100644 --- a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift @@ -133,7 +133,7 @@ class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType, } private func fetchLoginURLIfNeededAndContinue() async { - guard authenticationService.homeserver.value.loginMode.supportsOIDCFlow else { + guard authenticationService.homeserver.value.loginMode.supportsOAuthFlow else { actionsSubject.send(.continueWithPassword) return } @@ -146,9 +146,9 @@ class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType, startLoading() // Uses the same ID, so no need to worry if the indicator already exists defer { stopLoading() } - switch await authenticationService.urlForOIDCLogin(loginHint: nil) { - case .success(let oidcData): - actionsSubject.send(.continueWithOIDC(data: oidcData, window: window)) + switch await authenticationService.urlForOAuthLogin(loginHint: nil) { + case .success(let oAuthData): + actionsSubject.send(.continueWithOAuth(data: oAuthData, window: window)) case .failure: displayError(.unknownError) } diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift index 326fe700c..73e8ef4c4 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/MockSoftLogoutScreenState.swift @@ -17,7 +17,7 @@ enum MockSoftLogoutScreenState: String, CaseIterable { // mock that screen. case emptyPassword case enteredPassword - case oidc + case oAuth case unsupported case keyBackupNeeded @@ -37,9 +37,9 @@ enum MockSoftLogoutScreenState: String, CaseIterable { homeserver: .mockBasicServer, keyBackupNeeded: false, password: "12345678") - case .oidc: + case .oAuth: return SoftLogoutScreenViewModel(credentials: credentials, - homeserver: .mockOIDC, + homeserver: .mockOAuth, keyBackupNeeded: false) case .unsupported: return SoftLogoutScreenViewModel(credentials: credentials, diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift index 8acafca00..8a65b4dd0 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift @@ -46,7 +46,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol { parameters.authenticationService } - private var oidcPresenter: OIDCAuthenticationPresenter? + private var oAuthPresenter: OAuthAuthenticationPresenter? var actions: AnyPublisher { actionsSubject.eraseToAnyPublisher() @@ -76,8 +76,8 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol { showForgotPasswordScreen() case .clearAllData: actionsSubject.send(.clearAllData) - case .continueWithOIDC: - continueWithOIDC(presentationAnchor: viewModel.context.viewState.window) + case .continueWithOAuth: + continueWithOAuth(presentationAnchor: viewModel.context.viewState.window) } } .store(in: &cancellables) @@ -91,13 +91,13 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol { AnyView(SoftLogoutScreen(context: viewModel.context)) } - func handleOIDCRedirectURL(_ url: URL) { - guard let oidcPresenter else { - MXLog.error("Failed to find an OIDC request in progress.") + func handleOAuthCallbackURL(_ url: URL) { + guard let oAuthPresenter else { + MXLog.error("Failed to find an OAuth request in progress.") return } - oidcPresenter.handleUniversalLinkCallback(url) + oAuthPresenter.handleUniversalLinkCallback(url) } // MARK: - Private @@ -143,32 +143,32 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol { } } - private func continueWithOIDC(presentationAnchor: UIWindow?) { + private func continueWithOAuth(presentationAnchor: UIWindow?) { guard let presentationAnchor else { return } startLoading() Task { - switch await authenticationService.urlForOIDCLogin(loginHint: nil) { + switch await authenticationService.urlForOAuthLogin(loginHint: nil) { case .failure(let error): stopLoading() handleError(error) - case .success(let oidcData): + case .success(let oAuthData): stopLoading() - let presenter = OIDCAuthenticationPresenter(authenticationService: parameters.authenticationService, - oidcRedirectURL: parameters.appSettings.oidcRedirectURL, - presentationAnchor: presentationAnchor, - appMediator: parameters.appMediator, - userIndicatorController: parameters.userIndicatorController) - self.oidcPresenter = presenter - switch await presenter.authenticate(using: oidcData) { + let presenter = OAuthAuthenticationPresenter(authenticationService: parameters.authenticationService, + redirectURL: parameters.appSettings.oAuthRedirectURL, + presentationAnchor: presentationAnchor, + appMediator: parameters.appMediator, + userIndicatorController: parameters.userIndicatorController) + self.oAuthPresenter = presenter + switch await presenter.authenticate(using: oAuthData) { case .success(let userSession): actionsSubject.send(.signedIn(userSession)) case .failure(let error): handleError(error) } - self.oidcPresenter = nil + self.oAuthPresenter = nil } } } @@ -180,10 +180,10 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol { viewModel.displayError(.alert(L10n.screenLoginErrorInvalidCredentials)) case .accountDeactivated: viewModel.displayError(.alert(L10n.screenLoginErrorDeactivatedAccount)) - case .oidcError(.notSupported): - // Temporary alert hijacking the use of .notSupported, can be removed when OIDC support is in the SDK. + case .oAuthError(.notSupported): + // Temporary alert hijacking the use of .notSupported, can be removed when OAuth support is in the SDK. viewModel.displayError(.alert(L10n.commonServerNotSupported)) - case .oidcError(.userCancellation): + case .oAuthError(.userCancellation): // No need to show an error, the user cancelled authentication. break case .sessionTokenRefreshNotSupported: diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift index 1e2e00bc3..598fce80b 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenModels.swift @@ -22,8 +22,8 @@ enum SoftLogoutScreenViewModelAction: CustomStringConvertible { case forgotPassword /// Clear all user data case clearAllData - /// Continue using OIDC. - case continueWithOIDC + /// Continue using OAuth. + case continueWithOAuth /// A string representation of the result, ignoring any associated values that could leak PII. var description: String { @@ -34,8 +34,8 @@ enum SoftLogoutScreenViewModelAction: CustomStringConvertible { return "forgotPassword" case .clearAllData: return "clearAllData" - case .continueWithOIDC: - return "continueWithOIDC" + case .continueWithOAuth: + return "continueWithOAuth" } } } @@ -58,7 +58,7 @@ struct SoftLogoutScreenViewState: BindableState { homeserver.loginMode } - /// The presentation anchor used for OIDC authentication. + /// The presentation anchor used for OAuth authentication. var window: UIWindow? /// Whether to show recover encryption keys message @@ -80,7 +80,7 @@ struct SoftLogoutScreenBindings { } enum SoftLogoutScreenViewAction { - /// Updates the window used as the OIDC presentation anchor. + /// Updates the window used as the OAuth presentation anchor. case updateWindow(UIWindow?) /// Login. case login @@ -88,8 +88,8 @@ enum SoftLogoutScreenViewAction { case forgotPassword /// Clear all user data. case clearAllData - /// Continue using OIDC. - case continueWithOIDC + /// Continue using OAuth. + case continueWithOAuth } enum SoftLogoutScreenErrorType: Hashable { diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift index 561bfb091..402061977 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenViewModel.swift @@ -38,8 +38,8 @@ class SoftLogoutScreenViewModel: SoftLogoutScreenViewModelType, SoftLogoutScreen actionsSubject.send(.forgotPassword) case .clearAllData: actionsSubject.send(.clearAllData) - case .continueWithOIDC: - actionsSubject.send(.continueWithOIDC) + case .continueWithOAuth: + actionsSubject.send(.continueWithOAuth) case .updateWindow(let window): guard state.window != window else { return } Task { state.window = window } diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift index 31c16cd11..2a9e9045c 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift @@ -26,8 +26,8 @@ struct SoftLogoutScreen: View { switch context.viewState.loginMode { case .password: loginForm - case .oidc: - oidcButton + case .oAuth: + oAuthButton default: loginUnavailableText } @@ -98,15 +98,15 @@ struct SoftLogoutScreen: View { } } - /// The OIDC button that can be used for login. - var oidcButton: some View { - Button { context.send(viewAction: .continueWithOIDC) } label: { + /// The OAuth button that can be used for login. + var oAuthButton: some View { + Button { context.send(viewAction: .continueWithOAuth) } label: { Text(L10n.actionContinue) } .buttonStyle(.compound(.primary)) } - /// Text shown if neither password or OIDC login is supported. + /// Text shown if neither password or OAuth login is supported. var loginUnavailableText: some View { Text(L10n.screenLoginErrorUnsupportedAuthentication) .font(.body) diff --git a/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenCoordinator.swift index 92d09ebcd..bbdbfcbc7 100644 --- a/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenCoordinator.swift @@ -24,7 +24,7 @@ enum AuthenticationStartScreenCoordinatorAction { case login case register - case loginDirectlyWithOIDC(data: OIDCAuthorizationDataProxy, window: UIWindow) + case loginDirectlyWithOAuth(data: OAuthAuthorizationDataProxy, window: UIWindow) case loginDirectlyWithPassword(loginHint: String?) case reportProblem @@ -65,8 +65,8 @@ final class AuthenticationStartScreenCoordinator: CoordinatorProtocol { case .register: actionsSubject.send(.register) - case .loginDirectlyWithOIDC(let data, let window): - actionsSubject.send(.loginDirectlyWithOIDC(data: data, window: window)) + case .loginDirectlyWithOAuth(let data, let window): + actionsSubject.send(.loginDirectlyWithOAuth(data: data, window: window)) case .loginDirectlyWithPassword(let loginHint): actionsSubject.send(.loginDirectlyWithPassword(loginHint: loginHint)) diff --git a/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenModels.swift b/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenModels.swift index a3d3d7461..ed9e3afd7 100644 --- a/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenModels.swift @@ -13,7 +13,7 @@ enum AuthenticationStartScreenViewModelAction: Equatable { case login case register - case loginDirectlyWithOIDC(data: OIDCAuthorizationDataProxy, window: UIWindow) + case loginDirectlyWithOAuth(data: OAuthAuthorizationDataProxy, window: UIWindow) case loginDirectlyWithPassword(loginHint: String?) case reportProblem @@ -21,7 +21,7 @@ enum AuthenticationStartScreenViewModelAction: Equatable { } struct AuthenticationStartScreenViewState: BindableState { - /// The presentation anchor used for OIDC authentication. + /// The presentation anchor used for OAuth authentication. var window: UIWindow? let serverName: String? @@ -56,7 +56,7 @@ enum AuthenticationStartScreenAlertType { } enum AuthenticationStartScreenViewAction { - /// Updates the window used as the OIDC presentation anchor. + /// Updates the window used as the OAuth presentation anchor. case updateWindow(UIWindow) case developerOptions case reportProblem diff --git a/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenViewModel.swift index 1cc7e5ae7..3e16fd313 100644 --- a/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/StartScreen/AuthenticationStartScreenViewModel.swift @@ -144,7 +144,7 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType } } - guard authenticationService.homeserver.value.loginMode.supportsOIDCFlow else { + guard authenticationService.homeserver.value.loginMode.supportsOAuthFlow else { actionsSubject.send(.loginDirectlyWithPassword(loginHint: loginHint)) return } @@ -154,9 +154,9 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType return } - switch await authenticationService.urlForOIDCLogin(loginHint: loginHint) { - case .success(let oidcData): - actionsSubject.send(.loginDirectlyWithOIDC(data: oidcData, window: window)) + switch await authenticationService.urlForOAuthLogin(loginHint: loginHint) { + case .success(let oAuthData): + actionsSubject.send(.loginDirectlyWithOAuth(data: oAuthData, window: window)) case .failure: displayError() } diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift index 45296211d..872487172 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenCoordinator.swift @@ -10,7 +10,7 @@ import Combine import SwiftUI enum EncryptionResetScreenCoordinatorAction { - case requestOIDCAuthorisation(URL) + case requestOAuthAuthorisation(URL) case requestPassword(passwordPublisher: PassthroughSubject) case resetFinished case cancel @@ -44,8 +44,8 @@ final class EncryptionResetScreenCoordinator: CoordinatorProtocol { guard let self else { return } switch action { - case .requestOIDCAuthorisation(let url): - self.actionsSubject.send(.requestOIDCAuthorisation(url)) + case .requestOAuthAuthorisation(let url): + self.actionsSubject.send(.requestOAuthAuthorisation(url)) case .requestPassword(let passwordPublisher): self.actionsSubject.send(.requestPassword(passwordPublisher: passwordPublisher)) case .resetFinished: diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift index 038b2cde5..4d44f458e 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenModels.swift @@ -11,7 +11,7 @@ import Foundation enum EncryptionResetScreenViewModelAction { case requestPassword(passwordPublisher: PassthroughSubject) - case requestOIDCAuthorisation(url: URL) + case requestOAuthAuthorisation(url: URL) case resetFinished case cancel } diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift index a6e1c6a5a..4a142f2a1 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift @@ -91,9 +91,9 @@ class EncryptionResetScreenViewModel: EncryptionResetScreenViewModelType, Encryp hideLoadingIndicator() - actionsSubject.send(.requestOIDCAuthorisation(url: url)) + actionsSubject.send(.requestOAuthAuthorisation(url: url)) - await resetWithOIDCAuthorisation() + await resetWithOAuthAuthorisation() } case .failure(let error): MXLog.error("Failed resetting encryption with error \(error)") @@ -121,7 +121,7 @@ class EncryptionResetScreenViewModel: EncryptionResetScreenViewModelType, Encryp } } - private func resetWithOIDCAuthorisation() async { + private func resetWithOAuthAuthorisation() async { guard let identityResetHandle else { fatalError("Requested reset flow continuation without a stored handle") } diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift index 4015d0ce9..46108f5a7 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenCoordinator.swift @@ -24,7 +24,7 @@ enum QRCodeLoginScreenCoordinatorAction: CustomStringConvertible { case startOver case signInManually case signedIn(userSession: UserSessionProtocol) - case requestOIDCAuthorisation(URL, OIDCAccountSettingsPresenter.Continuation) + case requestOAuthAuthorisation(URL, OAuthAccountSettingsPresenter.Continuation) case linkedDevice /// Cancel the flow (dismiss the modal). case cancel @@ -34,7 +34,7 @@ enum QRCodeLoginScreenCoordinatorAction: CustomStringConvertible { case .startOver: "startOver" case .signInManually: "signInManually" case .signedIn: "signedIn" - case .requestOIDCAuthorisation: "requestOIDCAuthorisation" + case .requestOAuthAuthorisation: "requestOAuthAuthorisation" case .linkedDevice: "linkedDevice" case .cancel: "cancel" } @@ -71,8 +71,8 @@ final class QRCodeLoginScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.startOver) case .signedIn(let userSession): actionsSubject.send(.signedIn(userSession: userSession)) - case .requestOIDCAuthorisation(let url, let continuation): - actionsSubject.send(.requestOIDCAuthorisation(url, continuation)) + case .requestOAuthAuthorisation(let url, let continuation): + actionsSubject.send(.requestOAuthAuthorisation(url, continuation)) case .linkedDevice: actionsSubject.send(.linkedDevice) case .cancel: diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift index c4dc619b3..27b97be24 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenModels.swift @@ -16,7 +16,7 @@ enum QRCodeLoginScreenViewModelAction: CustomStringConvertible { case startOver case signInManually case signedIn(userSession: UserSessionProtocol) - case requestOIDCAuthorisation(URL, OIDCAccountSettingsPresenter.Continuation) + case requestOAuthAuthorisation(URL, OAuthAccountSettingsPresenter.Continuation) case linkedDevice /// Cancel the flow (dismiss the modal). case cancel @@ -26,7 +26,7 @@ enum QRCodeLoginScreenViewModelAction: CustomStringConvertible { case .startOver: "startOver" case .signInManually: "signInManually" case .signedIn: "signedIn" - case .requestOIDCAuthorisation: "requestOIDCAuthorisation" + case .requestOAuthAuthorisation: "requestOAuthAuthorisation" case .linkedDevice: "linkedDevice" case .cancel: "cancel" } diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift index 3e6dc3f81..cb7fac582 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift @@ -20,7 +20,7 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr } private var currentTask: AnyCancellable? - private var oidcResultTask: AnyCancellable? + private var oAuthResultTask: AnyCancellable? init(mode: QRCodeLoginScreenMode, canSignInManually: Bool, @@ -182,7 +182,7 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr case .establishingSecureChannel(let checkCodeString): state.state = .displayCode(.deviceCode(checkCodeString)) case .waitingForAuthorisation(let url): - requestOIDCAuthorization(url: url) + requestOAuthAuthorization(url: url) case .syncingSecrets: break // Nothing to do. case .done: @@ -222,7 +222,7 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr case .qrScanned(let checkCodeSender): state.state = .confirmCode(.inputCode(checkCodeSender)) case .waitingForAuthorisation(let url): - requestOIDCAuthorization(url: url) + requestOAuthAuthorization(url: url) case .syncingSecrets: break // Nothing to do. case .done: @@ -257,11 +257,11 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr } } - private func requestOIDCAuthorization(url: URL) { - let (stream, continuation) = AsyncStream>.makeStream() - actionsSubject.send(.requestOIDCAuthorisation(url, continuation)) + private func requestOAuthAuthorization(url: URL) { + let (stream, continuation) = AsyncStream>.makeStream() + actionsSubject.send(.requestOAuthAuthorisation(url, continuation)) - oidcResultTask = Task { [weak self] in + oAuthResultTask = Task { [weak self] in for await result in stream { guard let self else { return } switch result { diff --git a/ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift b/ElementX/Sources/Screens/Settings/AccountSettings/OAuthAccountSettingsPresenter.swift similarity index 85% rename from ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift rename to ElementX/Sources/Screens/Settings/AccountSettings/OAuthAccountSettingsPresenter.swift index 336f5951d..ae852231d 100644 --- a/ElementX/Sources/Screens/Settings/AccountSettings/OIDCAccountSettingsPresenter.swift +++ b/ElementX/Sources/Screens/Settings/AccountSettings/OAuthAccountSettingsPresenter.swift @@ -15,13 +15,13 @@ import AuthenticationServices /// have access to this session, and for some reason `prefersEphemeralWebBrowserSession` /// isn't sharing the session back to Safari. @MainActor -class OIDCAccountSettingsPresenter: NSObject { +class OAuthAccountSettingsPresenter: NSObject { private let accountURL: URL - private let oidcRedirectURL: URL + private let redirectURL: URL private let presentationAnchor: UIWindow private let appMediator: AppMediatorProtocol - typealias Continuation = AsyncStream>.Continuation + typealias Continuation = AsyncStream>.Continuation private let continuation: Continuation? init(accountURL: URL, @@ -30,7 +30,7 @@ class OIDCAccountSettingsPresenter: NSObject { appSettings: AppSettings, continuation: Continuation? = nil) { self.accountURL = accountURL - oidcRedirectURL = appSettings.oidcRedirectURL + redirectURL = appSettings.oAuthRedirectURL self.presentationAnchor = presentationAnchor self.appMediator = appMediator self.continuation = continuation @@ -40,10 +40,10 @@ class OIDCAccountSettingsPresenter: NSObject { /// Presents a web authentication session for the supplied data. func start() { - let session = ASWebAuthenticationSession(url: accountURL, callback: .oidcRedirectURL(oidcRedirectURL)) { [continuation] _, error in + let session = ASWebAuthenticationSession(url: accountURL, callback: .oAuthRedirectURL(redirectURL)) { [continuation] _, error in guard let continuation else { return } - if error?.isOIDCUserCancellation == true { + if error?.isOAuthUserCancellation == true { continuation.yield(.failure(.userCancellation)) } else { let errorDescription = error.map(String.init(describing:)) ?? "Unknown error" @@ -70,7 +70,7 @@ class OIDCAccountSettingsPresenter: NSObject { // MARK: ASWebAuthenticationPresentationContextProviding -extension OIDCAccountSettingsPresenter: ASWebAuthenticationPresentationContextProviding { +extension OAuthAccountSettingsPresenter: ASWebAuthenticationPresentationContextProviding { func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { presentationAnchor } diff --git a/ElementX/Sources/Services/Authentication/AuthenticationService.swift b/ElementX/Sources/Services/Authentication/AuthenticationService.swift index 76f4529ab..9be44dde3 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationService.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationService.swift @@ -73,7 +73,7 @@ class AuthenticationService: AuthenticationServiceProtocol { let loginDetails = await client.homeserverLoginDetails() homeserver.loginMode = if loginDetails.supportsOauthLogin() { - .oidc(supportsCreatePrompt: loginDetails.supportedOauthPrompts().contains(.create)) + .oAuth(supportsCreatePrompt: loginDetails.supportedOauthPrompts().contains(.create)) } else if loginDetails.supportsPasswordLogin() { .password } else { @@ -83,7 +83,7 @@ class AuthenticationService: AuthenticationServiceProtocol { if flow == .login, homeserver.loginMode == .unsupported { return .failure(.loginNotSupported) } - if flow == .register, !homeserver.loginMode.supportsOIDCFlow { + if flow == .register, !homeserver.loginMode.supportsOAuthFlow { return .failure(.registrationNotSupported) } @@ -105,39 +105,39 @@ class AuthenticationService: AuthenticationServiceProtocol { } } - func urlForOIDCLogin(loginHint: String?) async -> Result { - guard let client else { return .failure(.oidcError(.urlFailure)) } + func urlForOAuthLogin(loginHint: String?) async -> Result { + guard let client else { return .failure(.oAuthError(.urlFailure)) } do { // The create prompt is broken: https://github.com/element-hq/matrix-authentication-service/issues/3429 - // let prompt: OidcPrompt = flow == .register ? .create : .consent - let oidcData = try await client.urlForOauth(oauthConfiguration: appSettings.oidcConfiguration.rustValue, - prompt: .consent, - loginHint: loginHint, - deviceId: nil, - additionalScopes: nil) - return .success(OIDCAuthorizationDataProxy(underlyingData: oidcData)) + // let prompt: OAuthPrompt = flow == .register ? .create : .consent + let oAuthData = try await client.urlForOauth(oauthConfiguration: appSettings.oAuthConfiguration.rustValue, + prompt: .consent, + loginHint: loginHint, + deviceId: nil, + additionalScopes: nil) + return .success(OAuthAuthorizationDataProxy(underlyingData: oAuthData)) } catch { - MXLog.error("Failed to get URL for OIDC login: \(error)") - return .failure(.oidcError(.urlFailure)) + MXLog.error("Failed to get URL for OAuth login: \(error)") + return .failure(.oAuthError(.urlFailure)) } } - func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async { + func abortOAuthLogin(data: OAuthAuthorizationDataProxy) async { guard let client else { return } - MXLog.info("Aborting OIDC login.") + MXLog.info("Aborting OAuth login.") await client.abortOauthAuth(authorizationData: data.underlyingData) } - func loginWithOIDCCallback(_ callbackURL: URL) async -> Result { + func loginWithOAuthCallback(_ callbackURL: URL) async -> Result { guard let client else { return .failure(.failedLoggingIn) } do { try await client.loginWithOauthCallback(callbackUrl: callbackURL.absoluteString) await verifyClientIfPossible(client: client) return await userSession(for: client) - } catch OAuthError.Cancelled { - return .failure(.oidcError(.userCancellation)) + } catch MatrixRustSDK.OAuthError.Cancelled { + return .failure(.oAuthError(.userCancellation)) } catch { - MXLog.error("Login with OIDC failed: \(error)") + MXLog.error("Login with OAuth failed: \(error)") return .failure(.failedLoggingIn) } } @@ -149,7 +149,7 @@ class AuthenticationService: AuthenticationServiceProtocol { let refreshToken = try? client.session().refreshToken if refreshToken != nil { - MXLog.warning("Refresh token found for a non oidc session, can't restore session, logging out") + MXLog.warning("Refresh token found for a non OAuth session, can't restore session, logging out") _ = try? await client.logout() return .failure(.sessionTokenRefreshNotSupported) } @@ -206,7 +206,7 @@ class AuthenticationService: AuthenticationServiceProtocol { Task { do { let client = try await makeClient(homeserverAddress: scannedServerNameOrBaseUrl) - let qrCodeHandler = client.newLoginWithQrCodeHandler(oauthConfiguration: appSettings.oidcConfiguration.rustValue) + let qrCodeHandler = client.newLoginWithQrCodeHandler(oauthConfiguration: appSettings.oAuthConfiguration.rustValue) try await qrCodeHandler.scan(qrCodeData: qrData, progressListener: listener) // Since the QR code login flow includes verification. @@ -273,7 +273,7 @@ class AuthenticationService: AuthenticationServiceProtocol { // MARK: - Classic App /// Populates the Classic app account's state by checking whether the account's homeserver is supported - /// (has Sliding Sync and OIDC or password login) and whether all of the required secrets are available. + /// (has Sliding Sync and OAuth or password login) and whether all of the required secrets are available. func setupClassicAppAccountState() async { guard let classicAppAccount, classicAppAccount.state.isServerSupported == nil else { return } MXLog.info("Checking Classic app account: \(classicAppAccount)") diff --git a/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift b/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift index ce1e1ec3c..bb3bde9aa 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift @@ -19,8 +19,8 @@ enum AuthenticationFlow { } enum AuthenticationServiceError: Error, Equatable { - /// An error occurred during OIDC authentication. - case oidcError(OIDCError) + /// An error occurred during OAuth authentication. + case oAuthError(OAuthError) /// An error occurred during login with QR Code. case qrCodeError(QRCodeLoginError) @@ -46,12 +46,12 @@ protocol AuthenticationServiceProtocol: QRCodeLoginServiceProtocol { /// Sets up the service for login on the specified homeserver address. func configure(for homeserverAddress: String, flow: AuthenticationFlow) async -> Result - /// Performs login using OIDC for the current homeserver. - func urlForOIDCLogin(loginHint: String?) async -> Result - /// Asks the SDK to abort an ongoing OIDC login if we didn't get a callback to complete the request with. - func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async - /// Completes an OIDC login that was started using ``urlForOIDCLogin``. - func loginWithOIDCCallback(_ callbackURL: URL) async -> Result + /// Performs login using OAuth for the current homeserver. + func urlForOAuthLogin(loginHint: String?) async -> Result + /// Asks the SDK to abort an ongoing OAuth login if we didn't get a callback to complete the request with. + func abortOAuthLogin(data: OAuthAuthorizationDataProxy) async + /// Completes an OAuth login that was started using ``urlForOAuthLogin``. + func loginWithOAuthCallback(_ callbackURL: URL) async -> Result /// Performs a password login using the current homeserver. func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result @@ -70,25 +70,25 @@ protocol AuthenticationServiceProtocol: QRCodeLoginServiceProtocol { func refreshClassicAppAccountState() async } -// MARK: - OIDC +// MARK: - OAuth -enum OIDCError: Error { +enum OAuthError: Error { /// Failed to get the URL that should be presented for login. case urlFailure /// The user cancelled the login. case userCancellation - /// OIDC isn't supported on the currently configured server. + /// OAuth isn't supported on the currently configured server. case notSupported /// An unknown error occurred. case unknown } -struct OIDCAuthorizationDataProxy: Hashable { +struct OAuthAuthorizationDataProxy: Hashable { let underlyingData: OAuthAuthorizationData var url: URL { guard let url = URL(string: underlyingData.loginUrl()) else { - fatalError("OIDC login URL hasn't been validated.") + fatalError("OAuth login URL hasn't been validated.") } return url } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 11504f8c3..80edd14f0 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -405,7 +405,7 @@ class ClientProxy: ClientProxyProtocol { Task { await syncService.start() - // If we are using OIDC we want to cache the account management URL in volatile memory on the SDK side. + // If we are using OAuth we want to cache the account management URL in volatile memory on the SDK side. // To avoid the cache being invalidated while the app is backgrounded, we cache at every sync start. await cacheAccountURL() } diff --git a/ElementX/Sources/Services/UserSession/RestorationToken.swift b/ElementX/Sources/Services/UserSession/RestorationToken.swift index 7d4ef50c1..22acbbd00 100644 --- a/ElementX/Sources/Services/UserSession/RestorationToken.swift +++ b/ElementX/Sources/Services/UserSession/RestorationToken.swift @@ -77,7 +77,7 @@ extension MatrixRustSDK.Session: @retroactive Codable { userId: container.decode(String.self, forKey: .userId), deviceId: container.decode(String.self, forKey: .deviceId), homeserverUrl: container.decode(String.self, forKey: .homeserverUrl), - oauthData: container.decodeIfPresent(String.self, forKey: .oidcData), + oauthData: container.decodeIfPresent(String.self, forKey: .oauthData), slidingSyncVersion: .native) } @@ -88,10 +88,11 @@ extension MatrixRustSDK.Session: @retroactive Codable { try container.encode(userId, forKey: .userId) try container.encode(deviceId, forKey: .deviceId) try container.encode(homeserverUrl, forKey: .homeserverUrl) - try container.encode(oauthData, forKey: .oidcData) + try container.encode(oauthData, forKey: .oauthData) } enum CodingKeys: String, CodingKey { - case accessToken, refreshToken, userId, deviceId, homeserverUrl, oidcData, slidingSyncProxy + case accessToken, refreshToken, userId, deviceId, homeserverUrl, slidingSyncProxy + case oauthData = "oidcData" // We're using the name from before the MSC was stabilised. } } diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 2cac38e38..5ad352036 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -134,7 +134,7 @@ class MockScreen: Identifiable { allowOtherAccountProviders: false, hideBrandChrome: false, pushGatewayBaseURL: appSettings.pushGatewayBaseURL, - oidcRedirectURL: appSettings.oidcRedirectURL, + oAuthRedirectURL: appSettings.oAuthRedirectURL, websiteURL: appSettings.websiteURL, logoURL: appSettings.logoURL, copyrightURL: appSettings.copyrightURL, @@ -773,7 +773,7 @@ class MockScreen: Identifiable { switch action { case .dismiss: navigationRootCoordinator.setSheetCoordinator(nil) - case .requestOIDCAuthorisation: + case .requestOAuthAuthorisation: break } } diff --git a/Enterprise b/Enterprise index 4ce8b9a0e..0ea087616 160000 --- a/Enterprise +++ b/Enterprise @@ -1 +1 @@ -Subproject commit 4ce8b9a0e28ac38ca2b8cf7fe73255a6afdbdc14 +Subproject commit 0ea087616b59bf4f2d2271b3ddf3e056966653ce diff --git a/UITests/Sources/AuthenticationFlowCoordinatorTests.swift b/UITests/Sources/AuthenticationFlowCoordinatorTests.swift index 7fdd1f41c..501d8d1e3 100644 --- a/UITests/Sources/AuthenticationFlowCoordinatorTests.swift +++ b/UITests/Sources/AuthenticationFlowCoordinatorTests.swift @@ -23,7 +23,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase { // Server Confirmation: Tap change server button app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap() - // Server Selection: Clear the default, enter OIDC server and continue. + // Server Selection: Clear the default, enter OAuth server and continue. app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("example.com\n", app: app) // Await for the button to be hittable, since a loader may appear @@ -56,7 +56,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase { // Server Confirmation: Tap change server button app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap() - // Server Selection: Clear the default, enter OIDC server and continue. + // Server Selection: Clear the default, enter OAuth server and continue. app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("example.com\n", app: app) // Await for the button to be hittable, since a loader may appear @@ -91,7 +91,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase { // Server Confirmation: Tap change server button app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap() - // Server Selection: Clear the default, enter OIDC server and continue. + // Server Selection: Clear the default, enter OAuth server and continue. app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("example.com\n", app: app) // Await for the button to be hittable, since a loader may appear @@ -111,9 +111,9 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase { try await app.assertScreenshot() } - /// Disabled for now as the looping isn't 100% fool-proof and we have OIDC on the integration tests + /// Disabled for now as the looping isn't 100% fool-proof and we have OAuth on the integration tests /// so this mock version doesn't really add anything to the tests as a whole. - func disabled_testSelectingOIDCServer() { + func disabled_testSelectingOAuthServer() { // Allow this test to run for longer to help with the loop whilst waiting to resolve the // webcredentials for the Web Authentication Session (see below). executionTimeAllowance = 300 @@ -127,7 +127,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase { // Server Confirmation: Tap change server button app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap() - // Server Selection: Clear the default, enter OIDC server and continue. + // Server Selection: Clear the default, enter OAuth server and continue. app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("company.com\n", app: app) let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") @@ -155,7 +155,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase { } } - XCTAssertTrue(wasAlertText.exists, "The web authentication prompt should be shown after selecting a homeserver with OIDC.") + XCTAssertTrue(wasAlertText.exists, "The web authentication prompt should be shown after selecting a homeserver with OAuth.") } func testProvisionedLoginWithPassword() async throws { diff --git a/UnitTests/Sources/AppRouteURLParserTests.swift b/UnitTests/Sources/AppRouteURLParserTests.swift index 7cebea9f3..e1912810e 100644 --- a/UnitTests/Sources/AppRouteURLParserTests.swift +++ b/UnitTests/Sources/AppRouteURLParserTests.swift @@ -21,22 +21,22 @@ struct AppRouteURLParserTests { } @Test - func oidcCallbackRoute() { - // Given an OIDC callback for this app. - let callbackURL = appSettings.oidcRedirectURL.appending(queryItems: [URLQueryItem(name: "state", value: "12345"), - URLQueryItem(name: "code", value: "67890")]) + func oAuthCallbackRoute() { + // Given an OAuth callback for this app. + let callbackURL = appSettings.oAuthRedirectURL.appending(queryItems: [URLQueryItem(name: "state", value: "12345"), + URLQueryItem(name: "code", value: "67890")]) // When parsing that route. let route = appRouteURLParser.route(from: callbackURL) - // Then it should be considered a valid OIDC callback. - #expect(route == .oidcCallback(url: callbackURL)) + // Then it should be considered a valid OAuth callback. + #expect(route == .oAuthCallback(url: callbackURL)) } @Test - func oidcCallbackAppVariantRoute() { - // Given an OIDC callback for a different app variant. - let callbackURL = appSettings.oidcRedirectURL + func oAuthCallbackAppVariantRoute() { + // Given an OAuth callback for a different app variant. + let callbackURL = appSettings.oAuthRedirectURL .deletingLastPathComponent() .appending(component: "io.element.elementz") .appending(queryItems: [URLQueryItem(name: "state", value: "12345"), diff --git a/UnitTests/Sources/AuthenticationServiceTests.swift b/UnitTests/Sources/AuthenticationServiceTests.swift index f9a02ce2d..38a6f6a36 100644 --- a/UnitTests/Sources/AuthenticationServiceTests.swift +++ b/UnitTests/Sources/AuthenticationServiceTests.swift @@ -45,7 +45,7 @@ struct AuthenticationServiceTests { } @Test - mutating func configureLoginWithOIDC() async throws { + mutating func configureLoginWithOAuth() async throws { try await setup() try await service.configure(for: "matrix.org", flow: .login).get() @@ -55,7 +55,7 @@ struct AuthenticationServiceTests { } @Test - mutating func configureRegisterWithOIDC() async throws { + mutating func configureRegisterWithOAuth() async throws { try await setup() try await service.configure(for: "matrix.org", flow: .register).get() diff --git a/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift b/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift index 607b09a44..11c6c8767 100644 --- a/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift +++ b/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift @@ -64,15 +64,15 @@ final class AuthenticationStartScreenViewModelTests { } @Test - func provisionedOIDCState() async throws { - // Given a view model that has been provisioned with a server that supports OIDC. + func provisionedOAuthState() async throws { + // Given a view model that has been provisioned with a server that supports OAuth. await setupViewModel(provisioningParameters: .init(accountProvider: "company.com", loginHint: "user@company.com")) #expect(authenticationService.homeserver.value.loginMode == .unknown) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When tapping the login button the authentication service should be used and the screen // should request to continue the flow without any server selection needed. - let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOAuth } context.send(viewAction: .login) try await deferred.fulfill() @@ -80,13 +80,13 @@ final class AuthenticationStartScreenViewModelTests { #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.prompt == .consent) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.loginHint == "user@company.com") - #expect(authenticationService.homeserver.value.loginMode == .oidc(supportsCreatePrompt: false)) + #expect(authenticationService.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: false)) } @Test func provisionedPasswordState() async throws { - // Given a view model that has been provisioned with a server that does not support OIDC. - await setupViewModel(provisioningParameters: .init(accountProvider: "company.com", loginHint: "user@company.com"), supportsOIDC: false) + // Given a view model that has been provisioned with a server that does not support OAuth. + await setupViewModel(provisioningParameters: .init(accountProvider: "company.com", loginHint: "user@company.com"), supportsOAuth: false) #expect(authenticationService.homeserver.value.loginMode == .unknown) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) @@ -102,8 +102,8 @@ final class AuthenticationStartScreenViewModelTests { } @Test - func singleProviderOIDCState() async throws { - // Given a view model that for an app that only allows the use of a single provider that supports OIDC. + func singleProviderOAuthState() async throws { + // Given a view model that for an app that only allows the use of a single provider that supports OAuth. setAllowedAccountProviders(["company.com"]) await setupViewModel() #expect(authenticationService.homeserver.value.loginMode == .unknown) @@ -111,7 +111,7 @@ final class AuthenticationStartScreenViewModelTests { // When tapping the login button the authentication service should be used and the screen // should request to continue the flow without any server selection needed. - let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOAuth } context.send(viewAction: .login) try await deferred.fulfill() @@ -119,14 +119,14 @@ final class AuthenticationStartScreenViewModelTests { #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.prompt == .consent) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.loginHint == nil) - #expect(authenticationService.homeserver.value.loginMode == .oidc(supportsCreatePrompt: false)) + #expect(authenticationService.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: false)) } @Test func singleProviderPasswordState() async throws { - // Given a view model that for an app that only allows the use of a single provider that does not support OIDC. + // Given a view model that for an app that only allows the use of a single provider that does not support OAuth. setAllowedAccountProviders(["company.com"]) - await setupViewModel(supportsOIDC: false) + await setupViewModel(supportsOAuth: false) #expect(authenticationService.homeserver.value.loginMode == .unknown) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) @@ -156,13 +156,13 @@ final class AuthenticationStartScreenViewModelTests { // When continuing with the Classic app account the authentication service should be used and the screen // should request to continue the flow without any server selection needed. - let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOAuth } context.send(viewAction: .continueWithClassic(classicAppAccount)) try await deferred.fulfill() #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedArguments?.homeserverAddress == "company.com") - #expect(authenticationService.homeserver.value.loginMode == .oidc(supportsCreatePrompt: false)) + #expect(authenticationService.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: false)) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.loginHint == "mxid:\(classicAppAccount.userID)") } @@ -180,21 +180,21 @@ final class AuthenticationStartScreenViewModelTests { // When continuing with the Classic app account the authentication service should be used with the direct homeserver URL // and the screen should request to continue the flow without any server selection needed. - let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOAuth } context.send(viewAction: .continueWithClassic(classicAppAccount)) try await deferred.fulfill() #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 2) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedArguments?.homeserverAddress == "https://matrix.company.com") - #expect(authenticationService.homeserver.value.loginMode == .oidc(supportsCreatePrompt: false)) + #expect(authenticationService.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: false)) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.loginHint == "mxid:\(classicAppAccount.userID)") } @Test func classicAppAccountOnUnsupportedServer() async { - // Given a view model with a Classic app account whose server supports neither OIDC nor password login. + // Given a view model with a Classic app account whose server supports neither OAuth nor password login. let classicAppAccount = makeClassicAppAccount() - await setupViewModel(classicAppAccount: classicAppAccount, supportsOIDC: false, supportsPasswordLogin: false) + await setupViewModel(classicAppAccount: classicAppAccount, supportsOAuth: false, supportsPasswordLogin: false) guard case .welcomeBack(let account) = context.viewState.classicAppMode else { Issue.record("Expected classicAppMode to be .welcomeBack") return @@ -271,7 +271,7 @@ final class AuthenticationStartScreenViewModelTests { try await deferred.fulfill() // When the user continues with the Classic account again. - let deferredAction = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOIDC } + let deferredAction = deferFulfillment(viewModel.actions) { $0.isLoginDirectlyWithOAuth } context.send(viewAction: .continueWithClassic(classicAppAccount)) // Then the flow should continue the login process. @@ -282,12 +282,12 @@ final class AuthenticationStartScreenViewModelTests { private func setupViewModel(classicAppAccount: ClassicAppAccount? = nil, provisioningParameters: AccountProvisioningParameters? = nil, - supportsOIDC: Bool = true, + supportsOAuth: Bool = true, supportsPasswordLogin: Bool = true, availableSecrets: ClassicAppAccount.AvailableSecrets = .complete) async { // Manually create a configuration as the default homeserver address setting is immutable. - client = ClientSDKMock(configuration: .init(oidcLoginURL: supportsOIDC ? "https://account.company.com/authorize" : nil, - supportsOIDCCreatePrompt: false, + client = ClientSDKMock(configuration: .init(oAuthLoginURL: supportsOAuth ? "https://account.company.com/authorize" : nil, + supportsOAuthCreatePrompt: false, supportsPasswordLogin: supportsPasswordLogin)) // Map both the server name and the homeserver URL so fallback lookups work. let homeserverClients: [String: ClientSDKMock] = ["company.com": client, @@ -321,7 +321,7 @@ final class AuthenticationStartScreenViewModelTests { notificationCenter: notificationCenter, userIndicatorController: UserIndicatorControllerMock()) - // Add a fake window in order for the OIDC flow to continue + // Add a fake window in order for the OAuth flow to continue viewModel.context.send(viewAction: .updateWindow(UIWindow())) } @@ -342,7 +342,7 @@ final class AuthenticationStartScreenViewModelTests { allowOtherAccountProviders: false, hideBrandChrome: false, pushGatewayBaseURL: appSettings.pushGatewayBaseURL, - oidcRedirectURL: appSettings.oidcRedirectURL, + oAuthRedirectURL: appSettings.oAuthRedirectURL, websiteURL: appSettings.websiteURL, logoURL: appSettings.logoURL, copyrightURL: appSettings.copyrightURL, @@ -362,9 +362,9 @@ final class AuthenticationStartScreenViewModelTests { } extension AuthenticationStartScreenViewModelAction { - var isLoginDirectlyWithOIDC: Bool { + var isLoginDirectlyWithOAuth: Bool { switch self { - case .loginDirectlyWithOIDC: true + case .loginDirectlyWithOAuth: true default: false } } diff --git a/UnitTests/Sources/LoginScreenViewModelTests.swift b/UnitTests/Sources/LoginScreenViewModelTests.swift index 3a70a6161..0d8b3d8d1 100644 --- a/UnitTests/Sources/LoginScreenViewModelTests.swift +++ b/UnitTests/Sources/LoginScreenViewModelTests.swift @@ -155,21 +155,21 @@ struct LoginScreenViewModelTests { } @Test - mutating func oidcServer() async throws { + mutating func oAuthServer() async throws { // Given the screen configured for matrix.org await setupViewModel() - // When entering a username for a user on a homeserver with OIDC. + // When entering a username for a user on a homeserver with OAuth. let deferred = deferFulfillment(viewModel.actions) { - $0.isConfiguredForOIDC + $0.isConfiguredForOAuth } context.username = "@bob:company.com" context.send(viewAction: .parseUsername) try await deferred.fulfill() - // Then the view state should be updated with the homeserver and show the OIDC button. - #expect(context.viewState.loginMode.supportsOIDCFlow, - "The OIDC button should be shown.") + // Then the view state should be updated with the homeserver and show the OAuth button. + #expect(context.viewState.loginMode.supportsOAuthFlow, + "The OAuth button should be shown.") } @Test diff --git a/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift b/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift index 122a979b7..1db37eb07 100644 --- a/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift +++ b/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift @@ -147,7 +147,7 @@ struct QRCodeLoginScreenViewModelTests { try await deferred.fulfill() var deferredAction = deferFulfillment(viewModel.actionsPublisher) { action in - guard case .requestOIDCAuthorisation = action else { return false } + guard case .requestOAuthAuthorisation = action else { return false } return true } linkDesktopProgressSubject.send(.waitingForAuthorisation(verificationURL: .homeDirectory)) @@ -183,7 +183,7 @@ struct QRCodeLoginScreenViewModelTests { try await deferredState.fulfill() var deferredAction = deferFulfillment(viewModel.actionsPublisher) { action in - guard case .requestOIDCAuthorisation = action else { return false } + guard case .requestOAuthAuthorisation = action else { return false } return true } linkMobileProgressSubject.send(.waitingForAuthorisation(verificationURL: .homeDirectory)) diff --git a/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift b/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift index 5448c9501..9da2ef13e 100644 --- a/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift +++ b/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift @@ -21,7 +21,7 @@ struct ServerConfirmationScreenViewStateTests { authenticationFlow: .login) #expect(elementDotIoLogin.message == L10n.screenServerConfirmationMessageLoginElementDotIo, "element.io should have a custom message.") - let otherLogin = ServerConfirmationScreenViewState(mode: .confirmation(LoginHomeserver.mockOIDC.address), + let otherLogin = ServerConfirmationScreenViewState(mode: .confirmation(LoginHomeserver.mockOAuth.address), authenticationFlow: .login) #expect(otherLogin.message == "", "Other servers should not show a message.") @@ -36,8 +36,8 @@ struct ServerConfirmationScreenViewStateTests { authenticationFlow: .register) #expect(matrixDotOrgRegister.message == L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") - let oidcRegister = ServerConfirmationScreenViewState(mode: .confirmation(LoginHomeserver.mockOIDC.address), - authenticationFlow: .register) - #expect(oidcRegister.message == L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") + let oAuthRegister = ServerConfirmationScreenViewState(mode: .confirmation(LoginHomeserver.mockOAuth.address), + authenticationFlow: .register) + #expect(oAuthRegister.message == L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") } } diff --git a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift index 8a54b2caa..f91e1c380 100644 --- a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift +++ b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift @@ -46,7 +46,7 @@ final class ServerConfirmationScreenViewModelTests { #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When continuing from the confirmation screen. - let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOAuth } context.send(viewAction: .confirm) try await deferred.fulfill() @@ -54,7 +54,7 @@ final class ServerConfirmationScreenViewModelTests { #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.prompt == .consent) - #expect(service.homeserver.value.loginMode == .oidc(supportsCreatePrompt: true)) + #expect(service.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: true)) } @Test @@ -65,13 +65,13 @@ final class ServerConfirmationScreenViewModelTests { Issue.record("The configuration should succeed.") return } - #expect(service.homeserver.value.loginMode == .oidc(supportsCreatePrompt: true)) + #expect(service.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: true)) #expect(context.viewState.mode == .confirmation(service.homeserver.value.address)) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When continuing from the confirmation screen. - let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOAuth } context.send(viewAction: .confirm) try await deferred.fulfill() @@ -91,7 +91,7 @@ final class ServerConfirmationScreenViewModelTests { #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When continuing from the confirmation screen. - let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOAuth } context.send(viewAction: .confirm) try await deferred.fulfill() @@ -100,7 +100,7 @@ final class ServerConfirmationScreenViewModelTests { #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 1) // The create prompt is broken: https://github.com/element-hq/matrix-authentication-service/issues/3429 // #expect(client.urlForOauthOauthConfigurationPromptReceivedArguments?.prompt == .create) - #expect(service.homeserver.value.loginMode == .oidc(supportsCreatePrompt: true)) + #expect(service.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: true)) } @Test @@ -111,13 +111,13 @@ final class ServerConfirmationScreenViewModelTests { Issue.record("The configuration should succeed.") return } - #expect(service.homeserver.value.loginMode == .oidc(supportsCreatePrompt: true)) + #expect(service.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: true)) #expect(context.viewState.mode == .confirmation(service.homeserver.value.address)) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When continuing from the confirmation screen. - let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOAuth } context.send(viewAction: .confirm) try await deferred.fulfill() @@ -130,8 +130,8 @@ final class ServerConfirmationScreenViewModelTests { @Test func confirmPasswordLoginWithoutConfiguration() async throws { - // Given a view model for login using a service that hasn't been configured (against a server that doesn't support OIDC). - setupViewModel(authenticationFlow: .login, supportsOIDC: false) + // Given a view model for login using a service that hasn't been configured (against a server that doesn't support OAuth). + setupViewModel(authenticationFlow: .login, supportsOAuth: false) #expect(service.homeserver.value.loginMode == .unknown) #expect(context.viewState.mode == .confirmation(service.homeserver.value.address)) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 0) @@ -142,7 +142,7 @@ final class ServerConfirmationScreenViewModelTests { context.send(viewAction: .confirm) try await deferred.fulfill() - // Then a call to configure service should be made, but not for the OIDC URL. + // Then a call to configure service should be made, but not for the OAuth URL. #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) #expect(service.homeserver.value.loginMode == .password) @@ -151,7 +151,7 @@ final class ServerConfirmationScreenViewModelTests { @Test func confirmPasswordLoginAfterConfiguration() async throws { // Given a view model for login using a service that has already been configured (via the server selection screen). - setupViewModel(authenticationFlow: .login, supportsOIDC: false) + setupViewModel(authenticationFlow: .login, supportsOAuth: false) guard case .success = await service.configure(for: viewModel.state.homeserverAddress, flow: .login) else { Issue.record("The configuration should succeed.") return @@ -166,7 +166,7 @@ final class ServerConfirmationScreenViewModelTests { context.send(viewAction: .confirm) try await deferred.fulfill() - // Then the configured homeserver should be used and no additional client should be built, nor a call to get the OIDC URL. + // Then the configured homeserver should be used and no additional client should be built, nor a call to get the OAuth URL. #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) } @@ -175,7 +175,7 @@ final class ServerConfirmationScreenViewModelTests { func registrationNotSupportedAlert() async throws { // Given a view model for registration using a service that hasn't been configured and the default server doesn't support registration. // Note: We don't currently take the create prompt into account when determining registration support. - setupViewModel(authenticationFlow: .register, supportsOIDC: false, supportsOIDCCreatePrompt: false) + setupViewModel(authenticationFlow: .register, supportsOAuth: false, supportsOAuthCreatePrompt: false) #expect(service.homeserver.value.loginMode == .unknown) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 0) #expect(context.alertInfo == nil) @@ -193,7 +193,7 @@ final class ServerConfirmationScreenViewModelTests { @Test func loginNotSupportedAlert() async throws { // Given a view model for login using a service that hasn't been configured and the default server doesn't support login. - setupViewModel(authenticationFlow: .login, supportsOIDC: false, supportsOIDCCreatePrompt: false, supportsPasswordLogin: false) + setupViewModel(authenticationFlow: .login, supportsOAuth: false, supportsOAuthCreatePrompt: false, supportsPasswordLogin: false) #expect(service.homeserver.value.loginMode == .unknown) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 0) #expect(context.alertInfo == nil) @@ -211,7 +211,7 @@ final class ServerConfirmationScreenViewModelTests { @Test func elementProRequired() async throws { // Given a view model for login using a service that hasn't been configured and the default server requires Element Pro. - setupViewModel(authenticationFlow: .login, supportsOIDC: false, supportsOIDCCreatePrompt: false, supportsPasswordLogin: false, requiresElementPro: true) + setupViewModel(authenticationFlow: .login, supportsOAuth: false, supportsOAuthCreatePrompt: false, supportsPasswordLogin: false, requiresElementPro: true) #expect(service.homeserver.value.loginMode == .unknown) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 0) #expect(context.alertInfo == nil) @@ -238,7 +238,7 @@ final class ServerConfirmationScreenViewModelTests { #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When continuing from the confirmation screen. - let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOAuth } context.send(viewAction: .confirm) try await deferred.fulfill() @@ -246,7 +246,7 @@ final class ServerConfirmationScreenViewModelTests { #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesReceivedArguments?.prompt == .consent) - #expect(service.homeserver.value.loginMode == .oidc(supportsCreatePrompt: true)) + #expect(service.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: true)) } @Test @@ -257,13 +257,13 @@ final class ServerConfirmationScreenViewModelTests { Issue.record("The configuration should succeed.") return } - #expect(service.homeserver.value.loginMode == .oidc(supportsCreatePrompt: true)) + #expect(service.homeserver.value.loginMode == .oAuth(supportsCreatePrompt: true)) #expect(context.viewState.mode == .picker(appSettings.accountProviders)) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) // When continuing from the confirmation screen. - let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOIDC } + let deferred = deferFulfillment(viewModel.actions) { $0.isContinueWithOAuth } context.send(viewAction: .confirm) try await deferred.fulfill() @@ -275,8 +275,8 @@ final class ServerConfirmationScreenViewModelTests { @Test func pickerForPasswordLoginWithoutConfiguration() async throws { - // Given a view model for login using a service that hasn't been configured (against a server that doesn't support OIDC). - setupViewModel(authenticationFlow: .login, supportsOIDC: false, restrictedFlow: true) + // Given a view model for login using a service that hasn't been configured (against a server that doesn't support OAuth). + setupViewModel(authenticationFlow: .login, supportsOAuth: false, restrictedFlow: true) #expect(service.homeserver.value.loginMode == .unknown) #expect(context.viewState.mode == .picker(appSettings.accountProviders)) #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 0) @@ -287,7 +287,7 @@ final class ServerConfirmationScreenViewModelTests { context.send(viewAction: .confirm) try await deferred.fulfill() - // Then a call to configure service should be made, but not for the OIDC URL. + // Then a call to configure service should be made, but not for the OAuth URL. #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) #expect(service.homeserver.value.loginMode == .password) @@ -296,7 +296,7 @@ final class ServerConfirmationScreenViewModelTests { @Test func pickerForPasswordLoginAfterConfiguration() async throws { // Given a view model for login using a service that has already been configured (via the server selection screen). - setupViewModel(authenticationFlow: .login, supportsOIDC: false, restrictedFlow: true) + setupViewModel(authenticationFlow: .login, supportsOAuth: false, restrictedFlow: true) guard case .success = await service.configure(for: appSettings.accountProviders[0], flow: .login) else { Issue.record("The configuration should succeed.") return @@ -311,7 +311,7 @@ final class ServerConfirmationScreenViewModelTests { context.send(viewAction: .confirm) try await deferred.fulfill() - // Then the configured homeserver should be used and no additional client should be built, nor a call to get the OIDC URL. + // Then the configured homeserver should be used and no additional client should be built, nor a call to get the OAuth URL. #expect(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount == 1) #expect(client.urlForOauthOauthConfigurationPromptLoginHintDeviceIdAdditionalScopesCallsCount == 0) } @@ -319,8 +319,8 @@ final class ServerConfirmationScreenViewModelTests { // MARK: - Helpers private func setupViewModel(authenticationFlow: AuthenticationFlow, - supportsOIDC: Bool = true, - supportsOIDCCreatePrompt: Bool = true, + supportsOAuth: Bool = true, + supportsOAuthCreatePrompt: Bool = true, supportsPasswordLogin: Bool = true, restrictedFlow: Bool = false, requiresElementPro: Bool = false) { @@ -330,7 +330,7 @@ final class ServerConfirmationScreenViewModelTests { allowOtherAccountProviders: false, hideBrandChrome: false, pushGatewayBaseURL: appSettings.pushGatewayBaseURL, - oidcRedirectURL: appSettings.oidcRedirectURL, + oAuthRedirectURL: appSettings.oAuthRedirectURL, websiteURL: appSettings.websiteURL, logoURL: appSettings.logoURL, copyrightURL: appSettings.copyrightURL, @@ -350,8 +350,8 @@ final class ServerConfirmationScreenViewModelTests { } // Manually create a configuration as the default homeserver address setting is immutable. - client = ClientSDKMock(configuration: .init(oidcLoginURL: supportsOIDC ? "https://account.matrix.org/authorize" : nil, - supportsOIDCCreatePrompt: supportsOIDCCreatePrompt, + client = ClientSDKMock(configuration: .init(oAuthLoginURL: supportsOAuth ? "https://account.matrix.org/authorize" : nil, + supportsOAuthCreatePrompt: supportsOAuthCreatePrompt, supportsPasswordLogin: supportsPasswordLogin, elementWellKnown: requiresElementPro ? "{\"version\":1,\"enforce_element_pro\":true}" : nil)) let configuration = AuthenticationClientFactoryMock.Configuration(homeserverClients: ["matrix.org": client]) @@ -370,7 +370,7 @@ final class ServerConfirmationScreenViewModelTests { appSettings: ServiceLocator.shared.settings, userIndicatorController: UserIndicatorControllerMock()) - // Add a fake window in order for the OIDC flow to continue + // Add a fake window in order for the OAuth flow to continue viewModel.context.send(viewAction: .updateWindow(UIWindow())) } } @@ -387,9 +387,9 @@ private extension ServerConfirmationScreenViewState { } private extension ServerConfirmationScreenViewModelAction { - var isContinueWithOIDC: Bool { + var isContinueWithOAuth: Bool { switch self { - case .continueWithOIDC: true + case .continueWithOAuth: true default: false } } diff --git a/UnitTests/Sources/SoftLogoutScreenViewModelTests.swift b/UnitTests/Sources/SoftLogoutScreenViewModelTests.swift index f870e1d25..634fbe869 100644 --- a/UnitTests/Sources/SoftLogoutScreenViewModelTests.swift +++ b/UnitTests/Sources/SoftLogoutScreenViewModelTests.swift @@ -45,7 +45,7 @@ struct SoftLogoutScreenViewModelTests { } @Test - func initialStateForOIDC() { + func initialStateForOAuth() { let viewModel = SoftLogoutScreenViewModel(credentials: credentials, homeserver: .mockMatrixDotOrg, keyBackupNeeded: false) @@ -54,7 +54,7 @@ struct SoftLogoutScreenViewModelTests { // Given a view model where the user hasn't yet sent the verification email. #expect(context.password.isEmpty, "The view model should start with an empty password.") #expect(!context.viewState.canSubmit, "The view model should start with an invalid password.") - #expect(context.viewState.loginMode.supportsOIDCFlow, "The view model should show OIDC button for the given homeserver.") + #expect(context.viewState.loginMode.supportsOAuthFlow, "The view model should show OAuth button for the given homeserver.") #expect(!context.viewState.showRecoverEncryptionKeysMessage, "The view model should not show recover encryption keys message.") }