Skip to content

Commit

Permalink
Merge branch 'release/1.11.3/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Sep 13, 2023
2 parents c166e5b + 12c90dd commit e955e70
Show file tree
Hide file tree
Showing 21 changed files with 245 additions and 55 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## Changes in 1.11.3 (2023-09-13)

🐛 Bugfixes

- Show OIDC account management UI using embedded browser instead of system browser. ([#7671](https://github.com/vector-im/element-ios/issues/7671))
- Hide Sign Out X/All Sessions buttons in the Device Manager when using OIDC. ([#7672](https://github.com/vector-im/element-ios/issues/7672))


## Changes in 1.11.2 (2023-09-12)

🙌 Improvements
Expand Down
4 changes: 2 additions & 2 deletions Config/AppVersion.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
//

// Version
MARKETING_VERSION = 1.11.2
CURRENT_PROJECT_VERSION = 1.11.2
MARKETING_VERSION = 1.11.3
CURRENT_PROJECT_VERSION = 1.11.3
48 changes: 48 additions & 0 deletions Riot/Modules/Authentication/SSO/SSOAccountService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Copyright 2020 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

@objcMembers
/// A service for the SSOAuthenticationPresenter that allows to open an OIDC account management URL.
///
/// Both `callBackURLScheme` and `loginToken` are unneeded for this use case and return `nil`.
final class SSOAccountService: NSObject, SSOAuthenticationServiceProtocol {

// MARK: - Properties

private let accountURL: URL

let callBackURLScheme: String? = nil

// MARK: - Setup

init(accountURL: URL) {
self.accountURL = accountURL
super.init()
}

// MARK: - Public

func authenticationURL(for identityProvider: String?, transactionId: String) -> URL? {
accountURL
}

func loginToken(from url: URL) -> String? {
MXLog.error("The account service shouldn't receive a completion callback.")
return nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ final class SSOAuthenticationPresenter: NSObject {

// MARK: - Properties

private let ssoAuthenticationService: SSOAuthenticationService
private let ssoAuthenticationService: SSOAuthenticationServiceProtocol

// MARK: Private

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

// MARK: - Setup

init(ssoAuthenticationService: SSOAuthenticationService) {
init(ssoAuthenticationService: SSOAuthenticationServiceProtocol) {
self.ssoAuthenticationService = ssoAuthenticationService
super.init()
}
Expand Down
10 changes: 9 additions & 1 deletion Riot/Modules/Authentication/SSO/SSOAuthenticationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,16 @@ enum SSOAuthenticationServiceError: Error {
case unknown
}

@objc protocol SSOAuthenticationServiceProtocol {
var callBackURLScheme: String? { get }

func authenticationURL(for identityProvider: String?, transactionId: String) -> URL?

func loginToken(from url: URL) -> String?
}

@objcMembers
final class SSOAuthenticationService: NSObject {
final class SSOAuthenticationService: NSObject, SSOAuthenticationServiceProtocol {

// MARK: - Constants

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
};


@interface ManageSessionViewController () <UserVerificationCoordinatorBridgePresenterDelegate>
@interface ManageSessionViewController () <UserVerificationCoordinatorBridgePresenterDelegate, SSOAuthenticationPresenterDelegate>
{
// The device to display
MXDevice *device;
Expand All @@ -64,6 +64,8 @@ @interface ManageSessionViewController () <UserVerificationCoordinatorBridgePres

@property (nonatomic, strong) ReauthenticationCoordinatorBridgePresenter *reauthenticationCoordinatorBridgePresenter;

@property (nonatomic, strong) SSOAuthenticationPresenter *ssoAuthenticationPresenter;

@end

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

__weak typeof(self) weakSelf = self;
MXWeakify(self);
UIAlertAction *action = [UIAlertAction actionWithTitle:[VectorL10n ok]
style:UIAlertActionStyleDefault
handler: ^(UIAlertAction * action) {
[UIApplication.sharedApplication openURL:url options:@{} completionHandler:^(BOOL success) {
if (success && weakSelf)
{
[weakSelf withdrawViewControllerAnimated:YES completion:nil];
}
}];
MXStrongifyAndReturnIfNil(self);
SSOAccountService *service = [[SSOAccountService alloc] initWithAccountURL:url];
SSOAuthenticationPresenter *presenter = [[SSOAuthenticationPresenter alloc] initWithSsoAuthenticationService:service];
presenter.delegate = self;
self.ssoAuthenticationPresenter = presenter;

[presenter presentForIdentityProvider:nil with:@"" from:self animated:YES];
}];

[alert addAction: action];
[self presentViewController:alert animated:YES completion:nil];
}
Expand Down Expand Up @@ -755,4 +759,27 @@ - (void)userVerificationCoordinatorBridgePresenterDelegateDidComplete:(UserVerif
[self reloadDeviceWithCompletion:^{}];
}

#pragma mark - SSOAuthenticationPresenterDelegate

- (void)ssoAuthenticationPresenterDidCancel:(SSOAuthenticationPresenter *)presenter
{
self.ssoAuthenticationPresenter = nil;
MXLogDebug(@"OIDC account management complete.")
[self withdrawViewControllerAnimated:YES completion:nil];
}

- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter authenticationDidFailWithError:(NSError *)error
{
self.ssoAuthenticationPresenter = nil;
MXLogError(@"OIDC account management failed.")
}

- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter
authenticationSucceededWithToken:(NSString *)token
usingIdentityProvider:(SSOIdentityProvider *)identityProvider
{
self.ssoAuthenticationPresenter = nil;
MXLogWarning(@"Unexpected callback after OIDC account management.")
}

@end
34 changes: 32 additions & 2 deletions Riot/Modules/Settings/SettingsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ @interface SettingsViewController () <UITextFieldDelegate, MXKCountryPickerViewC
ServiceTermsModalCoordinatorBridgePresenterDelegate,
TableViewSectionsDelegate,
ThreadsBetaCoordinatorBridgePresenterDelegate,
ChangePasswordCoordinatorBridgePresenterDelegate>
ChangePasswordCoordinatorBridgePresenterDelegate,
SSOAuthenticationPresenterDelegate>
{
// Current alert (if any).
__weak UIAlertController *currentAlert;
Expand Down Expand Up @@ -300,6 +301,8 @@ @interface SettingsViewController () <UITextFieldDelegate, MXKCountryPickerViewC
@property (nonatomic) BOOL isPreparingIdentityService;
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;

@property (nonatomic, strong) SSOAuthenticationPresenter *ssoAuthenticationPresenter;

@property (nonatomic) AnalyticsScreenTracker *screenTracker;

@end
Expand Down Expand Up @@ -3926,7 +3929,12 @@ - (void)onManageAccountTap
{
NSURL *url = [NSURL URLWithString: self.mainSession.homeserverWellknown.authentication.account];
if (url) {
[UIApplication.sharedApplication openURL:url options:@{} completionHandler:nil];
SSOAccountService *service = [[SSOAccountService alloc] initWithAccountURL:url];
SSOAuthenticationPresenter *presenter = [[SSOAuthenticationPresenter alloc] initWithSsoAuthenticationService:service];
presenter.delegate = self;
self.ssoAuthenticationPresenter = presenter;

[presenter presentForIdentityProvider:nil with:@"" from:self animated:YES];
}
}

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

#pragma mark - SSOAuthenticationPresenterDelegate

- (void)ssoAuthenticationPresenterDidCancel:(SSOAuthenticationPresenter *)presenter
{
self.ssoAuthenticationPresenter = nil;
MXLogDebug(@"OIDC account management complete.")
}

- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter authenticationDidFailWithError:(NSError *)error
{
self.ssoAuthenticationPresenter = nil;
MXLogError(@"OIDC account management failed.")
}

- (void)ssoAuthenticationPresenter:(SSOAuthenticationPresenter *)presenter
authenticationSucceededWithToken:(NSString *)token
usingIdentityProvider:(SSOIdentityProvider *)identityProvider
{
self.ssoAuthenticationPresenter = nil;
MXLogWarning(@"Unexpected callback after OIDC account management.")
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ final class UserSessionsFlowCoordinator: NSObject, Coordinator, Presentable {
private var errorPresenter: MXKErrorPresentation
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
private var loadingIndicator: UserIndicator?
private var ssoAuthenticationPresenter: SSOAuthenticationPresenter?

/// The root coordinator for user session management.
private weak var sessionsOverviewCoordinator: UserSessionsOverviewCoordinator?
Expand Down Expand Up @@ -188,21 +189,25 @@ final class UserSessionsFlowCoordinator: NSObject, Coordinator, Presentable {
private func createOtherSessionsCoordinator(sessionInfos: [UserSessionInfo],
filterBy filter: UserOtherSessionsFilter,
title: String) -> UserOtherSessionsCoordinator {
let shouldShowDeviceLogout = parameters.session.homeserverWellknown.authentication == nil
let parameters = UserOtherSessionsCoordinatorParameters(sessionInfos: sessionInfos,
filter: filter,
title: title)
title: title,
showDeviceLogout: shouldShowDeviceLogout)
return UserOtherSessionsCoordinator(parameters: parameters)
}

private func openDeviceLogoutRedirectURL(_ url: URL) {
let alert = UIAlertController(title: VectorL10n.manageSessionRedirect, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default) { [weak self] _ in
UIApplication.shared.open(url) { [weak self] success in
guard success else {
return
}
self?.popToSessionsOverview()
}
guard let self else { return }

let service = SSOAccountService(accountURL: url)
let presenter = SSOAuthenticationPresenter(ssoAuthenticationService: service)
presenter.delegate = self
self.ssoAuthenticationPresenter = presenter

presenter.present(forIdentityProvider: nil, with: "", from: self.toPresentable(), animated: true)
})
alert.popoverPresentationController?.sourceView = toPresentable().view
navigationRouter.present(alert, animated: true)
Expand Down Expand Up @@ -547,3 +552,25 @@ private extension UserOtherSessionsFilter {
}
}
}

// MARK: ASWebAuthenticationPresentationContextProviding

extension UserSessionsFlowCoordinator: SSOAuthenticationPresenterDelegate {
func ssoAuthenticationPresenterDidCancel(_ presenter: SSOAuthenticationPresenter) {
ssoAuthenticationPresenter = nil
MXLog.info("OIDC account management complete.")
popToSessionsOverview()
}

func ssoAuthenticationPresenter(_ presenter: SSOAuthenticationPresenter, authenticationDidFailWithError error: Error) {
ssoAuthenticationPresenter = nil
MXLog.error("OIDC account management failed.")
}

func ssoAuthenticationPresenter(_ presenter: SSOAuthenticationPresenter,
authenticationSucceededWithToken token: String,
usingIdentityProvider identityProvider: SSOIdentityProvider?) {
ssoAuthenticationPresenter = nil
MXLog.warning("Unexpected callback after OIDC account management.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct UserOtherSessionsCoordinatorParameters {
let sessionInfos: [UserSessionInfo]
let filter: UserOtherSessionsFilter
let title: String
let showDeviceLogout: Bool
}

final class UserOtherSessionsCoordinator: Coordinator, Presentable {
Expand All @@ -40,6 +41,7 @@ final class UserOtherSessionsCoordinator: Coordinator, Presentable {
let viewModel = UserOtherSessionsViewModel(sessionInfos: parameters.sessionInfos,
filter: parameters.filter,
title: parameters.title,
showDeviceLogout: parameters.showDeviceLogout,
settingsService: RiotSettings.shared)
let view = UserOtherSessions(viewModel: viewModel.context)
userOtherSessionsViewModel = viewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,31 @@ enum MockUserOtherSessionsScreenState: MockScreenState, CaseIterable {
viewModel = UserOtherSessionsViewModel(sessionInfos: allSessions(),
filter: .all,
title: VectorL10n.userSessionsOverviewOtherSessionsSectionTitle,
showDeviceLogout: true,
settingsService: MockUserSessionSettings())
case .none:
viewModel = UserOtherSessionsViewModel(sessionInfos: [],
filter: .all,
title: VectorL10n.userSessionsOverviewOtherSessionsSectionTitle,
showDeviceLogout: true,
settingsService: MockUserSessionSettings())
case .inactiveSessions:
viewModel = UserOtherSessionsViewModel(sessionInfos: inactiveSessions(),
filter: .inactive,
title: VectorL10n.userOtherSessionSecurityRecommendationTitle,
showDeviceLogout: true,
settingsService: MockUserSessionSettings())
case .unverifiedSessions:
viewModel = UserOtherSessionsViewModel(sessionInfos: unverifiedSessions(),
filter: .unverified,
title: VectorL10n.userOtherSessionSecurityRecommendationTitle,
showDeviceLogout: true,
settingsService: MockUserSessionSettings())
case .verifiedSessions:
viewModel = UserOtherSessionsViewModel(sessionInfos: verifiedSessions(),
filter: .verified,
title: VectorL10n.userOtherSessionSecurityRecommendationTitle,
showDeviceLogout: true,
settingsService: MockUserSessionSettings())
}

Expand Down
Loading

0 comments on commit e955e70

Please sign in to comment.