diff --git a/CHANGES.rst b/CHANGES.rst index ccd8e3509..62aa65911 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,10 @@ Improvements: * Privacy: Remove the bind true flag from 3PID calls on registration (#2648). * Privacy: Remove the bind true flag from 3PID adds in settings (#2650). * Privacy: Email help text on registration should be updated without binding (#2675). + * Privacy: Use MXIdentityService to perform identity server requests (#2647). + * Privacy: Support identity server v2 API authentication (#2603). + * Privacy: Use the hashed v2 lookup API for 3PIDs (#2652). + * Privacy: Prompt to accept identity server policies on firt use (#2602). Changes in 0.9.2 (2019-08-08) =============================================== diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index e6dab7807..c51441fd7 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -84,7 +84,7 @@ NSString *const kAppDelegateDidTapStatusBarNotification = @"kAppDelegateDidTapStatusBarNotification"; NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateNetworkStatusDidChangeNotification"; -@interface AppDelegate () +@interface AppDelegate () { /** Reachability observer @@ -233,6 +233,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN @property (weak, nonatomic) UIAlertController *gdprConsentNotGivenAlertController; @property (weak, nonatomic) UIViewController *gdprConsentController; +@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter; + /** Used to manage on boarding steps, like create DM with riot bot */ @@ -647,6 +649,9 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // Register to GDPR consent not given notification [self registerUserConsentNotGivenNotification]; + // Register to identity server terms not signed notification + [self registerIdentityServiceTermsNotSignedNotification]; + // Start monitoring reachability [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { @@ -2101,19 +2106,37 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // iOS Patch: fix vector.im urls before using it webURL = [Tools fixURLWithSeveralHashKeys:webURL]; + NSString *validateEmailSubmitTokenPath = @"validate/email/submitToken"; + + NSString *validateEmailSubmitTokenAPIPathV1 = [NSString stringWithFormat:@"/%@/%@", kMXIdentityAPIPrefixPathV1, validateEmailSubmitTokenPath]; + NSString *validateEmailSubmitTokenAPIPathV2 = [NSString stringWithFormat:@"/%@/%@", kMXIdentityAPIPrefixPathV2, validateEmailSubmitTokenPath]; + // Manage email validation link - if ([webURL.path isEqualToString:@"/_matrix/identity/api/v1/validate/email/submitToken"]) + if ([webURL.path isEqualToString:validateEmailSubmitTokenAPIPathV1] || [webURL.path isEqualToString:validateEmailSubmitTokenAPIPathV2]) { // Validate the email on the passed identity server NSString *identityServer = [NSString stringWithFormat:@"%@://%@", webURL.scheme, webURL.host]; - MXRestClient *identityRestClient = [[MXRestClient alloc] initWithHomeServer:identityServer andOnUnrecognizedCertificateBlock:nil]; + + MXSession *mainSession = self.mxSessions.firstObject; + MXRestClient *homeserverRestClient; + + if (mainSession.matrixRestClient) + { + homeserverRestClient = mainSession.matrixRestClient; + } + else + { + homeserverRestClient = [[MXRestClient alloc] initWithHomeServer:identityServer andOnUnrecognizedCertificateBlock:nil]; + } + + MXIdentityService *identityService = [[MXIdentityService alloc] initWithIdentityServer:identityServer andHomeserverRestClient:homeserverRestClient]; // Extract required parameters from the link NSArray *pathParams; NSMutableDictionary *queryParams; [self parseUniversalLinkFragment:webURL.absoluteString outPathParams:&pathParams outQueryParams:&queryParams]; - [identityRestClient submit3PIDValidationToken:queryParams[@"token"] medium:kMX3PIDMediumEmail clientSecret:queryParams[@"client_secret"] sid:queryParams[@"sid"] success:^{ + [identityService submit3PIDValidationToken:queryParams[@"token"] medium:kMX3PIDMediumEmail clientSecret:queryParams[@"client_secret"] sid:queryParams[@"sid"] success:^{ NSLog(@"[AppDelegate] handleUniversalLink. Email successfully validated."); @@ -4683,6 +4706,63 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN }]; } +#pragma mark - Identity server service terms + +// Observe identity server terms not signed notification +- (void)registerIdentityServiceTermsNotSignedNotification +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleIdentityServiceTermsNotSignedNotification:) name:MXIdentityServiceTermsNotSignedNotification object:nil]; +} + +- (void)handleIdentityServiceTermsNotSignedNotification:(NSNotification*)notification +{ + NSString *baseURL; + NSString *accessToken; + + MXJSONModelSetString(baseURL, notification.userInfo[MXIdentityServiceNotificationIdentityServerKey]); + MXJSONModelSetString(accessToken, notification.userInfo[MXIdentityServiceNotificationAccessTokenKey]); + + [self presentIdentityServerTermsWithBaseURL:baseURL andAccessToken:accessToken]; +} + +- (void)presentIdentityServerTermsWithBaseURL:(NSString*)baseURL andAccessToken:(NSString*)accessToken +{ + MXSession *mxSession = self.mxSessions.firstObject; + + if (!mxSession || !baseURL || !accessToken || self.serviceTermsModalCoordinatorBridgePresenter.isPresenting) + { + return; + } + + ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter = [[ServiceTermsModalCoordinatorBridgePresenter alloc] initWithSession:mxSession + baseUrl:baseURL + serviceType:MXServiceTypeIdentityService + accessToken:accessToken]; + + serviceTermsModalCoordinatorBridgePresenter.delegate = self; + + UIViewController *presentingViewController = self.window.rootViewController.presentedViewController ?: self.window.rootViewController; + + [serviceTermsModalCoordinatorBridgePresenter presentFrom:presentingViewController animated:YES]; + self.serviceTermsModalCoordinatorBridgePresenter = serviceTermsModalCoordinatorBridgePresenter; +} + +- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter +{ + [coordinatorBridgePresenter dismissWithAnimated:YES completion:^{ + + }]; + self.serviceTermsModalCoordinatorBridgePresenter = nil; +} + +- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter +{ + [coordinatorBridgePresenter dismissWithAnimated:YES completion:^{ + + }]; + self.serviceTermsModalCoordinatorBridgePresenter = nil; +} + #pragma mark - Settings - (void)setupUserDefaults diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 2260cca71..2225bbd18 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -604,20 +604,22 @@ restClient = [self.delegate authInputsViewThirdPartyIdValidationRestClient:self]; } - if (restClient) + if (restClient && restClient.identityServer) { // Check whether a second 3pid is available _isThirdPartyIdentifierPending = (nbPhoneNumber && ![self isFlowCompleted:kMXLoginFlowTypeMSISDN]); // Launch email validation submittedEmail = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:self.emailTextField.text]; + + NSString *identityServer = restClient.identityServer; // Create the next link that is common to all Vector.im clients NSString *nextLink = [NSString stringWithFormat:@"%@/#/register?client_secret=%@&hs_url=%@&is_url=%@&session_id=%@", [Tools webAppUrl], [submittedEmail.clientSecret stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]], [restClient.homeserver stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]], - [restClient.identityServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]], + [identityServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]], [currentSession.session stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]]; [submittedEmail requestValidationTokenWithMatrixRestClient:restClient @@ -626,7 +628,7 @@ success:^ { - NSURL *identServerURL = [NSURL URLWithString:restClient.identityServer]; + NSURL *identServerURL = [NSURL URLWithString:identityServer]; NSDictionary *parameters; parameters = @{ @"auth": @{ @@ -1644,31 +1646,40 @@ { [self->submittedMSISDN submitValidationToken:smsCode success:^{ - // Retrieve the REST client from delegate - MXRestClient *restClient; + // Retrieve the identity service from delegate + MXIdentityService *identityService; - if (self.delegate && [self.delegate respondsToSelector:@selector(authInputsViewThirdPartyIdValidationRestClient:)]) + if (self.delegate && [self.delegate respondsToSelector:@selector(authInputsViewThirdPartyIdValidationIdentityService:)]) { - restClient = [self.delegate authInputsViewThirdPartyIdValidationRestClient:self]; + identityService = [self.delegate authInputsViewThirdPartyIdValidationIdentityService:self]; } - NSURL *identServerURL = [NSURL URLWithString:restClient.identityServer]; - NSDictionary *parameters; - parameters = @{ - @"auth": @{ - @"session":self->currentSession.session, - @"threepid_creds": @{ - @"client_secret": self->submittedMSISDN.clientSecret, - @"id_server": identServerURL.host, - @"sid": self->submittedMSISDN.sid - }, - @"type": kMXLoginFlowTypeMSISDN - }, - @"username": self.userLoginTextField.text, - @"password": self.passWordTextField.text - }; + NSString *identityServer = identityService.identityServer; - callback(parameters, nil); + if (identityServer) + { + NSURL *identServerURL = [NSURL URLWithString:identityServer]; + NSDictionary *parameters; + parameters = @{ + @"auth": @{ + @"session":self->currentSession.session, + @"threepid_creds": @{ + @"client_secret": self->submittedMSISDN.clientSecret, + @"id_server": identServerURL.host, + @"sid": self->submittedMSISDN.sid + }, + @"type": kMXLoginFlowTypeMSISDN + }, + @"username": self.userLoginTextField.text, + @"password": self.passWordTextField.text + }; + + callback(parameters, nil); + } + else + { + NSLog(@"[AuthInputsView] Failed to retrieve identity server URL"); + } } failure:^(NSError *error) { diff --git a/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorBridgePresenter.swift b/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorBridgePresenter.swift index 22cda942b..5802b90eb 100644 --- a/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorBridgePresenter.swift +++ b/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorBridgePresenter.swift @@ -42,6 +42,10 @@ final class ServiceTermsModalCoordinatorBridgePresenter: NSObject { weak var delegate: ServiceTermsModalCoordinatorBridgePresenterDelegate? + var isPresenting: Bool { + return self.coordinator != nil + } + // MARK: - Setup init(session: MXSession, baseUrl: String, serviceType: MXServiceType, accessToken: String) {