AuthenticationViewController.m 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  3. * SPDX-License-Identifier: GPL-3.0-or-later
  4. */
  5. #import "AuthenticationViewController.h"
  6. #import "NextcloudTalk-Swift.h"
  7. #import "CCCertificate.h"
  8. #import "NCAPIController.h"
  9. #import "NCAppBranding.h"
  10. #import "NCDatabaseManager.h"
  11. #import "NCSettingsController.h"
  12. NSString * const kNCAuthTokenFlowEndpoint = @"/index.php/login/flow";
  13. @interface AuthenticationViewController () <WKNavigationDelegate>
  14. {
  15. UIActivityIndicatorView *_activityIndicatorView;
  16. }
  17. @end
  18. @implementation AuthenticationViewController
  19. @synthesize delegate = _delegate;
  20. - (id)initWithServerUrl:(NSString *)serverUrl
  21. {
  22. self = [super init];
  23. if (self) {
  24. self.serverUrl = serverUrl;
  25. }
  26. return self;
  27. }
  28. - (void)viewDidLoad
  29. {
  30. [super viewDidLoad];
  31. WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
  32. configuration.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
  33. NSString *urlString = [NSString stringWithFormat:@"%@%@", _serverUrl, kNCAuthTokenFlowEndpoint];
  34. if (_user) {
  35. urlString = [NSString stringWithFormat:@"%@?user=%@", urlString, _user];
  36. }
  37. NSURL *url = [NSURL URLWithString:urlString];
  38. NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
  39. for (NSHTTPCookie *cookie in [storage cookies])
  40. {
  41. [storage deleteCookie:cookie];
  42. }
  43. NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
  44. NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
  45. [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
  46. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
  47. [request setValue:@"true" forHTTPHeaderField:@"OCS-APIRequest"];
  48. self->_webView = [[DebounceWebView alloc] initWithFrame:self.view.frame configuration:configuration];
  49. NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
  50. NSString *deviceName = [[UIDevice currentDevice] name];
  51. NSString *userAgent = [NSString stringWithFormat:@"%@ (%@)", deviceName, appDisplayName];
  52. self->_webView.customUserAgent = [[NSString alloc] initWithCString:[userAgent UTF8String] encoding:NSASCIIStringEncoding];
  53. self->_webView.navigationDelegate = self;
  54. self->_webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  55. [self->_webView loadRequest:request];
  56. [self.view addSubview:self->_webView];
  57. self->_activityIndicatorView = [[UIActivityIndicatorView alloc] init];
  58. self->_activityIndicatorView.center = self.view.center;
  59. self->_activityIndicatorView.color = [NCAppBranding brandColor];
  60. [self->_activityIndicatorView startAnimating];
  61. [self.view addSubview:self->_activityIndicatorView];
  62. }];
  63. }
  64. - (void)viewWillAppear:(BOOL)animated
  65. {
  66. [super viewWillAppear:animated];
  67. UIColor *themeColor = [NCAppBranding themeColor];
  68. [self.view setBackgroundColor:themeColor];
  69. [self.navigationController.navigationBar setTitleTextAttributes:
  70. @{NSForegroundColorAttributeName:[NCAppBranding themeTextColor]}];
  71. self.navigationController.navigationBar.tintColor = [NCAppBranding themeTextColor];
  72. self.navigationController.navigationBar.translucent = YES;
  73. self.navigationController.navigationBar.barTintColor = [NCAppBranding themeColor];
  74. UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
  75. target:self action:@selector(cancelButtonPressed)];
  76. cancelButton.accessibilityHint = NSLocalizedString(@"Double tap to dismiss authentication dialog", nil);
  77. self.navigationController.navigationBar.topItem.leftBarButtonItem = cancelButton;
  78. UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
  79. [appearance configureWithOpaqueBackground];
  80. appearance.backgroundColor = themeColor;
  81. appearance.titleTextAttributes = @{NSForegroundColorAttributeName:[NCAppBranding themeTextColor]};
  82. self.navigationItem.standardAppearance = appearance;
  83. self.navigationItem.compactAppearance = appearance;
  84. self.navigationItem.scrollEdgeAppearance = appearance;
  85. }
  86. - (void)cancelButtonPressed
  87. {
  88. [self dismissViewControllerAnimated:YES completion:nil];
  89. }
  90. - (void)didReceiveMemoryWarning
  91. {
  92. [super didReceiveMemoryWarning];
  93. // Dispose of any resources that can be recreated.
  94. }
  95. - (UIStatusBarStyle)preferredStatusBarStyle
  96. {
  97. return [NCAppBranding statusBarStyleForBrandColor];
  98. }
  99. - (BOOL)shouldAutorotate
  100. {
  101. return YES;
  102. }
  103. - (UIInterfaceOrientationMask)supportedInterfaceOrientations
  104. {
  105. return UIInterfaceOrientationMaskPortrait;
  106. }
  107. #pragma mark - WKWebView Navigation Delegate
  108. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
  109. {
  110. NSURL *url = navigationAction.request.URL;
  111. NSArray *components = [url.absoluteString componentsSeparatedByString:@"&"];
  112. NSString *ncScheme = @"nc";
  113. if ([url.scheme isEqualToString:ncScheme]) {
  114. NSString *user = nil;
  115. NSString *token = nil;
  116. NSString *userPrefix = @"user:";
  117. NSString *passPrefix = @"password:";
  118. for (NSString *component in components)
  119. {
  120. if ([component hasPrefix:userPrefix])
  121. user = [[[component substringFromIndex:[userPrefix length]] stringByReplacingOccurrencesOfString:@"+" withString:@" "] stringByRemovingPercentEncoding];
  122. if ([component hasPrefix:passPrefix])
  123. token = [[[component substringFromIndex:[passPrefix length]] stringByReplacingOccurrencesOfString:@"+" withString:@" "] stringByRemovingPercentEncoding];
  124. }
  125. [[NCSettingsController sharedInstance] addNewAccountForUser:user withToken:token inServer:_serverUrl];
  126. [self.delegate authenticationViewControllerDidFinish:self];
  127. decisionHandler(WKNavigationActionPolicyCancel);
  128. return;
  129. }
  130. if (navigationAction.targetFrame == nil) {
  131. [NCUtils openLinkInBrowserWithLink:url.absoluteString];
  132. decisionHandler(WKNavigationActionPolicyCancel);
  133. return;
  134. }
  135. decisionHandler(WKNavigationActionPolicyAllow);
  136. }
  137. - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
  138. {
  139. if ([[CCCertificate sharedManager] checkTrustedChallenge:challenge]) {
  140. completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
  141. } else {
  142. completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
  143. }
  144. }
  145. - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
  146. {
  147. // Disable user interaction to prevent any unwanted zooming while the navigation is ongoing
  148. [self.webView setUserInteractionEnabled:NO];
  149. [_activityIndicatorView stopAnimating];
  150. [_activityIndicatorView removeFromSuperview];
  151. }
  152. - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
  153. [self.webView setUserInteractionEnabled:YES];
  154. }
  155. @end