Skip to content

Commit e955e70

Browse files
committed
Merge branch 'release/1.11.3/master'
2 parents c166e5b + 12c90dd commit e955e70

21 files changed

+245
-55
lines changed

CHANGES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## Changes in 1.11.3 (2023-09-13)
2+
3+
🐛 Bugfixes
4+
5+
- Show OIDC account management UI using embedded browser instead of system browser. ([#7671](https://github.com/vector-im/element-ios/issues/7671))
6+
- Hide Sign Out X/All Sessions buttons in the Device Manager when using OIDC. ([#7672](https://github.com/vector-im/element-ios/issues/7672))
7+
8+
19
## Changes in 1.11.2 (2023-09-12)
210

311
🙌 Improvements

Config/AppVersion.xcconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
//
1616

1717
// Version
18-
MARKETING_VERSION = 1.11.2
19-
CURRENT_PROJECT_VERSION = 1.11.2
18+
MARKETING_VERSION = 1.11.3
19+
CURRENT_PROJECT_VERSION = 1.11.3
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Copyright 2020 New Vector Ltd
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
import Foundation
18+
19+
@objcMembers
20+
/// A service for the SSOAuthenticationPresenter that allows to open an OIDC account management URL.
21+
///
22+
/// Both `callBackURLScheme` and `loginToken` are unneeded for this use case and return `nil`.
23+
final class SSOAccountService: NSObject, SSOAuthenticationServiceProtocol {
24+
25+
// MARK: - Properties
26+
27+
private let accountURL: URL
28+
29+
let callBackURLScheme: String? = nil
30+
31+
// MARK: - Setup
32+
33+
init(accountURL: URL) {
34+
self.accountURL = accountURL
35+
super.init()
36+
}
37+
38+
// MARK: - Public
39+
40+
func authenticationURL(for identityProvider: String?, transactionId: String) -> URL? {
41+
accountURL
42+
}
43+
44+
func loginToken(from url: URL) -> String? {
45+
MXLog.error("The account service shouldn't receive a completion callback.")
46+
return nil
47+
}
48+
}

Riot/Modules/Authentication/SSO/SSOAuthenticationPresenter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ final class SSOAuthenticationPresenter: NSObject {
3737

3838
// MARK: - Properties
3939

40-
private let ssoAuthenticationService: SSOAuthenticationService
40+
private let ssoAuthenticationService: SSOAuthenticationServiceProtocol
4141

4242
// MARK: Private
4343

@@ -53,7 +53,7 @@ final class SSOAuthenticationPresenter: NSObject {
5353

5454
// MARK: - Setup
5555

56-
init(ssoAuthenticationService: SSOAuthenticationService) {
56+
init(ssoAuthenticationService: SSOAuthenticationServiceProtocol) {
5757
self.ssoAuthenticationService = ssoAuthenticationService
5858
super.init()
5959
}

Riot/Modules/Authentication/SSO/SSOAuthenticationService.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,16 @@ enum SSOAuthenticationServiceError: Error {
2222
case unknown
2323
}
2424

25+
@objc protocol SSOAuthenticationServiceProtocol {
26+
var callBackURLScheme: String? { get }
27+
28+
func authenticationURL(for identityProvider: String?, transactionId: String) -> URL?
29+
30+
func loginToken(from url: URL) -> String?
31+
}
32+
2533
@objcMembers
26-
final class SSOAuthenticationService: NSObject {
34+
final class SSOAuthenticationService: NSObject, SSOAuthenticationServiceProtocol {
2735

2836
// MARK: - Constants
2937

Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
};
4646

4747

48-
@interface ManageSessionViewController () <UserVerificationCoordinatorBridgePresenterDelegate>
48+
@interface ManageSessionViewController () <UserVerificationCoordinatorBridgePresenterDelegate, SSOAuthenticationPresenterDelegate>
4949
{
5050
// The device to display
5151
MXDevice *device;
@@ -64,6 +64,8 @@ @interface ManageSessionViewController () <UserVerificationCoordinatorBridgePres
6464

6565
@property (nonatomic, strong) ReauthenticationCoordinatorBridgePresenter *reauthenticationCoordinatorBridgePresenter;
6666

67+
@property (nonatomic, strong) SSOAuthenticationPresenter *ssoAuthenticationPresenter;
68+
6769
@end
6870

6971
@implementation ManageSessionViewController
@@ -679,17 +681,19 @@ -(void) removeDeviceRedirectWithURL: (NSURL * _Nonnull) url
679681
{
680682
UIAlertController *alert = [UIAlertController alertControllerWithTitle: [VectorL10n manageSessionRedirect] message: nil preferredStyle:UIAlertControllerStyleAlert];
681683

682-
__weak typeof(self) weakSelf = self;
684+
MXWeakify(self);
683685
UIAlertAction *action = [UIAlertAction actionWithTitle:[VectorL10n ok]
684686
style:UIAlertActionStyleDefault
685687
handler: ^(UIAlertAction * action) {
686-
[UIApplication.sharedApplication openURL:url options:@{} completionHandler:^(BOOL success) {
687-
if (success && weakSelf)
688-
{
689-
[weakSelf withdrawViewControllerAnimated:YES completion:nil];
690-
}
691-
}];
688+
MXStrongifyAndReturnIfNil(self);
689+
SSOAccountService *service = [[SSOAccountService alloc] initWithAccountURL:url];
690+
SSOAuthenticationPresenter *presenter = [[SSOAuthenticationPresenter alloc] initWithSsoAuthenticationService:service];
691+
presenter.delegate = self;
692+
self.ssoAuthenticationPresenter = presenter;
693+
694+
[presenter presentForIdentityProvider:nil with:@"" from:self animated:YES];
692695
}];
696+
693697
[alert addAction: action];
694698
[self presentViewController:alert animated:YES completion:nil];
695699
}
@@ -755,4 +759,27 @@ - (void)userVerificationCoordinatorBridgePresenterDelegateDidComplete:(UserVerif
755759
[self reloadDeviceWithCompletion:^{}];
756760
}
757761

762+
#pragma mark - SSOAuthenticationPresenterDelegate
763+
764+
- (void)ssoAuthenticationPresenterDidCancel:(SSOAuthenticationPresenter *)presenter
765+
{
766+
self.ssoAuthenticationPresenter = nil;
767+
MXLogDebug(@"OIDC account management complete.")
768+
[self withdrawViewControllerAnimated:YES completion:nil];
769+
}
770+
771+
- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter authenticationDidFailWithError:(NSError *)error
772+
{
773+
self.ssoAuthenticationPresenter = nil;
774+
MXLogError(@"OIDC account management failed.")
775+
}
776+
777+
- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter
778+
authenticationSucceededWithToken:(NSString *)token
779+
usingIdentityProvider:(SSOIdentityProvider *)identityProvider
780+
{
781+
self.ssoAuthenticationPresenter = nil;
782+
MXLogWarning(@"Unexpected callback after OIDC account management.")
783+
}
784+
758785
@end

Riot/Modules/Settings/SettingsViewController.m

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ @interface SettingsViewController () <UITextFieldDelegate, MXKCountryPickerViewC
204204
ServiceTermsModalCoordinatorBridgePresenterDelegate,
205205
TableViewSectionsDelegate,
206206
ThreadsBetaCoordinatorBridgePresenterDelegate,
207-
ChangePasswordCoordinatorBridgePresenterDelegate>
207+
ChangePasswordCoordinatorBridgePresenterDelegate,
208+
SSOAuthenticationPresenterDelegate>
208209
{
209210
// Current alert (if any).
210211
__weak UIAlertController *currentAlert;
@@ -300,6 +301,8 @@ @interface SettingsViewController () <UITextFieldDelegate, MXKCountryPickerViewC
300301
@property (nonatomic) BOOL isPreparingIdentityService;
301302
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;
302303

304+
@property (nonatomic, strong) SSOAuthenticationPresenter *ssoAuthenticationPresenter;
305+
303306
@property (nonatomic) AnalyticsScreenTracker *screenTracker;
304307

305308
@end
@@ -3926,7 +3929,12 @@ - (void)onManageAccountTap
39263929
{
39273930
NSURL *url = [NSURL URLWithString: self.mainSession.homeserverWellknown.authentication.account];
39283931
if (url) {
3929-
[UIApplication.sharedApplication openURL:url options:@{} completionHandler:nil];
3932+
SSOAccountService *service = [[SSOAccountService alloc] initWithAccountURL:url];
3933+
SSOAuthenticationPresenter *presenter = [[SSOAuthenticationPresenter alloc] initWithSsoAuthenticationService:service];
3934+
presenter.delegate = self;
3935+
self.ssoAuthenticationPresenter = presenter;
3936+
3937+
[presenter presentForIdentityProvider:nil with:@"" from:self animated:YES];
39303938
}
39313939
}
39323940

@@ -4602,4 +4610,26 @@ - (void)showUserSessionsFlow
46024610
[self.userSessionsFlowCoordinatorBridgePresenter pushFrom:self.navigationController animated:YES];
46034611
}
46044612

4613+
#pragma mark - SSOAuthenticationPresenterDelegate
4614+
4615+
- (void)ssoAuthenticationPresenterDidCancel:(SSOAuthenticationPresenter *)presenter
4616+
{
4617+
self.ssoAuthenticationPresenter = nil;
4618+
MXLogDebug(@"OIDC account management complete.")
4619+
}
4620+
4621+
- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter authenticationDidFailWithError:(NSError *)error
4622+
{
4623+
self.ssoAuthenticationPresenter = nil;
4624+
MXLogError(@"OIDC account management failed.")
4625+
}
4626+
4627+
- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter
4628+
authenticationSucceededWithToken:(NSString *)token
4629+
usingIdentityProvider:(SSOIdentityProvider *)identityProvider
4630+
{
4631+
self.ssoAuthenticationPresenter = nil;
4632+
MXLogWarning(@"Unexpected callback after OIDC account management.")
4633+
}
4634+
46054635
@end

RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ final class UserSessionsFlowCoordinator: NSObject, Coordinator, Presentable {
3232
private var errorPresenter: MXKErrorPresentation
3333
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
3434
private var loadingIndicator: UserIndicator?
35+
private var ssoAuthenticationPresenter: SSOAuthenticationPresenter?
3536

3637
/// The root coordinator for user session management.
3738
private weak var sessionsOverviewCoordinator: UserSessionsOverviewCoordinator?
@@ -188,21 +189,25 @@ final class UserSessionsFlowCoordinator: NSObject, Coordinator, Presentable {
188189
private func createOtherSessionsCoordinator(sessionInfos: [UserSessionInfo],
189190
filterBy filter: UserOtherSessionsFilter,
190191
title: String) -> UserOtherSessionsCoordinator {
192+
let shouldShowDeviceLogout = parameters.session.homeserverWellknown.authentication == nil
191193
let parameters = UserOtherSessionsCoordinatorParameters(sessionInfos: sessionInfos,
192194
filter: filter,
193-
title: title)
195+
title: title,
196+
showDeviceLogout: shouldShowDeviceLogout)
194197
return UserOtherSessionsCoordinator(parameters: parameters)
195198
}
196199

197200
private func openDeviceLogoutRedirectURL(_ url: URL) {
198201
let alert = UIAlertController(title: VectorL10n.manageSessionRedirect, message: nil, preferredStyle: .alert)
199202
alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default) { [weak self] _ in
200-
UIApplication.shared.open(url) { [weak self] success in
201-
guard success else {
202-
return
203-
}
204-
self?.popToSessionsOverview()
205-
}
203+
guard let self else { return }
204+
205+
let service = SSOAccountService(accountURL: url)
206+
let presenter = SSOAuthenticationPresenter(ssoAuthenticationService: service)
207+
presenter.delegate = self
208+
self.ssoAuthenticationPresenter = presenter
209+
210+
presenter.present(forIdentityProvider: nil, with: "", from: self.toPresentable(), animated: true)
206211
})
207212
alert.popoverPresentationController?.sourceView = toPresentable().view
208213
navigationRouter.present(alert, animated: true)
@@ -547,3 +552,25 @@ private extension UserOtherSessionsFilter {
547552
}
548553
}
549554
}
555+
556+
// MARK: ASWebAuthenticationPresentationContextProviding
557+
558+
extension UserSessionsFlowCoordinator: SSOAuthenticationPresenterDelegate {
559+
func ssoAuthenticationPresenterDidCancel(_ presenter: SSOAuthenticationPresenter) {
560+
ssoAuthenticationPresenter = nil
561+
MXLog.info("OIDC account management complete.")
562+
popToSessionsOverview()
563+
}
564+
565+
func ssoAuthenticationPresenter(_ presenter: SSOAuthenticationPresenter, authenticationDidFailWithError error: Error) {
566+
ssoAuthenticationPresenter = nil
567+
MXLog.error("OIDC account management failed.")
568+
}
569+
570+
func ssoAuthenticationPresenter(_ presenter: SSOAuthenticationPresenter,
571+
authenticationSucceededWithToken token: String,
572+
usingIdentityProvider identityProvider: SSOIdentityProvider?) {
573+
ssoAuthenticationPresenter = nil
574+
MXLog.warning("Unexpected callback after OIDC account management.")
575+
}
576+
}

RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Coordinator/UserOtherSessionsCoordinator.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct UserOtherSessionsCoordinatorParameters {
2121
let sessionInfos: [UserSessionInfo]
2222
let filter: UserOtherSessionsFilter
2323
let title: String
24+
let showDeviceLogout: Bool
2425
}
2526

2627
final class UserOtherSessionsCoordinator: Coordinator, Presentable {
@@ -40,6 +41,7 @@ final class UserOtherSessionsCoordinator: Coordinator, Presentable {
4041
let viewModel = UserOtherSessionsViewModel(sessionInfos: parameters.sessionInfos,
4142
filter: parameters.filter,
4243
title: parameters.title,
44+
showDeviceLogout: parameters.showDeviceLogout,
4345
settingsService: RiotSettings.shared)
4446
let view = UserOtherSessions(viewModel: viewModel.context)
4547
userOtherSessionsViewModel = viewModel

RiotSwiftUI/Modules/UserSessions/UserOtherSessions/MockUserOtherSessionsScreenState.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,31 @@ enum MockUserOtherSessionsScreenState: MockScreenState, CaseIterable {
4949
viewModel = UserOtherSessionsViewModel(sessionInfos: allSessions(),
5050
filter: .all,
5151
title: VectorL10n.userSessionsOverviewOtherSessionsSectionTitle,
52+
showDeviceLogout: true,
5253
settingsService: MockUserSessionSettings())
5354
case .none:
5455
viewModel = UserOtherSessionsViewModel(sessionInfos: [],
5556
filter: .all,
5657
title: VectorL10n.userSessionsOverviewOtherSessionsSectionTitle,
58+
showDeviceLogout: true,
5759
settingsService: MockUserSessionSettings())
5860
case .inactiveSessions:
5961
viewModel = UserOtherSessionsViewModel(sessionInfos: inactiveSessions(),
6062
filter: .inactive,
6163
title: VectorL10n.userOtherSessionSecurityRecommendationTitle,
64+
showDeviceLogout: true,
6265
settingsService: MockUserSessionSettings())
6366
case .unverifiedSessions:
6467
viewModel = UserOtherSessionsViewModel(sessionInfos: unverifiedSessions(),
6568
filter: .unverified,
6669
title: VectorL10n.userOtherSessionSecurityRecommendationTitle,
70+
showDeviceLogout: true,
6771
settingsService: MockUserSessionSettings())
6872
case .verifiedSessions:
6973
viewModel = UserOtherSessionsViewModel(sessionInfos: verifiedSessions(),
7074
filter: .verified,
7175
title: VectorL10n.userOtherSessionSecurityRecommendationTitle,
76+
showDeviceLogout: true,
7277
settingsService: MockUserSessionSettings())
7378
}
7479

0 commit comments

Comments
 (0)