Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 57 additions & 5 deletions ios/CredentialsManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
#import <React/RCTLog.h>
#import <AuthenticationServices/AuthenticationServices.h>

static NSArray<NSString *> *RNCMNSArrayFromLazyStringVector(const facebook::react::LazyVector<NSString *> &vec)
{
NSMutableArray<NSString *> *result = [NSMutableArray arrayWithCapacity:vec.size()];
for (size_t i = 0, n = vec.size(); i < n; i++) {
NSString *value = vec.at(i);
if (value != nil) {
[result addObject:value];
}
}
return result;
}

@interface CredentialsManager ()
- (NSArray<ASAuthorizationScope> *)appleAuthorizationScopesFromJSScopes:(NSArray<NSString *> *)scopes;
- (void)configureAppleIDRequest:(ASAuthorizationAppleIDRequest *)request
nonce:(NSString *)nonce
requestedScopes:(NSArray<NSString *> *)requestedScopes;
@end

@implementation CredentialsManager

RCT_EXPORT_MODULE()
Expand Down Expand Up @@ -119,6 +138,14 @@ - (void)signIn:(NSArray *)options
reject:(RCTPromiseRejectBlock)reject {

id passkeyParams = params.passkeys();

NSString *appleNonce = nil;
NSArray<NSString *> *appleRequestedScopes = nil;
std::optional<JS::NativeCredentialsManager::AppleSignInParams> appleSignIn = params.appleSignIn();
if (appleSignIn.has_value()) {
appleNonce = appleSignIn->nonce();
appleRequestedScopes = RNCMNSArrayFromLazyStringVector(appleSignIn->requestedScopes());
}

dispatch_async(dispatch_get_main_queue(), ^{
self.currentResolve = resolve;
Expand Down Expand Up @@ -169,9 +196,7 @@ - (void)signIn:(NSArray *)options
} else if ([option isEqualToString:@"apple-signin"]) {
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];

NSArray<ASAuthorizationScope> *defaultScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
appleIDRequest.requestedScopes = defaultScopes;
[self configureAppleIDRequest:appleIDRequest nonce:appleNonce requestedScopes:appleRequestedScopes];

[authRequests addObject:appleIDRequest];
} else if ([option isEqualToString:@"google-signin"]) {
Expand Down Expand Up @@ -206,15 +231,16 @@ - (void)signUpWithGoogle:(JS::NativeCredentialsManager::GoogleSignInParams &)par
- (void)signUpWithApple:(JS::NativeCredentialsManager::AppleSignInParams &)params
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
NSString *nonce = params.nonce();
NSArray<NSString *> *requestedScopes = RNCMNSArrayFromLazyStringVector(params.requestedScopes());

dispatch_async(dispatch_get_main_queue(), ^{
self.currentResolve = resolve;
self.currentReject = reject;

ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];

appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
[self configureAppleIDRequest:appleIDRequest nonce:nonce requestedScopes:requestedScopes];

ASAuthorizationController *authController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest]];
authController.delegate = self;
Expand Down Expand Up @@ -378,6 +404,32 @@ - (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthoriz
return keyWindow ?: [[UIApplication sharedApplication] windows].firstObject;
}

#pragma mark - Apple Sign In Helpers

- (NSArray<ASAuthorizationScope> *)appleAuthorizationScopesFromJSScopes:(NSArray<NSString *> *)scopes {
NSMutableArray<ASAuthorizationScope> *mappedScopes = [NSMutableArray array];
for (NSString *scope in scopes) {
if ([scope isEqualToString:@"fullName"]) {
[mappedScopes addObject:ASAuthorizationScopeFullName];
} else if ([scope isEqualToString:@"email"]) {
[mappedScopes addObject:ASAuthorizationScopeEmail];
}
}

return mappedScopes.count > 0
? [mappedScopes copy]
: @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
}

- (void)configureAppleIDRequest:(ASAuthorizationAppleIDRequest *)request
nonce:(NSString *)nonce
requestedScopes:(NSArray<NSString *> *)requestedScopes {
if (nonce.length > 0) {
request.nonce = nonce;
}
request.requestedScopes = [self appleAuthorizationScopesFromJSScopes:requestedScopes];
}

#pragma mark - Helper Methods

- (NSString *)createAuthenticationResponseJSON:(ASAuthorizationPlatformPublicKeyCredentialAssertion *)assertion {
Expand Down
Loading