Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passkey Support #12733

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
90 changes: 90 additions & 0 deletions FirebaseAuth/Sources/Auth/FIRAuth.m
Expand Up @@ -40,6 +40,8 @@
#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeySignInRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeySignInResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h"
Expand All @@ -54,6 +56,8 @@
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRStartPasskeySignInRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRStartPasskeySignInResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h"
Expand Down Expand Up @@ -82,6 +86,10 @@
#import "FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h"
#endif

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST
#import <AuthenticationServices/AuthenticationServices.h>
#endif

NS_ASSUME_NONNULL_BEGIN

#pragma mark-- Logger Service String.
Expand Down Expand Up @@ -1216,6 +1224,88 @@ - (void)signInWithCustomToken:(NSString *)token
});
}

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST
- (void)startPasskeySignInWithCompletion:
(nullable void (^)(
ASAuthorizationPlatformPublicKeyCredentialAssertionRequest *_Nullable request,
NSError *_Nullable error))completion {
FIRStartPasskeySignInRequest *request =
[[FIRStartPasskeySignInRequest alloc] initWithRequestConfiguration:self.requestConfiguration];
[FIRAuthBackend
startPasskeySignIn:request
callback:^(FIRStartPasskeySignInResponse *_Nullable response,
NSError *_Nullable error) {
if (error) {
completion(nil, error);
return;
}
if (response) {
NSData *challengeInData =
[[NSData alloc] initWithBase64EncodedString:response.challenge options:0];
ASAuthorizationPlatformPublicKeyCredentialProvider *provider =
[[ASAuthorizationPlatformPublicKeyCredentialProvider alloc]
initWithRelyingPartyIdentifier:response.rpID];
ASAuthorizationPlatformPublicKeyCredentialAssertionRequest *request =
[provider createCredentialAssertionRequestWithChallenge:challengeInData];

completion(request, nil);
}
}];
}

- (void)finalizePasskeySignInWithPlatformCredential:
(ASAuthorizationPlatformPublicKeyCredentialAssertion *)platformCredential
completion:(nullable void (^)(
FIRAuthDataResult *_Nullable authResult,
NSError *_Nullable error))completion {
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
FIRAuthDataResultCallback decoratedCallback =
[self signInFlowAuthDataResultCallbackByDecoratingCallback:completion];
NSString *credentialID = [platformCredential.credentialID base64EncodedStringWithOptions:0];
NSString *clientDataJson =
[platformCredential.rawClientDataJSON base64EncodedStringWithOptions:0];
NSString *authenticatorData =
[platformCredential.rawAuthenticatorData base64EncodedStringWithOptions:0];
NSString *signature = [platformCredential.signature base64EncodedStringWithOptions:0];
NSString *userID = [platformCredential.userID base64EncodedStringWithOptions:0];
FIRFinalizePasskeySignInRequest *request =
[[FIRFinalizePasskeySignInRequest alloc] initWithCredentialID:credentialID
clientDataJson:clientDataJson
authenticatorData:authenticatorData
signature:signature
userID:userID
requestConfiguration:self.requestConfiguration];
[FIRAuthBackend
finalizePasskeySignIn:request
callback:^(FIRFinalizePasskeySignInResponse *_Nullable response,
NSError *_Nullable error) {
if (error) {
decoratedCallback(nil, error);
return;
}
[self completeSignInWithAccessToken:response.idToken
accessTokenExpirationDate:nil
refreshToken:response.refreshToken
anonymous:NO
callback:^(FIRUser *_Nullable user,
NSError *_Nullable error) {
if (error) {
completion(nil, error);
return;
}

FIRAuthDataResult *authDataResult =
user ? [[FIRAuthDataResult alloc]
initWithUser:user
additionalUserInfo:nil]
: nil;
decoratedCallback(authDataResult, error);
}];
}];
});
}
#endif // #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST

- (void)createUserWithEmail:(NSString *)email
password:(NSString *)password
completion:(nullable FIRAuthDataResultCallback)completion {
Expand Down
137 changes: 131 additions & 6 deletions FirebaseAuth/Sources/Backend/FIRAuthBackend.h
Expand Up @@ -58,6 +58,14 @@
@class FIRRevokeTokenResponse;
@class FIRGetRecaptchaConfigRequest;
@class FIRGetRecaptchaConfigResponse;
@class FIRStartPasskeyEnrollmentRequest;
@class FIRStartPasskeyEnrollmentResponse;
@class FIRFinalizePasskeyEnrollmentRequest;
@class FIRFinalizePasskeyEnrollmentResponse;
@class FIRStartPasskeySignInRequest;
@class FIRStartPasskeySignInResponse;
@class FIRFinalizePasskeySignInRequest;
@class FIRFinalizePasskeySignInResponse;

@protocol FIRAuthBackendImplementation;
@protocol FIRAuthBackendRPCIssuer;
Expand Down Expand Up @@ -243,15 +251,60 @@ typedef void (^FIRRevokeTokenResponseCallback)(FIRRevokeTokenResponse *_Nullable
typedef void (^FIRSignInWithGameCenterResponseCallback)(
FIRSignInWithGameCenterResponse *_Nullable response, NSError *_Nullable error);

/** @typedef FIRGetRecaptchaConfigResponseCallback
@brief The type of block used to return the result of a call to the getRecaptchaConfig endpoint.
@param response The received response, if any.
@param error The error which occurred, if any.
@remarks One of response or error will be non-nil.
*/
/**
@typedef FIRGetRecaptchaConfigResponseCallback
@brief The type of block used to return the result of a call to the getRecaptchaConfig endpoint.
@param response The received response, if any.
@param error The error which occurred, if any.
@remarks One of response or error will be non-nil.
*/
typedef void (^FIRGetRecaptchaConfigResponseCallback)(
FIRGetRecaptchaConfigResponse *_Nullable response, NSError *_Nullable error);

/**
@typedef FIRStartPasskeyEnrollmentResponseCallback
@brief The type of block used to return the result of a call to the StartPasskeyEnrollment
endpoint.
@param response The received response, if any.
@param error The error which occurred, if any.
@remarks One of response or error will be non-nil.
*/
typedef void (^FIRStartPasskeyEnrollmentResponseCallback)(
FIRStartPasskeyEnrollmentResponse *_Nullable response, NSError *_Nullable error);

/**
@typedef FIRFinalizePasskeyEnrollmentResponseCallback
@brief The type of block used to return the result of a call to the finalizePasskeyEnrollment
endpoint.
@param response The received response, if any.
@param error The error which occurred, if any.
@remarks One of response or error will be non-nil.
*/
typedef void (^FIRFinalizePasskeyEnrollmentResponseCallback)(
FIRFinalizePasskeyEnrollmentResponse *_Nullable response, NSError *_Nullable error);

/**
@typedef FIRStartPasskeySignInResponseCallback
@brief The type of block used to return the result of a call to the StartPasskeySignIn
endpoint.
@param response The received response, if any.
@param error The error which occurred, if any.
@remarks One of response or error will be non-nil.
*/
typedef void (^FIRStartPasskeySignInResponseCallback)(
FIRStartPasskeySignInResponse *_Nullable response, NSError *_Nullable error);

/**
@typedef FIRFinalizePasskeySignInResponseCallback
@brief The type of block used to return the result of a call to the finalizePasskeySignIn
endpoint.
@param response The received response, if any.
@param error The error which occurred, if any.
@remarks One of response or error will be non-nil.
*/
typedef void (^FIRFinalizePasskeySignInResponseCallback)(
FIRFinalizePasskeySignInResponse *_Nullable response, NSError *_Nullable error);

/** @class FIRAuthBackend
@brief Simple static class with methods representing the backend RPCs.
@remarks All callback blocks passed as method parameters are invoked asynchronously on the
Expand Down Expand Up @@ -448,6 +501,42 @@ typedef void (^FIRGetRecaptchaConfigResponseCallback)(

#endif

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST
/** @fn startPasskeyEnrollment:callback:
@brief Calls the startPasskeyEnrollment endpoint, which is responsible for receving the
challenge that will later be consumed for platform key creation.
@param request The request parameters.
@param callback The callback.
*/
+ (void)startPasskeyEnrollment:(FIRStartPasskeyEnrollmentRequest *)request
callback:(FIRStartPasskeyEnrollmentResponseCallback)callback;

/** @fn finalizePasskeyEnrollment:callback:
@brief Sends the platform created public info to the finalizePasskeyEnrollment endpoint.
@param request The request parameters.
@param callback The callback.
*/
+ (void)finalizePasskeyEnrollment:(FIRFinalizePasskeyEnrollmentRequest *)request
callback:(FIRFinalizePasskeyEnrollmentResponseCallback)callback;

/** @fn startPasskeySignIn:callback:
@brief Calls the startPasskeySignIn endpoint, which is responsible for receving the
challenge that will later be consumed for platform key attestation.
@param request The request parameters.
@param callback The callback.
*/
+ (void)startPasskeySignIn:(FIRStartPasskeySignInRequest *)request
callback:(FIRStartPasskeySignInResponseCallback)callback;

/** @fn finalizePasskeySignIn:callback:
@brief Sends the platform created public info to the finalizePasskeySignIn endpoint.
@param request The request parameters.
@param callback The callback.
*/
+ (void)finalizePasskeySignIn:(FIRFinalizePasskeySignInRequest *)request
callback:(FIRFinalizePasskeySignInResponseCallback)callback;
#endif

/** @fn revokeToken:callback:
@brief Calls the revokeToken endpoint, which is responsible for revoking the given token
provided in the request parameters.
Expand Down Expand Up @@ -622,6 +711,42 @@ typedef void (^FIRGetRecaptchaConfigResponseCallback)(

#endif

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST
/** @fn startPasskeyEnrollment:callback:
@brief Calls the startPasskeyEnrollment endpoint, which is responsible for receving the
challenge that will later be consumed for platform key creation.
@param request The request parameters.
@param callback The callback.
*/
- (void)startPasskeyEnrollment:(FIRStartPasskeyEnrollmentRequest *)request
callback:(FIRStartPasskeyEnrollmentResponseCallback)callback;

/** @fn finalizePasskeyEnrollment:callback:
@brief Calls the finalizePasskeyEnrollment endpoint, which is responsible for sending the
platform credential details to GCIP backend to exchange the access token and refresh token.
@param request The request parameters.
@param callback The callback.
*/
- (void)finalizePasskeyEnrollment:(FIRFinalizePasskeyEnrollmentRequest *)request
callback:(FIRFinalizePasskeyEnrollmentResponseCallback)callback;

/** @fn startPasskeySignIn:callback:
@brief Calls the startPasskeySignIn endpoint, which is responsible for receving the challange.
@param request The request parameters.
@param callback The callback.
*/
- (void)startPasskeySignIn:(FIRStartPasskeySignInRequest *)request
callback:(FIRStartPasskeySignInResponseCallback)callback;

/** @fn finalizePasskeySignIn:callback:
@brief Sends the platform created public info to the finalizePasskeySignIn endpoint.
@param request The request parameters.
@param callback The callback.
*/
- (void)finalizePasskeySignIn:(FIRFinalizePasskeySignInRequest *)request
callback:(FIRFinalizePasskeySignInResponseCallback)callback;
#endif

/** @fn revokeToken:callback:
@brief Calls the revokeToken endpoint, which is responsible for revoking the given token
provided in the request parameters.
Expand Down