MainViewController+OAuth.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * Copyright 2019 Google
  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. #import "MainViewController+OAuth.h"
  17. #import <AuthenticationServices/AuthenticationServices.h>
  18. #import "AppManager.h"
  19. #import "FIROAuthProvider.h"
  20. #import "MainViewController+Internal.h"
  21. NS_ASSUME_NONNULL_BEGIN
  22. @interface MainViewController () <ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding>
  23. @end
  24. @implementation MainViewController (OAuth)
  25. - (StaticContentTableViewSection *)oAuthSection {
  26. __weak typeof(self) weakSelf = self;
  27. return [StaticContentTableViewSection sectionWithTitle:@"OAuth" cells:@[
  28. [StaticContentTableViewCell cellWithTitle:@"Sign in with Google"
  29. action:^{ [weakSelf signInGoogleHeadfulLite]; }],
  30. [StaticContentTableViewCell cellWithTitle:@"Link with Google"
  31. action:^{ [weakSelf linkWithGoogleHeadfulLite]; }],
  32. [StaticContentTableViewCell cellWithTitle:@"Reauthenticate with Google"
  33. action:^{ [weakSelf reauthenticateWithGoogleHeadfulLite]; }],
  34. [StaticContentTableViewCell cellWithTitle:@"Sign in with Apple"
  35. action:^{ [weakSelf signInWithApple]; }],
  36. [StaticContentTableViewCell cellWithTitle:@"Link with Apple"
  37. action:^{ [weakSelf linkWithApple]; }],
  38. [StaticContentTableViewCell cellWithTitle:@"Unlink with Apple"
  39. action:^{ [weakSelf unlinkFromProvider:@"apple.com" completion:nil]; }],
  40. [StaticContentTableViewCell cellWithTitle:@"Reauthenticate with Apple"
  41. action:^{ [weakSelf reauthenticateWithApple]; }],
  42. [StaticContentTableViewCell cellWithTitle:@"Sign in with Twitter"
  43. action:^{ [weakSelf signInTwitterHeadfulLite]; }],
  44. [StaticContentTableViewCell cellWithTitle:@"Sign in with GitHub"
  45. action:^{ [weakSelf signInGitHubHeadfulLite]; }],
  46. [StaticContentTableViewCell cellWithTitle:@"Sign in with GitHub (Access token)"
  47. action:^{ [weakSelf signInWithGitHub]; }],
  48. [StaticContentTableViewCell cellWithTitle:@"Sign in with Microsoft"
  49. action:^{ [weakSelf signInMicrosoftHeadfulLite]; }],
  50. [StaticContentTableViewCell cellWithTitle:@"Sign in with Yahoo"
  51. action:^{ [weakSelf signInYahooHeadfulLite]; }],
  52. [StaticContentTableViewCell cellWithTitle:@"Sign in with Linkedin"
  53. action:^{ [weakSelf signInLinkedinHeadfulLite]; }],
  54. ]];
  55. }
  56. - (void)signInGoogleHeadfulLite {
  57. FIROAuthProvider *provider = self.googleOAuthProvider;
  58. provider.customParameters = @{
  59. @"prompt" : @"consent",
  60. };
  61. provider.scopes = @[ @"profile", @"email", @"https://www.googleapis.com/auth/plus.me" ];
  62. [self showSpinner:^{
  63. [[AppManager auth] signInWithProvider:provider
  64. UIDelegate:nil
  65. completion:^(FIRAuthDataResult *_Nullable authResult,
  66. NSError *_Nullable error) {
  67. [self hideSpinner:^{
  68. if (error) {
  69. [self logFailure:@"sign-in with provider (Google) failed" error:error];
  70. } else if (authResult.additionalUserInfo) {
  71. [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]];
  72. if (self.isNewUserToggleOn) {
  73. NSString *newUserString = authResult.additionalUserInfo.newUser ?
  74. @"New user" : @"Existing user";
  75. [self showMessagePromptWithTitle:@"New or Existing"
  76. message:newUserString
  77. showCancelButton:NO
  78. completion:nil];
  79. }
  80. }
  81. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  82. }];
  83. }];
  84. }];
  85. }
  86. - (void)linkWithGoogleHeadfulLite {
  87. FIROAuthProvider *provider = self.googleOAuthProvider;
  88. provider.customParameters = @{
  89. @"prompt" : @"consent",
  90. };
  91. provider.scopes = @[ @"profile", @"email", @"https://www.googleapis.com/auth/plus.me" ];
  92. [self showSpinner:^{
  93. [[AppManager auth].currentUser linkWithProvider:provider
  94. UIDelegate:nil
  95. completion:^(FIRAuthDataResult *_Nullable authResult,
  96. NSError *_Nullable error) {
  97. [self hideSpinner:^{
  98. if (error) {
  99. [self logFailure:@"Reauthenticate with provider (Google) failed" error:error];
  100. } else if (authResult.additionalUserInfo) {
  101. [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]];
  102. if (self.isNewUserToggleOn) {
  103. NSString *newUserString = authResult.additionalUserInfo.newUser ?
  104. @"New user" : @"Existing user";
  105. [self showMessagePromptWithTitle:@"New or Existing"
  106. message:newUserString
  107. showCancelButton:NO
  108. completion:nil];
  109. }
  110. }
  111. [self showTypicalUIForUserUpdateResultsWithTitle:@"Link Error" error:error];
  112. }];
  113. }];
  114. }];
  115. }
  116. - (void)reauthenticateWithGoogleHeadfulLite {
  117. FIROAuthProvider *provider = self.googleOAuthProvider;
  118. provider.customParameters = @{
  119. @"prompt" : @"consent",
  120. };
  121. provider.scopes = @[ @"profile", @"email", @"https://www.googleapis.com/auth/plus.me" ];
  122. [self showSpinner:^{
  123. [[AppManager auth].currentUser reauthenticateWithProvider:provider
  124. UIDelegate:nil
  125. completion:^(FIRAuthDataResult *_Nullable authResult,
  126. NSError *_Nullable error) {
  127. [self hideSpinner:^{
  128. if (error) {
  129. [self logFailure:@"Link with provider (Google) failed" error:error];
  130. } else if (authResult.additionalUserInfo) {
  131. [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]];
  132. if (self.isNewUserToggleOn) {
  133. NSString *newUserString = authResult.additionalUserInfo.newUser ?
  134. @"New user" : @"Existing user";
  135. [self showMessagePromptWithTitle:@"New or Existing"
  136. message:newUserString
  137. showCancelButton:NO
  138. completion:nil];
  139. }
  140. }
  141. [self showTypicalUIForUserUpdateResultsWithTitle:@"Reauthenticate Error" error:error];
  142. }];
  143. }];
  144. }];
  145. }
  146. - (void)signInTwitterHeadfulLite {
  147. FIROAuthProvider *provider = self.twitterOAuthProvider;
  148. [self showSpinner:^{
  149. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential,
  150. NSError *_Nullable error) {
  151. if (error) {
  152. [self logFailure:@"sign-in with Twitter failed" error:error];
  153. return;
  154. }
  155. [[AppManager auth] signInWithCredential:credential
  156. completion:^(FIRAuthDataResult *_Nullable
  157. authResult,
  158. NSError *_Nullable error) {
  159. [self hideSpinner:^{
  160. if (error) {
  161. [self logFailure:@"sign-in with Twitter (headful-lite) failed" error:error];
  162. return;
  163. } else {
  164. [self logSuccess:@"sign-in with Twitter (headful-lite) succeeded."];
  165. }
  166. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  167. }];
  168. }];
  169. }];
  170. }];
  171. }
  172. - (void)signInWithGitHub {
  173. [self showTextInputPromptWithMessage:@"GitHub Access Token:"
  174. completionBlock:^(BOOL userPressedOK, NSString *_Nullable accessToken) {
  175. if (!userPressedOK || !accessToken.length) {
  176. return;
  177. }
  178. FIROAuthCredential *credential =
  179. [FIROAuthProvider credentialWithProviderID:FIRGitHubAuthProviderID accessToken:accessToken];
  180. if (credential) {
  181. [[AppManager auth] signInWithCredential:credential
  182. completion:^(FIRAuthDataResult *_Nullable result,
  183. NSError *_Nullable error) {
  184. if (error) {
  185. [self logFailure:@"sign-in with provider failed" error:error];
  186. } else {
  187. [self logSuccess:@"sign-in with provider succeeded."];
  188. }
  189. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In" error:error];
  190. }];
  191. }
  192. }];
  193. }
  194. - (void)signInGitHubHeadfulLite {
  195. FIROAuthProvider *provider = self.gitHubOAuthProvider;
  196. [self showSpinner:^{
  197. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential,
  198. NSError *_Nullable error) {
  199. if (error) {
  200. [self logFailure:@"sign-in with GitHub failed" error:error];
  201. return;
  202. }
  203. [[AppManager auth] signInWithCredential:credential
  204. completion:^(FIRAuthDataResult *_Nullable
  205. authResult,
  206. NSError *_Nullable error) {
  207. [self hideSpinner:^{
  208. if (error) {
  209. [self logFailure:@"sign-in with GitHub (headful-lite) failed" error:error];
  210. return;
  211. } else {
  212. [self logSuccess:@"sign-in with GitHub (headful-lite) succeeded."];
  213. }
  214. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  215. }];
  216. }];
  217. }];
  218. }];
  219. }
  220. - (void)signInLinkedinHeadfulLite {
  221. FIROAuthProvider *provider = self.linkedinOAuthProvider;
  222. [self showSpinner:^{
  223. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential,
  224. NSError *_Nullable error) {
  225. if (error) {
  226. [self logFailure:@"sign-in with Linkedin failed" error:error];
  227. return;
  228. }
  229. [[AppManager auth] signInWithCredential:credential
  230. completion:^(FIRAuthDataResult *_Nullable
  231. authResult,
  232. NSError *_Nullable error) {
  233. [self hideSpinner:^{
  234. if (error) {
  235. [self logFailure:@"sign-in with Linkedin (headful-lite) failed" error:error];
  236. return;
  237. } else {
  238. [self logSuccess:@"sign-in with Linkedin (headful-lite) succeeded."];
  239. }
  240. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  241. }];
  242. }];
  243. }];
  244. }];
  245. }
  246. - (void)signInMicrosoftHeadfulLite {
  247. FIROAuthProvider *provider = self.microsoftOAuthProvider;
  248. provider.customParameters = @{
  249. @"prompt" : @"consent",
  250. @"login_hint" : @"tu8731@gmail.com",
  251. };
  252. provider.scopes = @[ @"user.readwrite,calendars.read" ];
  253. [self showSpinner:^{
  254. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential,
  255. NSError *_Nullable error) {
  256. if (error) {
  257. [self logFailure:@"sign-in with Microsoft failed" error:error];
  258. return;
  259. }
  260. [[AppManager auth] signInWithCredential:credential
  261. completion:^(FIRAuthDataResult *_Nullable
  262. authResult,
  263. NSError *_Nullable error) {
  264. [self hideSpinner:^{
  265. if (error) {
  266. [self logFailure:@"sign-in with Microsoft failed" error:error];
  267. return;
  268. } else {
  269. [self logSuccess:@"sign-in with Microsoft (headful-lite) succeeded."];
  270. }
  271. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  272. }];
  273. }];
  274. }];
  275. }];
  276. }
  277. - (void)signInYahooHeadfulLite {
  278. FIROAuthProvider *provider = self.yahooOAuthProvider;
  279. [self showSpinner:^{
  280. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential,
  281. NSError *_Nullable error) {
  282. if (error) {
  283. [self logFailure:@"sign-in with Yahoo failed" error:error];
  284. return;
  285. }
  286. [[AppManager auth] signInWithCredential:credential
  287. completion:^(FIRAuthDataResult *_Nullable
  288. authResult,
  289. NSError *_Nullable error) {
  290. [self hideSpinner:^{
  291. if (error) {
  292. [self logFailure:@"sign-in with Yahoo (headful-lite) failed" error:error];
  293. return;
  294. } else {
  295. [self logSuccess:@"sign-in with Yahoo (headful-lite) succeeded."];
  296. }
  297. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  298. }];
  299. }];
  300. }];
  301. }];
  302. }
  303. - (ASAuthorizationAppleIDRequest *)appleIDRequestWithState:(NSString *)state API_AVAILABLE(ios(13.0)) {
  304. ASAuthorizationAppleIDRequest *request = [[[ASAuthorizationAppleIDProvider alloc] init] createRequest];
  305. request.requestedScopes = @[ASAuthorizationScopeEmail, ASAuthorizationScopeFullName];
  306. request.nonce = @"REPLACE_ME_WITH_YOUR_NONCE";
  307. request.state = state;
  308. return request;
  309. }
  310. - (void)signInWithApple {
  311. if (@available(iOS 13, *)) {
  312. ASAuthorizationAppleIDRequest* request = [self appleIDRequestWithState:@"signIn"];
  313. ASAuthorizationController* controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
  314. controller.delegate = self;
  315. controller.presentationContextProvider = self;
  316. [controller performRequests];
  317. }
  318. }
  319. - (void)linkWithApple {
  320. if (@available(iOS 13, *)) {
  321. ASAuthorizationAppleIDRequest* request = [self appleIDRequestWithState:@"link"];
  322. ASAuthorizationController* controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
  323. controller.delegate = self;
  324. controller.presentationContextProvider = self;
  325. [controller performRequests];
  326. }
  327. }
  328. - (void)reauthenticateWithApple {
  329. if (@available(iOS 13, *)) {
  330. ASAuthorizationAppleIDRequest* request = [self appleIDRequestWithState:@"reauth"];
  331. ASAuthorizationController* controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
  332. controller.delegate = self;
  333. controller.presentationContextProvider = self;
  334. [controller performRequests];
  335. }
  336. }
  337. - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
  338. ASAuthorizationAppleIDCredential* appleIDCredential = authorization.credential;
  339. NSString *IDToken = [NSString stringWithUTF8String:[appleIDCredential.identityToken bytes]];
  340. FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"apple.com"
  341. IDToken:IDToken
  342. rawNonce:@"REPLACE_ME_WITH_YOUR_RAW_NONCE"
  343. accessToken:nil];
  344. if ([appleIDCredential.state isEqualToString:@"signIn"]) {
  345. [FIRAuth.auth signInWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
  346. if (!error) {
  347. NSLog(@"%@", authResult.description);
  348. } else {
  349. NSLog(@"%@", error.description);
  350. }
  351. }];
  352. } else if ([appleIDCredential.state isEqualToString:@"link"]) {
  353. [FIRAuth.auth.currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
  354. if (!error) {
  355. NSLog(@"%@", authResult.description);
  356. } else {
  357. NSLog(@"%@", error.description);
  358. }
  359. }];
  360. } else if ([appleIDCredential.state isEqualToString:@"reauth"]) {
  361. [FIRAuth.auth.currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
  362. if (!error) {
  363. NSLog(@"%@", authResult.description);
  364. } else {
  365. NSLog(@"%@", error.description);
  366. }
  367. }];
  368. }
  369. }
  370. - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) {
  371. NSLog(@"%@", error.description);
  372. }
  373. @end
  374. NS_ASSUME_NONNULL_END