Skip to content

Commit

Permalink
Add sample code for passkey sign in and enrollment
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoshouzi-gh committed Nov 21, 2023
1 parent 7927f92 commit 8f27717
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 42 deletions.
107 changes: 65 additions & 42 deletions FirebaseAuth/Tests/Sample/Sample/MainViewController+OAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -434,53 +434,76 @@ - (void)revokeAppleTokenAndDeleteUser {
}

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
ASAuthorizationAppleIDCredential* appleIDCredential = authorization.credential;
NSString *IDToken = [NSString stringWithUTF8String:[appleIDCredential.identityToken bytes]];
FIROAuthCredential *credential =
[FIROAuthProvider appleCredentialWithIDToken:IDToken
rawNonce:self.appleRawNonce
fullName:appleIDCredential.fullName];

if ([appleIDCredential.state isEqualToString:@"signIn"]) {
[FIRAuth.auth signInWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (!error) {
NSLog(@"%@", authResult.description);
} else {
NSLog(@"%@", error.description);
}
}];
} else if ([appleIDCredential.state isEqualToString:@"link"]) {
[FIRAuth.auth.currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (!error) {
NSLog(@"%@", authResult.description);
} else {
NSLog(@"%@", error.description);
}
}];
} else if ([appleIDCredential.state isEqualToString:@"reauth"]) {
[FIRAuth.auth.currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (!error) {
NSLog(@"%@", authResult.description);
} else {
NSLog(@"%@", error.description);
}
}];
} else if ([appleIDCredential.state isEqualToString:@"revokeAppleTokenAndDeleteUser"]) {
NSString *code = [[NSString alloc] initWithData:appleIDCredential.authorizationCode encoding:NSUTF8StringEncoding];
if (@available(iOS 16.0, *)) {
if ([authorization.credential isKindOfClass: [ASAuthorizationPlatformPublicKeyCredentialRegistration class]]) {
ASAuthorizationPlatformPublicKeyCredentialRegistration *platformCredential = (ASAuthorizationPlatformPublicKeyCredentialRegistration*) authorization.credential;

FIRUser *user = FIRAuth.auth.currentUser;
[FIRAuth.auth revokeTokenWithAuthorizationCode:code completion:^(NSError * _Nullable error) {
[user finalizePasskeyEnrollmentWithPlatformCredential:platformCredential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
[self log:[NSString stringWithFormat:@"Passkey Enrollment succeed with uid: %@", authResult.user.uid] ];
[self showTypicalUIForUserUpdateResultsWithTitle:@"Enrollment with passkey" error:error];
}];

} else if ([authorization.credential isKindOfClass: [ASAuthorizationPlatformPublicKeyCredentialAssertion class]]) {
ASAuthorizationPlatformPublicKeyCredentialAssertion *platformCredential = (ASAuthorizationPlatformPublicKeyCredentialAssertion*) authorization.credential;
[[AppManager auth] finalizePasskeySignInWithPlatformCredential:platformCredential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
[self log:[NSString stringWithFormat:@"Passkey sign-in succeed with uid: %@", authResult.user.uid]];
[self showTypicalUIForUserUpdateResultsWithTitle:@"Sign in with passkey" error:error];

}];
}
} else if ([authorization.credential isKindOfClass: [ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential* appleIDCredential = authorization.credential;
NSString *IDToken = [NSString stringWithUTF8String:[appleIDCredential.identityToken bytes]];
FIROAuthCredential *credential =
[FIROAuthProvider appleCredentialWithIDToken:IDToken
rawNonce:self.appleRawNonce
fullName:appleIDCredential.fullName];

if ([appleIDCredential.state isEqualToString:@"signIn"]) {
[FIRAuth.auth signInWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (!error) {
// Token revocation succeeded then delete user again.
[user deleteWithCompletion:^(NSError *_Nullable error) {
if (error) {
[self logFailure:@"delete account failed" error:error];
}
[self showTypicalUIForUserUpdateResultsWithTitle:@"Delete User" error:error];
}];
NSLog(@"%@", authResult.description);
} else {
NSLog(@"%@", error.description);
}
}];
}];
} else if ([appleIDCredential.state isEqualToString:@"link"]) {
[FIRAuth.auth.currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (!error) {
NSLog(@"%@", authResult.description);
} else {
NSLog(@"%@", error.description);
}
}];
} else if ([appleIDCredential.state isEqualToString:@"reauth"]) {
[FIRAuth.auth.currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (!error) {
NSLog(@"%@", authResult.description);
} else {
NSLog(@"%@", error.description);
}
}];
} else if ([appleIDCredential.state isEqualToString:@"revokeAppleTokenAndDeleteUser"]) {
NSString *code = [[NSString alloc] initWithData:appleIDCredential.authorizationCode encoding:NSUTF8StringEncoding];
FIRUser *user = FIRAuth.auth.currentUser;
[FIRAuth.auth revokeTokenWithAuthorizationCode:code completion:^(NSError * _Nullable error) {
if (!error) {
// Token revocation succeeded then delete user again.
[user deleteWithCompletion:^(NSError *_Nullable error) {
if (error) {
[self logFailure:@"delete account failed" error:error];
}
[self showTypicalUIForUserUpdateResultsWithTitle:@"Delete User" error:error];
}];
} else {
NSLog(@"%@", error.description);
}
}];
}
} else {
// TODO signInCredential
[self log:@"credential type not found or OS version too low."];
}
}

Expand Down
31 changes: 31 additions & 0 deletions FirebaseAuth/Tests/Sample/Sample/MainViewController+Passkey.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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/LICENSE-2.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 <Foundation/Foundation.h>

#import "MainViewController.h"

#import "StaticContentTableViewManager.h"

NS_ASSUME_NONNULL_BEGIN

@interface MainViewController (Passkey)

- (StaticContentTableViewSection *)passkeySection;

@end

NS_ASSUME_NONNULL_END
105 changes: 105 additions & 0 deletions FirebaseAuth/Tests/Sample/Sample/MainViewController+Passkey.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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/LICENSE-2.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 "MainViewController+Passkey.h"
#import "AppManager.h"
#import "MainViewController+Internal.h"
#import <AuthenticationServices/AuthenticationServices.h>


NS_ASSUME_NONNULL_BEGIN
@interface MainViewController () <ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding>
@end

@implementation MainViewController (Passkey)

- (StaticContentTableViewSection *)passkeySection {
__weak typeof(self) weakSelf = self;
return [StaticContentTableViewSection sectionWithTitle:@"Passkey" cells:@[
[StaticContentTableViewCell cellWithTitle:@"Sign Up With Passkey"
action:^{ [weakSelf passkeySignUp]; }],
[StaticContentTableViewCell cellWithTitle:@"Sign In With Passkey"
action:^{ [weakSelf passkeySignIn]; }],
[StaticContentTableViewCell cellWithTitle:@"Enroll with Passkey"
action:^{ [weakSelf passkeyEnroll]; }],
]];
}

- (void)passkeySignUp {
// sign in anoymously
[[AppManager auth] signInAnonymouslyWithCompletion:^(FIRAuthDataResult *_Nullable result,
NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in anonymously failed" error:error];
} else {
[self logSuccess:@"sign-in anonymously succeeded."];
[self log:[NSString stringWithFormat:@"User ID : %@", result.user.uid]];
[self passkeyEnroll];
}
}];

}

- (void)passkeyEnroll {
FIRUser *user = FIRAuth.auth.currentUser;
if (!user) {
[self logFailure:@"Please sign in first." error:nil];
return;
}
[self showTextInputPromptWithMessage:@"passkey name"
keyboardType:UIKeyboardTypeEmailAddress
completionBlock:^(BOOL userPressedOK, NSString *_Nullable passkeyName) {
if (@available(iOS 16.0, macOS 12.0, tvOS 16.0, *)) {
[user startPasskeyEnrollmentWithName:passkeyName completion:^(ASAuthorizationPlatformPublicKeyCredentialRegistrationRequest * _Nullable request, NSError * _Nullable error) {
if (request) {
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests: [NSMutableArray arrayWithObject:request]];
controller.delegate = self;
controller.presentationContextProvider = self;
[controller performRequests];
} else if (error) {
[self logFailure:@"Passkey enrollment failed" error:error];
}
}];
} else {
[self log:@"OS version is not supported for this action."];
}
}];

}

- (void)passkeySignIn {
if (@available(iOS 16.0, macOS 12.0, tvOS 16.0, *)) {
[[AppManager auth] startPasskeySignInWithCompletion:^(ASAuthorizationPlatformPublicKeyCredentialAssertionRequest * _Nullable request, NSError * _Nullable error) {
if (request) {
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests: [NSMutableArray arrayWithObject:request]];
controller.delegate = self;
controller.presentationContextProvider = self;
[controller performRequestsWithOptions:ASAuthorizationControllerRequestOptionPreferImmediatelyAvailableCredentials];
}
}];
} else {
[self log:@"OS version is not supported for this action."];
}

}

- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){

return self.view.window;
}

@end

NS_ASSUME_NONNULL_END
3 changes: 3 additions & 0 deletions FirebaseAuth/Tests/Sample/Sample/MainViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#import "UIViewController+Alerts.h"
#import "UserInfoViewController.h"
#import "UserTableViewCell.h"
#import "MainViewController+Passkey.h"

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -252,6 +253,8 @@ - (void)updateTable {
[weakSelf oobSection],
// Auto Tests
[weakSelf autoTestsSection],
// Passkey
[weakSelf passkeySection],
]];
}

Expand Down
15 changes: 15 additions & 0 deletions FirebaseAuth/Tests/Sample/Sample/UserInfoViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import "UserInfoViewController.h"

#import <FirebaseAuth/FIRUser.h>
#import <FirebaseAuth/FIRPasskeyInfo.h>
#import <FirebaseAuth/FIRUserInfo.h>
#import <FirebaseAuth/FIRUserMetadata.h>
#import "StaticContentTableViewManager.h"
Expand Down Expand Up @@ -74,6 +75,8 @@ - (void)loadTableView {
value:stringWithBool(_user.emailVerified)],
[StaticContentTableViewCell cellWithTitle:@"refresh token" value:_user.refreshToken],
[StaticContentTableViewCell cellWithTitle:@"multi factor" value:[self multiFactorString]],
[StaticContentTableViewCell cellWithTitle:@"passkeys" value:[self passkeysString]],

]]
] mutableCopy];
[sections addObject:[self sectionWithUserInfo:_user]];
Expand Down Expand Up @@ -108,4 +111,16 @@ - (NSString *)multiFactorString {
return string;
}

- (NSString *)passkeysString {
NSMutableString *string = [NSMutableString string];

for (FIRPasskeyInfo *info in _user.enrolledPasskeys) {
[string appendString:info.name];
[string appendString:@" - "];
[string appendString:info.credentialID];
}

return string;
}

@end

0 comments on commit 8f27717

Please sign in to comment.