Skip to content

Commit

Permalink
[Passkey #1 cloned] start passkey enrollment rpc (#11872)
Browse files Browse the repository at this point in the history
1. implemented rpc call to startPasskeyEnrollment
2. defined startPasskeyEnrollment request and response
3. added unit tests
  • Loading branch information
Xiaoshouzi-gh authored Oct 2, 2023
1 parent 0e7e4f9 commit b8f0972
Show file tree
Hide file tree
Showing 8 changed files with 709 additions and 6 deletions.
48 changes: 42 additions & 6 deletions FirebaseAuth/Sources/Backend/FIRAuthBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
@class FIRRevokeTokenResponse;
@class FIRGetRecaptchaConfigRequest;
@class FIRGetRecaptchaConfigResponse;
@class FIRStartPasskeyEnrollmentRequest;
@class FIRStartPasskeyEnrollmentResponse;

@protocol FIRAuthBackendImplementation;
@protocol FIRAuthBackendRPCIssuer;
Expand Down Expand Up @@ -243,15 +245,27 @@ 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);

/** @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 +462,17 @@ 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;
#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 +647,17 @@ 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;
#endif

/** @fn revokeToken:callback:
@brief Calls the revokeToken endpoint, which is responsible for revoking the given token
provided in the request parameters.
Expand Down
25 changes: 25 additions & 0 deletions FirebaseAuth/Sources/Backend/FIRAuthBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,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/FIRStartPasskeyEnrollmentRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRStartPasskeyEnrollmentResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h"
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h"
Expand Down Expand Up @@ -673,6 +675,13 @@ + (void)verifyClient:(id)request callback:(FIRVerifyClientResponseCallback)callb

#endif

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST
+ (void)startPasskeyEnrollment:(FIRStartPasskeyEnrollmentRequest *)request
callback:(FIRStartPasskeyEnrollmentResponseCallback)callback {
[[self implementation] startPasskeyEnrollment:request callback:callback];
}
#endif

+ (void)revokeToken:(FIRRevokeTokenRequest *)request
callback:(FIRRevokeTokenResponseCallback)callback {
[[self implementation] revokeToken:request callback:callback];
Expand Down Expand Up @@ -1099,6 +1108,22 @@ - (void)verifyClient:(id)request callback:(FIRVerifyClientResponseCallback)callb

#endif

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST
- (void)startPasskeyEnrollment:(FIRStartPasskeyEnrollmentRequest *)request
callback:(FIRStartPasskeyEnrollmentResponseCallback)callback {
FIRStartPasskeyEnrollmentResponse *response = [[FIRStartPasskeyEnrollmentResponse alloc] init];
[self callWithRequest:request
response:response
callback:^(NSError *error) {
if (error) {
callback(nil, error);
return;
}
callback(response, nil);
}];
}
#endif

- (void)revokeToken:(FIRRevokeTokenRequest *)request
callback:(FIRRevokeTokenResponseCallback)callback {
FIRRevokeTokenResponse *response = [[FIRRevokeTokenResponse alloc] init];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 FIRStartPasskeyEnrollmentRequest
@brief Represents the parameters for the startPasskeyEnrollment endpoint.
*/
@interface FIRStartPasskeyEnrollmentRequest : FIRIdentityToolkitRequest <FIRAuthRPCRequest>

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

- (nullable instancetype)initWithIDToken:(NSString *)IDToken
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration;

@end

NS_ASSUME_NONNULL_END
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/RPC/FIRStartPasskeyEnrollmentRequest.h"

NS_ASSUME_NONNULL_BEGIN

/**
@var kStartPasskeyEnrollmentEndPoint
@brief GCIP endpoint for startPasskeyEnrollment rpc
*/
static NSString *const kStartPasskeyEnrollmentEndPoint = @"accounts/passkeyEnrollment:start";

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

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

@implementation FIRStartPasskeyEnrollmentRequest

- (nullable instancetype)initWithIDToken:(NSString *)IDToken
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration {
self = [super initWithEndpoint:kStartPasskeyEnrollmentEndPoint
requestConfiguration:requestConfiguration];

if (self) {
_IDToken = IDToken;
self.useIdentityPlatform = YES;
}

return self;
}

- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error {
NSMutableDictionary *postBody = [NSMutableDictionary dictionary];
if (_IDToken) {
postBody[kIDToken] = _IDToken;
}
if (self.tenantID) {
postBody[kTenantIDKey] = self.tenantID;
}
return [postBody copy];
}

@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/FIRAuthRPCResponse.h"

NS_ASSUME_NONNULL_BEGIN

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

/**
@property rpID
@brief The RP ID of the FIDO Relying Party.
*/
@property(nonatomic, readonly, copy) NSString *rpID;

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

/**
@property challenge
@brief The FIDO challenge.
*/
@property(nonatomic, readonly, copy) NSString *challenge;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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/FIRStartPasskeyEnrollmentResponse.h"

/**
@var kOptionsKey
@brief The name of the field in the response JSON for CredentialCreationOptions.
*/
static const NSString *kOptionsKey = @"credentialCreationOptions";

/**
@var kRpKey
@brief The name of the field in the response JSON for Relying Party.
*/
static const NSString *kRpKey = @"rp";

/**
@var kUserKey
@brief The name of the field in the response JSON for User.
*/
static const NSString *kUserKey = @"user";

/**
@var kIDKey
@brief The name of the field in the response JSON for ids.
*/
static const NSString *kIDKey = @"id";

/**
@var kChallengeKey
@brief The name of the field in the response JSON for challenge.
*/
static const NSString *kChallengeKey = @"challenge";

@implementation FIRStartPasskeyEnrollmentResponse

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

if (dictionary[kOptionsKey][kUserKey] == nil ||
dictionary[kOptionsKey][kUserKey][kIDKey] == nil) {
return NO;
}

if (dictionary[kOptionsKey][kChallengeKey] == nil) {
return NO;
}

_rpID = dictionary[kOptionsKey][kRpKey][kIDKey];
_userID = dictionary[kOptionsKey][kUserKey][kIDKey];
_challenge = dictionary[kOptionsKey][kChallengeKey];
return YES;
}

@end
Loading

0 comments on commit b8f0972

Please sign in to comment.