Skip to content

Commit

Permalink
[Passkey #2] finalize passkey enrollment rpc (#11885)
Browse files Browse the repository at this point in the history
Implemented finalizePasskeyEnrollment rpc call
Defined finalizePasskeyEnrollment Request and Response object
Added unit tests
  • Loading branch information
Xiaoshouzi-gh authored Oct 4, 2023
1 parent dfa40c0 commit 33f3636
Show file tree
Hide file tree
Showing 9 changed files with 765 additions and 1 deletion.
31 changes: 31 additions & 0 deletions FirebaseAuth/Sources/Backend/FIRAuthBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
@class FIRGetRecaptchaConfigResponse;
@class FIRStartPasskeyEnrollmentRequest;
@class FIRStartPasskeyEnrollmentResponse;
@class FIRFinalizePasskeyEnrollmentRequest;
@class FIRFinalizePasskeyEnrollmentResponse;
@class FIRStartPasskeySignInRequest;
@class FIRStartPasskeySignInResponse;

Expand Down Expand Up @@ -268,6 +270,17 @@ endpoint.
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 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 (^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
Expand Down Expand Up @@ -485,6 +498,14 @@ typedef void (^FIRStartPasskeySignInResponseCallback)(
+ (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.
Expand Down Expand Up @@ -679,6 +700,16 @@ typedef void (^FIRStartPasskeySignInResponseCallback)(
- (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.
Expand Down
23 changes: 23 additions & 0 deletions FirebaseAuth/Sources/Backend/FIRAuthBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeyEnrollmentRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeyEnrollmentResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h"
Expand Down Expand Up @@ -687,6 +689,11 @@ + (void)startPasskeyEnrollment:(FIRStartPasskeyEnrollmentRequest *)request
callback:(FIRStartPasskeyEnrollmentResponseCallback)callback {
[[self implementation] startPasskeyEnrollment:request callback:callback];
}

+ (void)finalizePasskeyEnrollment:(FIRFinalizePasskeyEnrollmentRequest *)request
callback:(FIRFinalizePasskeyEnrollmentResponseCallback)callback {
[[self implementation] finalizePasskeyEnrollment:request callback:callback];
}
#endif

+ (void)revokeToken:(FIRRevokeTokenRequest *)request
Expand Down Expand Up @@ -1144,6 +1151,22 @@ - (void)startPasskeyEnrollment:(FIRStartPasskeyEnrollmentRequest *)request
callback(response, nil);
}];
}

- (void)finalizePasskeyEnrollment:(FIRFinalizePasskeyEnrollmentRequest *)request
callback:(FIRFinalizePasskeyEnrollmentResponseCallback)callback {
FIRFinalizePasskeyEnrollmentResponse *response =
[[FIRFinalizePasskeyEnrollmentResponse alloc] init];
[self callWithRequest:request
response:response
callback:^(NSError *error) {
if (error) {
callback(nil, error);
return;
}
callback(response, nil);
}];
}

#endif

- (void)revokeToken:(FIRRevokeTokenRequest *)request
Expand Down
2 changes: 1 addition & 1 deletion FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
@protocol FIRAuthRPCResponse <NSObject>

/** @fn setFieldsWithDictionary:error:
/** @fn setWithDictionary:error:
@brief Sets the response instance from the decoded JSON response.
@param dictionary The dictionary decoded from HTTP JSON response.
@param error An out field for an error which occurred constructing the request.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h"
#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h"

NS_ASSUME_NONNULL_BEGIN

/** @class FIRFinalizePasskeyEnrollmentRequest
@brief Represents the parameters for the finalizePasskeyEnrollment endpoint.
*/
@interface FIRFinalizePasskeyEnrollmentRequest : FIRIdentityToolkitRequest <FIRAuthRPCRequest>

/**
@property IDToken
@brief The raw user access token.
*/
@property(nonatomic, copy, readonly) NSString *IDToken;

/**
@property name
@brief The passkey name.
*/
@property(nonatomic, copy, readonly) NSString *name;

/**
@property credentialID
@brief The credential ID.
*/
@property(nonatomic, copy, readonly) NSString *credentialID;

/**
@property clientDataJson
@brief The CollectedClientData object from the authenticator.
*/
@property(nonatomic, copy, readonly) NSString *clientDataJson;

/**
@property attestationObject
@brief The attestation object from the authenticator.
*/
@property(nonatomic, copy, readonly) NSString *attestationObject;

- (nullable instancetype)initWithIDToken:(NSString *)IDToken
name:(NSString *)name
credentialID:(NSString *)credentialID
clientDataJson:(NSString *)clientDataJson
attestationObject:(NSString *)attestationObject
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration;

@end

NS_ASSUME_NONNULL_END
127 changes: 127 additions & 0 deletions FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeyEnrollmentRequest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeyEnrollmentRequest.h"
NS_ASSUME_NONNULL_BEGIN

/**
@var kFinalizePasskeyEnrollmentEndPoint
@brief GCIP endpoint for finalizePasskeyEnrollment rpc
*/
static NSString *const kFinalizePasskeyEnrollmentEndPoint = @"accounts/passkeyEnrollment:finalize";

/**
@var kTenantIDKey
@brief The key for the tenant id value in the request.
*/
static NSString *const kTenantIDKey = @"tenantId";

/**
@var kIDTokenKey
@brief The key for idToken value in the request.
*/
static NSString *const kIDTokenKey = @"idToken";

/**
@var kAuthRegistrationRespKey
@brief The key for registration object from the authenticator.
*/
static NSString *const kAuthRegistrationRespKey = @"authenticatorRegistrationResponse";

/**
@var kNameKey
@brief The key of passkey name.
*/
static NSString *const kNameKey = @"name";

/**
@var kCredentialIDKey
@brief The key for registered credential identifier.
*/
static NSString *const kCredentialIDKey = @"credentialId";

/**
@var kAuthAttestationRespKey
@brief The key for attestation response from a FIDO authenticator.
*/
static NSString *const kAuthAttestationRespKey = @"authenticatorAttestationResponse";

/**
@var kClientDataJsonKey
@brief The key for CollectedClientData object from the authenticator.
*/
static NSString *const kClientDataJsonKey = @"clientDataJson";

/**
@var kAttestationObject
@brief The key for the attestation object from the authenticator.
*/
static NSString *const kAttestationObject = @"attestationObject";

@implementation FIRFinalizePasskeyEnrollmentRequest

- (nullable instancetype)initWithIDToken:(NSString *)IDToken
name:(NSString *)name
credentialID:(NSString *)credentialID
clientDataJson:(NSString *)clientDataJson
attestationObject:(NSString *)attestationObject
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration {
self = [super initWithEndpoint:kFinalizePasskeyEnrollmentEndPoint
requestConfiguration:requestConfiguration];
if (self) {
self.useIdentityPlatform = YES;
_IDToken = IDToken;
_name = name;
_credentialID = credentialID;
_clientDataJson = clientDataJson;
_attestationObject = attestationObject;
}
return self;
}

- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error {
NSMutableDictionary *postBody = [NSMutableDictionary dictionary];
NSMutableDictionary *authRegistrationResponse = [NSMutableDictionary dictionary];
NSMutableDictionary *authAttestationResponse = [NSMutableDictionary dictionary];

if (_IDToken) {
postBody[kIDTokenKey] = _IDToken;
}
if (_name) {
postBody[kNameKey] = _name;
}
if (_credentialID) {
authRegistrationResponse[kCredentialIDKey] = _credentialID;
}
if (_clientDataJson) {
authAttestationResponse[kClientDataJsonKey] = _clientDataJson;
}
if (_attestationObject) {
authAttestationResponse[kAttestationObject] = _attestationObject;
}
if (self.tenantID) {
postBody[kTenantIDKey] = self.tenantID;
}

authRegistrationResponse[kAuthAttestationRespKey] = authAttestationResponse;
postBody[kAuthRegistrationRespKey] = authRegistrationResponse;

return [postBody copy];
}

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h"

NS_ASSUME_NONNULL_BEGIN

/**
@class FIRFinalizePasskeyEnrollmentResponse
@brief Represents the response from the startPasskeyEnrollment endpoint.
*/
@interface FIRFinalizePasskeyEnrollmentResponse : NSObject <FIRAuthRPCResponse>

/**
@property idToken
@brief The user raw access token.
*/
@property(nonatomic, readonly, copy) NSString *idToken;

/**
@property refershToken
@brief Refresh token for the authenticated user.
*/
@property(nonatomic, copy, readonly) NSData *refreshToken;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "FirebaseAuth/Sources/Backend/RPC/FIRFinalizePasskeyEnrollmentResponse.h"

/**
@var kIDTokenKey
@brief The name of the field in the response JSON for id token.
*/
static const NSString *kIdTokenKey = @"idToken";

/**
@var kRefreshTokenKey
@brief The name of the field in the response JSON for refresh token.
*/
static const NSString *kRefreshTokenKey = @"refreshToken";

@implementation FIRFinalizePasskeyEnrollmentResponse

- (BOOL)setWithDictionary:(nonnull NSDictionary *)dictionary
error:(NSError *__autoreleasing _Nullable *_Nullable)error {
if (dictionary[kIdTokenKey] == nil) {
return NO;
}
if (dictionary[kRefreshTokenKey] == nil) {
return NO;
}

_idToken = dictionary[kIdTokenKey];
_refreshToken = dictionary[kRefreshTokenKey];
return YES;
}

@end
Loading

0 comments on commit 33f3636

Please sign in to comment.