#42: Proof of concept login via OIDC.

Uses AppAuth library in the app, ignoring token refresh
This commit is contained in:
Doug 2022-07-28 09:28:42 +01:00 committed by GitHub
parent f8c30a7341
commit c20bc6bd1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 323 additions and 57 deletions

View File

@ -25,7 +25,7 @@
072BA9DBA932374CCA300125 /* MessageComposerTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6C10032A77AE7DC5AA4C50 /* MessageComposerTextField.swift */; };
0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */; };
0C38C3E771B472E27295339D /* SessionVerificationModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4BB9A17AC512A7EF4B106E5 /* SessionVerificationModels.swift */; };
0E8C480700870BB34A2A360F /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
0E8C480700870BB34A2A360F /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
0ED951768EC443A8728DE1D7 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; };
0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; };
@ -63,8 +63,8 @@
28410F3DE89C2C44E4F75C92 /* MockBugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E7BF8F7BB1021F889C6483 /* MockBugReportService.swift */; };
297CD0A27C87B0C50FF192EE /* RoomTimelineViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE384418EB1FEDFA62C9CD0 /* RoomTimelineViewFactoryProtocol.swift */; };
29AEE68A604940180AB9EBFF /* MockRoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6BDAC8895AB2B77B47703AE /* MockRoomSummary.swift */; };
29EE1791E0AFA1ABB7F23D2F /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
2BA59D0AEFB4B82A2EC2A326 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; };
29EE1791E0AFA1ABB7F23D2F /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
2BA59D0AEFB4B82A2EC2A326 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 04C28663564E008DB32B5972 /* Introspect */; };
2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; };
2C0CE61E5DC177938618E0B1 /* RootRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90733775209F4D4D366A268F /* RootRouterType.swift */; };
2E59008365E01F0AFB3A6B24 /* ImageRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF686BA36D0C2FA3C63DFDF /* ImageRoomMessage.swift */; };
@ -76,6 +76,7 @@
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
313382FC5D38064EAAA35CB2 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D1CC633517D695FEC54208 /* FileManager.swift */; };
33B4E59D408AE6E02323EE41 /* NoticeRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDA364DFFC3AC71C4771251 /* NoticeRoomMessage.swift */; };
33CAC1226DFB8B5D8447D286 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
344AF4CBB6D8786214878642 /* NavigationRouterStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9D5F812E5AD6DC786DBC9B /* NavigationRouterStoreProtocol.swift */; };
34966D4C1C2C6D37FE3F7F50 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2D50A7EAA4FC78417730E /* SettingsCoordinator.swift */; };
352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; };
@ -87,12 +88,12 @@
388FD50AC66E9E684DDFA9D8 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D2C0950F8196232D88045C /* ServerSelectionScreen.swift */; };
38C76D586404C1FDED095F3A /* LoginModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B01468022EC826CB2FD2C0 /* LoginModels.swift */; };
3B770CB4DED51CC362C66D47 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4990FDBDA96B88E214F92F48 /* SettingsModels.swift */; };
3C549A0BF39F8A854D45D9FD /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
3C549A0BF39F8A854D45D9FD /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
3D325A1147F6281C57BFCDF6 /* EventBrief.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4411C0DA0087A1CB143E96FA /* EventBrief.swift */; };
3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; };
3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; };
418B4AEFD03DC7A6D2C9D5C8 /* EventBriefFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36322DD0D4E29D31B0945ADC /* EventBriefFactory.swift */; };
41DFDD212D1BE57CA50D783B /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; };
41DFDD212D1BE57CA50D783B /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
438FB9BC535BC95948AA5F34 /* SettingsViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2F9D5C39A4494D19F33E38 /* SettingsViewModelProtocol.swift */; };
43FD77998F33C32718C51450 /* TemplateCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD460ED7ED1E03B85DEA25C /* TemplateCoordinator.swift */; };
462813B93C39DF93B1249403 /* RoundedToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFABDF2E19D349DAAAC18C65 /* RoundedToastView.swift */; };
@ -117,6 +118,7 @@
5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; };
53B9C2240C2F5533246EE230 /* RectangleToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6235E1CE00A6D989D7DB6D47 /* RectangleToastView.swift */; };
541374590CA7E8318BD480FD /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
563A05B43207D00A6B698211 /* OIDCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9010EE0CC913D095887EF36E /* OIDCService.swift */; };
56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; };
59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */; };
5B2C4C17888FC095ED6880B2 /* SplashViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48971F1FFD7FC5C466889FC7 /* SplashViewController.xib */; };
@ -127,13 +129,14 @@
5F1FDE49DFD0C680386E48F9 /* TemplateViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B80895CE021B49847BD7D74 /* TemplateViewModelProtocol.swift */; };
5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; };
617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; };
6298AB0906DDD3525CD78C6B /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; };
62BBF5BE7B905222F0477FF2 /* MediaSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8210612D17A39369480FC183 /* MediaSource.swift */; };
63C9AF0FB8278AF1C0388A0C /* TemplateModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB10E673916D2B8D21FD197 /* TemplateModels.swift */; };
64FF5CB4E35971255872E1BB /* AuthenticationServiceProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F0CB536D1C3CC15AA740CC6 /* AuthenticationServiceProxyProtocol.swift */; };
6647430A45B4A8E692909A8F /* EmoteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */; };
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; };
6832733838C57A7D3FE8FEB5 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 04C28663564E008DB32B5972 /* Introspect */; };
6832733838C57A7D3FE8FEB5 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
684BDE198AE5AA1392288A73 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CE6D4FF64C9A3C18619224 /* SplashScreen.swift */; };
68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */; };
69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; };
@ -142,7 +145,7 @@
6AC1DC1EAD9F7568360DA1BA /* ServerSelectionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30A1758E2B73EF38E7C42F8 /* ServerSelectionModels.swift */; };
6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */; };
6EA61FCA55D950BDE326A1A7 /* ImageAnonymizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */; };
6F2AB43A1EFAD8A97AF41A15 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
6F2AB43A1EFAD8A97AF41A15 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; };
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */; };
7002C55A4C917F3715765127 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */; };
706F79A39BDB32F592B8C2C7 /* UIKitBackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */; };
@ -187,7 +190,7 @@
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */; };
93BA4A81B6D893271101F9F0 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 5986E300FC849DEAB2EE7AEB /* Introspect */; };
93BA4A81B6D893271101F9F0 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
94A65DD8A353DF112EBEF67A /* SessionVerificationControllerProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D56469A9EE0CFA2B7BA9760 /* SessionVerificationControllerProxyProtocol.swift */; };
94D0F36A87E596A93C0C178A /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
94E062D08E27B0387658E364 /* SplashScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5CF94E124616FD89424B73 /* SplashScreenViewModelTests.swift */; };
@ -196,21 +199,21 @@
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
989029A28C9E2F828AD6658A /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
9AC5F8142413862A9E3A2D98 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = FD43A50D9B75C9D6D30F006B /* SwiftyBeaver */; };
99ED42B8F8D6BFB1DBCF4C45 /* AppAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 4346F63D53A346271577FD9C /* AppAuth */; };
9AC5F8142413862A9E3A2D98 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 5986E300FC849DEAB2EE7AEB /* Introspect */; };
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; };
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A20AE75FF4FF35B1FF6CA7 /* MockServerSelectionScreenState.swift */; };
9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; };
9C9E48A627C7C166084E3F5B /* LabelledActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56F01DD1BBD4450E18115916 /* LabelledActivityIndicatorView.swift */; };
9CB5129C83F75921E5E28028 /* ToastViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C82DAE0B8EB28234E84E6CF /* ToastViewState.swift */; };
9D2E03DB175A6AB14589076D /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; };
9D2E03DB175A6AB14589076D /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */; };
9DC5FB22B8F86C3B51E907C1 /* HomeScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6E4C37E9F0E53D3DF951AC /* HomeScreenUITests.swift */; };
9E8AE387FD03E4F1C1B8815A /* SessionVerificationStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = C06FCD42EEFEFC220F14EAC5 /* SessionVerificationStateMachine.swift */; };
A00DFC1DD3567B1EDC9F8D16 /* SplashScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 325A2B3278875554DDEB8A9B /* SplashScreenUITests.swift */; };
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; };
A32517FB1CA0BBCE2BC75249 /* BugReportCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6C07DA7D3FF193F7419F55 /* BugReportCoordinator.swift */; };
A4E885358D7DD5A072A06824 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
A4E885358D7DD5A072A06824 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
A50849766F056FD1DB942DEA /* AlertInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */; };
A5C8F013ED9FB8AA6FEE18A7 /* InfoPlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A901D95158B02CA96C79C7F /* InfoPlist.swift */; };
A5EC21A071F58FC1229C20D0 /* MemberDetailsProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09747989908EC5E4AA29F844 /* MemberDetailsProviderProtocol.swift */; };
@ -223,7 +226,7 @@
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; };
ACF094CF3BF02DBFA6DFDE60 /* AuthenticationCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */; };
B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97755C01C3971474EFAD5367 /* AuthenticationIconImage.swift */; };
B245583C63F8F90357B87FAE /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
B245583C63F8F90357B87FAE /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; };
B3357B00F1AA930E54F76609 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
B3FDB1D9CF40777695DBBD1D /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A9AB74614131D6706894E0C /* AppCoordinatorStateMachine.swift */; };
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
@ -247,9 +250,9 @@
C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; };
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
CA1E41AE5CDCB8D801DE0830 /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F87116470221880017CF522 /* BuildSettings.swift */; };
CB137BFB3E083C33E398A6CB /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
CB137BFB3E083C33E398A6CB /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = FD43A50D9B75C9D6D30F006B /* SwiftyBeaver */; };
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */; };
CB498F4E27AA0545DCEF0F6F /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
CB498F4E27AA0545DCEF0F6F /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
CC736DA1AA8F8B9FD8785009 /* ScreenshotDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */; };
CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; };
CE7A715947ABAB1DEB5C21D7 /* SplashScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F7A812F160E75B69A9181A2 /* SplashScreenCoordinator.swift */; };
@ -286,7 +289,7 @@
F4C3FEDB1B3A05376A1723A3 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A4427F9E0571B4E6E048A2B /* KeychainController.swift */; };
F508683B76EF7B23BB2CBD6D /* TimelineItemPlainStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */; };
F56261126E368C831B3DE976 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEC02D93AFF46BC13313A /* NavigationRouterType.swift */; };
F656F92A63D3DC1978D79427 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */; };
F656F92A63D3DC1978D79427 /* AppAuth in Frameworks */ = {isa = PBXBuildFile; productRef = AA4E1BEB4E9BC2467006E12B /* AppAuth */; };
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; };
F78C57B197DA74735FEBB42C /* EventBriefFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B61C243325DC76D3086494 /* EventBriefFactoryProtocol.swift */; };
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
@ -533,6 +536,7 @@
8C37FB986891D90BEAA93EAE /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = "<group>"; };
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; };
9010EE0CC913D095887EF36E /* OIDCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCService.swift; sourceTree = "<group>"; };
90733775209F4D4D366A268F /* RootRouterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouterType.swift; sourceTree = "<group>"; };
92B61C243325DC76D3086494 /* EventBriefFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBriefFactoryProtocol.swift; sourceTree = "<group>"; };
92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTask.swift; sourceTree = "<group>"; };
@ -707,14 +711,15 @@
buildActionMask = 2147483647;
files = (
2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */,
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */,
0E8C480700870BB34A2A360F /* KeychainAccess in Frameworks */,
CB498F4E27AA0545DCEF0F6F /* Kingfisher in Frameworks */,
6832733838C57A7D3FE8FEB5 /* Introspect in Frameworks */,
2BA59D0AEFB4B82A2EC2A326 /* SwiftyBeaver in Frameworks */,
B245583C63F8F90357B87FAE /* SwiftState in Frameworks */,
A4E885358D7DD5A072A06824 /* GZIP in Frameworks */,
29EE1791E0AFA1ABB7F23D2F /* Sentry in Frameworks */,
99ED42B8F8D6BFB1DBCF4C45 /* AppAuth in Frameworks */,
0E8C480700870BB34A2A360F /* DTCoreText in Frameworks */,
CB498F4E27AA0545DCEF0F6F /* KeychainAccess in Frameworks */,
6832733838C57A7D3FE8FEB5 /* Kingfisher in Frameworks */,
2BA59D0AEFB4B82A2EC2A326 /* Introspect in Frameworks */,
B245583C63F8F90357B87FAE /* SwiftyBeaver in Frameworks */,
A4E885358D7DD5A072A06824 /* SwiftState in Frameworks */,
29EE1791E0AFA1ABB7F23D2F /* GZIP in Frameworks */,
33CAC1226DFB8B5D8447D286 /* Sentry in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -724,14 +729,15 @@
files = (
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */,
1F3232BD368DF430AB433907 /* DesignKit in Frameworks */,
F656F92A63D3DC1978D79427 /* DTCoreText in Frameworks */,
9D2E03DB175A6AB14589076D /* KeychainAccess in Frameworks */,
6F2AB43A1EFAD8A97AF41A15 /* Kingfisher in Frameworks */,
93BA4A81B6D893271101F9F0 /* Introspect in Frameworks */,
9AC5F8142413862A9E3A2D98 /* SwiftyBeaver in Frameworks */,
CB137BFB3E083C33E398A6CB /* SwiftState in Frameworks */,
3C549A0BF39F8A854D45D9FD /* GZIP in Frameworks */,
41DFDD212D1BE57CA50D783B /* Sentry in Frameworks */,
F656F92A63D3DC1978D79427 /* AppAuth in Frameworks */,
9D2E03DB175A6AB14589076D /* DTCoreText in Frameworks */,
6F2AB43A1EFAD8A97AF41A15 /* KeychainAccess in Frameworks */,
93BA4A81B6D893271101F9F0 /* Kingfisher in Frameworks */,
9AC5F8142413862A9E3A2D98 /* Introspect in Frameworks */,
CB137BFB3E083C33E398A6CB /* SwiftyBeaver in Frameworks */,
3C549A0BF39F8A854D45D9FD /* SwiftState in Frameworks */,
41DFDD212D1BE57CA50D783B /* GZIP in Frameworks */,
6298AB0906DDD3525CD78C6B /* Sentry in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1377,6 +1383,7 @@
CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */,
4F0CB536D1C3CC15AA740CC6 /* AuthenticationServiceProxyProtocol.swift */,
65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */,
9010EE0CC913D095887EF36E /* OIDCService.swift */,
);
path = Authentication;
sourceTree = "<group>";
@ -1628,6 +1635,7 @@
name = UITests;
packageProductDependencies = (
B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */,
4346F63D53A346271577FD9C /* AppAuth */,
36B7FC232711031AA2B0D188 /* DTCoreText */,
78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */,
50009897F60FAE7D63EF5E5B /* Kingfisher */,
@ -1677,6 +1685,7 @@
packageProductDependencies = (
A678E40E917620059695F067 /* MatrixRustSDK */,
A5A56C4F47C368EBE5C5E870 /* DesignKit */,
AA4E1BEB4E9BC2467006E12B /* AppAuth */,
531CE4334AC5CA8DFF6AEB84 /* DTCoreText */,
020597E28A4BC8E1BE8EDF6E /* KeychainAccess */,
0DD568A494247444A4B56031 /* Kingfisher */,
@ -1788,6 +1797,7 @@
);
mainGroup = 405B00F139AEE3994601B36A;
packageReferences = (
4CE94127E27181B8B72188F0 /* XCRemoteSwiftPackageReference "AppAuth-iOS" */,
C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */,
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */,
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
@ -2047,6 +2057,7 @@
33B4E59D408AE6E02323EE41 /* NoticeRoomMessage.swift in Sources */,
8BBD3AA589DEE02A1B0923B2 /* NoticeRoomTimelineItem.swift in Sources */,
368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */,
563A05B43207D00A6B698211 /* OIDCService.swift in Sources */,
7D1DAAA364A9A29D554BD24E /* PlaceholderAvatarImage.swift in Sources */,
BF35062D06888FA80BD139FF /* Presentable.swift in Sources */,
C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */,
@ -2659,6 +2670,14 @@
minimumVersion = 1.9.5;
};
};
4CE94127E27181B8B72188F0 /* XCRemoteSwiftPackageReference "AppAuth-iOS" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/openid/AppAuth-iOS";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.5.0;
};
};
61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess";
@ -2756,6 +2775,11 @@
package = 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */;
productName = SwiftState;
};
4346F63D53A346271577FD9C /* AppAuth */ = {
isa = XCSwiftPackageProductDependency;
package = 4CE94127E27181B8B72188F0 /* XCRemoteSwiftPackageReference "AppAuth-iOS" */;
productName = AppAuth;
};
50009897F60FAE7D63EF5E5B /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;
package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */;
@ -2810,6 +2834,11 @@
package = 25B4484A6A20B9F1705DEEDA /* XCRemoteSwiftPackageReference "SwiftyBeaver" */;
productName = SwiftyBeaver;
};
AA4E1BEB4E9BC2467006E12B /* AppAuth */ = {
isa = XCSwiftPackageProductDependency;
package = 4CE94127E27181B8B72188F0 /* XCRemoteSwiftPackageReference "AppAuth-iOS" */;
productName = AppAuth;
};
B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */ = {
isa = XCSwiftPackageProductDependency;
package = 80B898A3AD2AC63F3ABFC218 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */;

View File

@ -1,5 +1,14 @@
{
"pins" : [
{
"identity" : "appauth-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/openid/AppAuth-iOS",
"state" : {
"revision" : "33660c271c961f8ce1084cc13f2ea8195e864f7d",
"version" : "1.5.0"
}
},
{
"identity" : "dtcoretext",
"kind" : "remoteSourceControl",

View File

@ -110,8 +110,6 @@ class AuthenticationCoordinator: Coordinator, Presentable {
switch action {
case .signedIn(let userSession):
self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
case .continueWithOIDC:
break
}
}

View File

@ -14,6 +14,7 @@
// limitations under the License.
//
import AppAuth
import MatrixRustSDK
import SwiftUI
@ -27,8 +28,6 @@ struct LoginCoordinatorParameters {
enum LoginCoordinatorAction {
/// Login was successful.
case signedIn(UserSessionProtocol)
/// Continue using OIDC.
case continueWithOIDC
}
final class LoginCoordinator: Coordinator, Presentable {
@ -39,6 +38,8 @@ final class LoginCoordinator: Coordinator, Presentable {
private let parameters: LoginCoordinatorParameters
private let loginHostingController: UIViewController
private var loginViewModel: LoginViewModelProtocol
/// Passed to the OIDC service to provide a view controller from which to present the authentication session.
private let oidcUserAgent: OIDExternalUserAgentIOS?
private var currentTask: Task<Void, Error>? {
willSet {
@ -69,6 +70,7 @@ final class LoginCoordinator: Coordinator, Presentable {
loginHostingController = UIHostingController(rootView: view)
indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: loginHostingController)
oidcUserAgent = OIDExternalUserAgentIOS(presenting: loginHostingController)
}
// MARK: - Public
@ -90,7 +92,7 @@ final class LoginCoordinator: Coordinator, Presentable {
case .login(let username, let password):
self.login(username: username, password: password)
case .continueWithOIDC:
self.callback?(.continueWithOIDC)
self.loginWithOIDC()
}
}
}
@ -138,6 +140,26 @@ final class LoginCoordinator: Coordinator, Presentable {
}
}
private func loginWithOIDC() {
guard let oidcUserAgent = oidcUserAgent else {
handleError(AuthenticationServiceError.oidcError(.notSupported))
return
}
startLoading(isInteractionBlocking: true)
Task {
switch await authenticationService.loginWithOIDC(userAgent: oidcUserAgent) {
case .success(let userSession):
callback?(.signedIn(userSession))
stopLoading()
case .failure(let error):
stopLoading()
handleError(error)
}
}
}
/// Requests the authentication coordinator to log in using the specified credentials.
private func login(username: String, password: String) {
startLoading(isInteractionBlocking: true)

View File

@ -53,7 +53,8 @@ final class HomeScreenCoordinator: Coordinator, Presentable {
init(parameters: HomeScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = HomeScreenViewModel(attributedStringBuilder: parameters.attributedStringBuilder)
viewModel = HomeScreenViewModel(initialDisplayName: parameters.userSession.userID,
attributedStringBuilder: parameters.attributedStringBuilder)
let view = HomeScreen(context: viewModel.context)
hostingController = UIHostingController(rootView: view)

View File

@ -31,7 +31,7 @@ enum HomeScreenViewAction {
}
struct HomeScreenViewState: BindableState {
var userDisplayName: String?
var userDisplayName: String
var userAvatar: UIImage?
var showSessionVerificationBanner = false

View File

@ -39,10 +39,11 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
// MARK: - Setup
init(attributedStringBuilder: AttributedStringBuilderProtocol) {
init(initialDisplayName: String, attributedStringBuilder: AttributedStringBuilderProtocol) {
self.attributedStringBuilder = attributedStringBuilder
super.init(initialViewState: HomeScreenViewState(isLoadingRooms: true))
super.init(initialViewState: HomeScreenViewState(userDisplayName: initialDisplayName,
isLoadingRooms: true))
}
// MARK: - Public

View File

@ -94,21 +94,14 @@ struct HomeScreen: View {
.frame(width: 32, height: 32, alignment: .center)
.clipShape(Circle())
.accessibilityIdentifier("userAvatarImage")
} else {
EmptyView()
}
}
@ViewBuilder
private var userDisplayNameView: some View {
if let displayName = context.viewState.userDisplayName {
Text(displayName)
Text(context.viewState.userDisplayName)
.font(.headline)
.fontWeight(.bold)
.foregroundColor(.primary)
} else {
EmptyView()
}
}
}
@ -173,11 +166,14 @@ struct RoomCell: View {
struct HomeScreen_Previews: PreviewProvider {
static var previews: some View {
body.preferredColorScheme(.light)
.tint(.element.accent)
body.preferredColorScheme(.dark)
.tint(.element.accent)
}
static var body: some View {
let viewModel = HomeScreenViewModel(attributedStringBuilder: AttributedStringBuilder())
let viewModel = HomeScreenViewModel(initialDisplayName: "@username:server.com",
attributedStringBuilder: AttributedStringBuilder())
let eventBrief = EventBrief(eventId: "id",
senderId: "senderId",

View File

@ -6,6 +6,7 @@
// Copyright © 2022 Element. All rights reserved.
//
import AppAuth
import Foundation
import MatrixRustSDK
@ -59,6 +60,42 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
}
}
func loginWithOIDC(userAgent: OIDExternalUserAgentIOS) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
guard case let .oidc(issuerURL) = homeserver.loginMode else {
return .failure(.oidcError(.notSupported))
}
let token: String
let deviceID = generateDeviceID()
do {
let oidcService = OIDCService(issuerURL: issuerURL)
let configuration = try await oidcService.metadata()
let registationResponse = try await oidcService.registerClient(metadata: configuration)
let authResponse = try await oidcService.presentWebAuthentication(metadata: configuration,
clientID: registationResponse.clientID,
scope: "urn:matrix:device:\(deviceID)",
userAgent: userAgent)
let tokenResponse = try await oidcService.redeemCodeForTokens(authResponse: authResponse)
guard let accessToken = tokenResponse.accessToken else { return .failure(.oidcError(.unknown)) }
token = accessToken
} catch let error as OIDCError {
MXLog.error("Login with OIDC failed: \(error)")
return .failure(.oidcError(error))
} catch {
MXLog.error("Login with OIDC failed: \(error)")
return .failure(.failedLoggingIn)
}
do {
let client = try authenticationService.restoreWithAccessToken(token: token, deviceId: deviceID)
return await userSession(for: client)
} catch {
MXLog.debug(error)
return .failure(.failedLoggingIn)
}
}
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
Benchmark.startTrackingForIdentifier("Login", message: "Started new login")
@ -97,4 +134,13 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
return .failure(.failedLoggingIn)
}
}
private func generateDeviceID() -> String {
var deviceID = ""
for _ in 0..<10 {
guard let scalar = UnicodeScalar(Int.random(in: 65...90)) else { fatalError() }
deviceID.append(Character(scalar))
}
return deviceID
}
}

View File

@ -6,9 +6,12 @@
// Copyright © 2022 Element. All rights reserved.
//
import AppAuth
import Foundation
enum AuthenticationServiceError: Error {
/// An error occurred during OIDC authentication.
case oidcError(OIDCError)
case invalidServer
case invalidCredentials
case invalidHomeserverAddress
@ -22,6 +25,8 @@ protocol AuthenticationServiceProxyProtocol {
/// Sets up the service for login on the specified homeserver address.
func configure(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError>
/// Performs login using OIDC for the current homeserver.
func loginWithOIDC(userAgent: OIDExternalUserAgentIOS) async -> Result<UserSessionProtocol, AuthenticationServiceError>
/// Performs a password login using the current homeserver.
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError>
}

View File

@ -6,11 +6,13 @@
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
import AppAuth
class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
let validCredentials = (username: "alice", password: "12345678")
private(set) var homeserver: LoginHomeserver = .mockMatrixDotOrg
var oidcUserAgent: OIDExternalUserAgentIOS?
func configure(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError> {
// Map the address to the mock homeservers
@ -32,6 +34,10 @@ class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
}
}
func loginWithOIDC(userAgent: OIDExternalUserAgentIOS) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
.failure(.oidcError(.notSupported))
}
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
// Login only succeeds if the username and password match the valid credentials property
guard username == validCredentials.username, password == validCredentials.password else {

View File

@ -0,0 +1,140 @@
//
// OIDCAuthenticationService.swift
// ElementX
//
// Created by Doug on 07/07/2022.
// Copyright © 2022 Element. All rights reserved.
//
import AppAuth
/// Errors thrown by the OIDC service.
enum OIDCError: Error {
case notSupported
case metadataMissingRegistrationEndpoint
case userCancellation
case missingTokenExchangeRequest
case unknown
}
/// A proof of concept implementation of a service that assists with authentication via OIDC.
/// It will be replaced by an implementation in the Rust SDK tracked in the following issue:
/// https://github.com/matrix-org/matrix-rust-sdk/issues/859
class OIDCService {
private let issuerURL: URL
private var authState: OIDAuthState
private var metadata: OIDServiceConfiguration?
/// Redirect URI for the request. Must match the `client_uri` in reverse DNS format.
private let redirectURI = URL(string: "io.element:/callback")!
// swiftlint:disable:previous force_unwrapping
/// Maintains a strong ref to the authorization session that's in progress.
private var session: OIDExternalUserAgentSession?
init(issuerURL: URL) {
self.issuerURL = issuerURL
authState = OIDAuthState(authorizationResponse: nil, tokenResponse: nil, registrationResponse: nil)
}
/// Get OpenID Connect endpoints and ensure that dynamic client registration is configured.
func metadata() async throws -> OIDServiceConfiguration {
let metadata = try await OIDAuthorizationService.discoverConfiguration(forIssuer: issuerURL)
guard metadata.registrationEndpoint != nil else {
throw OIDCError.metadataMissingRegistrationEndpoint
}
return metadata
}
/// Perform dynamic client registration and then store the response
func registerClient(metadata: OIDServiceConfiguration) async throws -> OIDRegistrationResponse {
let extraParams = [
"client_name": "ElementX iOS",
"client_uri": "https://element.io",
"tos_uri": "https://example.com/tos",
"policy_uri": "https://example.com/policy"
]
let nonTemplatizedRequest = OIDRegistrationRequest(
configuration: metadata,
redirectURIs: [redirectURI],
responseTypes: nil,
grantTypes: [OIDGrantTypeAuthorizationCode],
subjectType: nil,
tokenEndpointAuthMethod: "none",
additionalParameters: extraParams
)
let registrationResponse = try await OIDAuthorizationService.perform(nonTemplatizedRequest)
MXLog.info("Registration data retrieved successfully")
MXLog.debug("Created dynamic client: ID: \(registrationResponse.clientID)")
// This is a PoC, a complete implementation would persist the client ID and secret for reuse.
return registrationResponse
}
/// Trigger a redirect with standard parameters.
/// `acr_values` can be sent as an extra parameter, to control authentication methods.
func presentWebAuthentication(metadata: OIDServiceConfiguration,
clientID: String,
scope: String,
userAgent: OIDExternalUserAgent) async throws -> OIDAuthorizationResponse {
let scopesArray = scope.components(separatedBy: " ")
let request = OIDAuthorizationRequest(configuration: metadata,
clientId: clientID,
clientSecret: nil,
scopes: scopesArray,
redirectURL: redirectURI,
responseType: OIDResponseTypeCode,
additionalParameters: nil)
let result: OIDAuthorizationResponse = try await withCheckedThrowingContinuation { continuation in
self.session = OIDAuthorizationService.present(request, externalUserAgent: userAgent) { response, error in
guard let response = response else {
if let error = error {
MXLog.info("User cancelled the ASWebAuthenticationSession window")
continuation.resume(with: .failure(self.isUserCancellationError(error) ? OIDCError.userCancellation : error))
} else {
continuation.resume(with: .failure(OIDCError.unknown))
}
return
}
MXLog.info("Authorization response received successfully")
continuation.resume(with: .success(response))
}
}
return result
}
/// Handle the authorization response, including the user closing the Chrome Custom Tab
func redeemCodeForTokens(authResponse: OIDAuthorizationResponse) async throws -> OIDTokenResponse {
guard let request = authResponse.tokenExchangeRequest() else { throw OIDCError.missingTokenExchangeRequest }
return try await OIDAuthorizationService.perform(request, originalAuthorizationResponse: authResponse)
}
/// We can check for specific error codes to handle the user cancelling the ASWebAuthenticationSession window.
private func isUserCancellationError(_ error: Error) -> Bool {
let error = error as NSError
return error.domain == OIDGeneralErrorDomain && error.code == OIDErrorCode.userCanceledAuthorizationFlow.rawValue
}
}
extension OIDAuthorizationService {
/// An async version of `perform(_:originalAuthorizationResponse:callback:)`.
class func perform(_ request: OIDTokenRequest,
originalAuthorizationResponse authorizationResponse: OIDAuthorizationResponse?) async throws -> OIDTokenResponse {
try await withCheckedThrowingContinuation { continuation in
perform(request, originalAuthorizationResponse: authorizationResponse) { response, error in
guard let response = response else {
continuation.resume(with: .failure(error ?? OIDCError.unknown))
return
}
continuation.resume(with: .success(response))
}
}
}
}

View File

@ -12,6 +12,7 @@ struct MockUserSession: UserSessionProtocol {
let callbacks = PassthroughSubject<UserSessionCallback, Never>()
let sessionVerificationController: SessionVerificationControllerProxyProtocol? = nil
let userID = "@mock:usersession.com"
let clientProxy: ClientProxyProtocol
let mediaProvider: MediaProviderProtocol
}

View File

@ -13,6 +13,8 @@ class UserSession: UserSessionProtocol {
private var cancellables = Set<AnyCancellable>()
private var checkForSessionVerificationControllerCancellable: AnyCancellable?
var userID: String { clientProxy.userIdentifier }
let clientProxy: ClientProxyProtocol
let mediaProvider: MediaProviderProtocol
let callbacks = PassthroughSubject<UserSessionCallback, Never>()

View File

@ -15,6 +15,8 @@ enum UserSessionCallback {
}
protocol UserSessionProtocol {
var userID: String { get }
var clientProxy: ClientProxyProtocol { get }
var mediaProvider: MediaProviderProtocol { get }

View File

@ -101,6 +101,7 @@ targets:
dependencies:
- package: MatrixRustSDK
- package: DesignKit
- package: AppAuth
- package: DTCoreText
- package: KeychainAccess
- package: Kingfisher

View File

@ -9,6 +9,8 @@ targets:
- target: ElementX
- package: MatrixRustSDK
linkType: static
- package: AppAuth
linkType: static
- package: DTCoreText
linkType: static
- package: KeychainAccess

View File

@ -23,7 +23,8 @@ class HomeScreenViewModelTests: XCTestCase {
var context: HomeScreenViewModelType.Context!
@MainActor override func setUpWithError() throws {
viewModel = HomeScreenViewModel(attributedStringBuilder: AttributedStringBuilder())
viewModel = HomeScreenViewModel(initialDisplayName: "@test:example.com",
attributedStringBuilder: AttributedStringBuilder())
context = viewModel.context
}

1
changelog.d/42.wip Normal file
View File

@ -0,0 +1 @@
Add a proof of concept implementation for login with OIDC.

View File

@ -35,6 +35,9 @@ packages:
# path: ../matrix-rust-components-swift
DesignKit:
path: ./
AppAuth:
url: https://github.com/openid/AppAuth-iOS
majorVersion: 1.5.0
DTCoreText:
url: https://github.com/Cocoanetics/DTCoreText
majorVersion: 1.6.26