Jelajahi Sumber

Update the sample app to use a random nonce in the Sign in with Apple flow (#5981)

* Update the sample app to use a random nonce in the Sign in with Apple flow.

* Address feedback.
Rosalyn Tan 5 tahun lalu
induk
melakukan
c9a8502472

+ 2 - 0
FirebaseAuth/Tests/Sample/Sample/MainViewController+Internal.h

@@ -51,6 +51,8 @@ typedef void (^TestAutomationCallback)(NSError *_Nullable error);
 
 @property(nonatomic) NSURL *actionCodeContinueURL;
 
+@property(nonatomic, copy) NSString *appleRawNonce;
+
 @property(nonatomic) FIROAuthProvider *googleOAuthProvider;
 @property(nonatomic) FIROAuthProvider *microsoftOAuthProvider;
 @property(nonatomic) FIROAuthProvider *twitterOAuthProvider;

+ 50 - 2
FirebaseAuth/Tests/Sample/Sample/MainViewController+OAuth.m

@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@import CommonCrypto;
+
 #import "MainViewController+OAuth.h"
 
 #import <AuthenticationServices/AuthenticationServices.h>
@@ -321,11 +323,57 @@ NS_ASSUME_NONNULL_BEGIN
 - (ASAuthorizationAppleIDRequest *)appleIDRequestWithState:(NSString *)state API_AVAILABLE(ios(13.0)) {
   ASAuthorizationAppleIDRequest *request = [[[ASAuthorizationAppleIDProvider alloc] init] createRequest];
   request.requestedScopes = @[ASAuthorizationScopeEmail, ASAuthorizationScopeFullName];
-  request.nonce = @"REPLACE_ME_WITH_YOUR_NONCE";
+  NSString *rawNonce = [self randomNonce:32];
+  self.appleRawNonce = rawNonce;
+  request.nonce = [self stringBySha256HashingString:rawNonce];
   request.state = state;
   return request;
 }
 
+- (NSString *)randomNonce:(NSInteger)length {
+  NSAssert(length > 0, @"Expected nonce to have positive length");
+  NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
+  NSMutableString *result = [NSMutableString string];
+  NSInteger remainingLength = length;
+
+  while (remainingLength > 0) {
+    NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16];
+    for (NSInteger i = 0; i < 16; i++) {
+      uint8_t random = 0;
+      int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random);
+      NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode);
+
+      [randoms addObject:@(random)];
+    }
+
+    for (NSNumber *random in randoms) {
+      if (remainingLength == 0) {
+        break;
+      }
+
+      if (random.unsignedIntValue < characterSet.length) {
+        unichar character = [characterSet characterAtIndex:random.unsignedIntValue];
+        [result appendFormat:@"%C", character];
+        remainingLength--;
+      }
+    }
+  }
+
+  return result;
+}
+
+- (NSString *)stringBySha256HashingString:(NSString *)input {
+  const char *string = [input UTF8String];
+  unsigned char result[CC_SHA256_DIGEST_LENGTH];
+  CC_SHA256(string, (CC_LONG)strlen(string), result);
+
+  NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
+  for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
+    [hashed appendFormat:@"%02x", result[i]];
+  }
+  return hashed;
+}
+
 - (void)signInWithApple {
   if (@available(iOS 13, *)) {
     ASAuthorizationAppleIDRequest* request = [self appleIDRequestWithState:@"signIn"];
@@ -364,7 +412,7 @@ NS_ASSUME_NONNULL_BEGIN
   NSString *IDToken = [NSString stringWithUTF8String:[appleIDCredential.identityToken bytes]];
   FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"apple.com"
                                                                       IDToken:IDToken
-                                                                     rawNonce:@"REPLACE_ME_WITH_YOUR_RAW_NONCE"
+                                                                     rawNonce:self.appleRawNonce
                                                                   accessToken:nil];
 
   if ([appleIDCredential.state isEqualToString:@"signIn"]) {