Skip to content

Commit

Permalink
[feat] add authenticate function
Browse files Browse the repository at this point in the history
  • Loading branch information
zetsuboii committed Jan 20, 2024
1 parent 2e83dc5 commit 27abd73
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 28 deletions.
51 changes: 47 additions & 4 deletions src/Passkey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class Passkey {
userName: string,
challenge: string,
options: Partial<CreateOptions> = {}
) {
): Promise<PasskeyRegistrationResult> {
if (!Passkey.isSupported) {
throw NotSupportedError;
}
Expand All @@ -92,7 +92,7 @@ export class Passkey {
}

/**
* Authenticates using an existing Passkey
* Authenticates using an existing Passkey and returns signature only
*
* @param credentialIds The credential IDs of the Passkey to authenticate with
* @param challenge The FIDO2 Challenge without formatting
Expand All @@ -104,7 +104,49 @@ export class Passkey {
credentialIds: Array<string>,
challenge: string,
options: Partial<SignOptions> = {}
) {
): Promise<string> {
if (!Passkey.isSupported) {
throw NotSupportedError;
}

const challengeBase64 = utils.toBase64(challenge);

const request = this.generateSignRequest(
credentialIds,
challengeBase64,
options
);

let authResponse: PasskeyAuthenticationResult;

if (Platform.OS === 'android') {
authResponse = await PasskeyAndroid.authenticate(request);
} else {
authResponse = await PasskeyiOS.authenticate(
request,
options.withSecurityKey ?? false
);
}

const base64Decoded = utils.fromBase64(authResponse.response.signature);
const { r, s } = utils.derToRs(base64Decoded);
return ['0x', r, s].join('');
}

/**
* Authenticates using an existing Passkey and returns full response
*
* @param credentialIds The credential IDs of the Passkey to authenticate with
* @param challenge The FIDO2 Challenge without formatting
* @options An object containing options for the authentication process
* @returns The FIDO2 Assertion Result in JSON format
* @throws
*/
public static async authenticate(
credentialIds: Array<string>,
challenge: string,
options: Partial<SignOptions> = {}
): Promise<PasskeyAuthenticationResult> {
if (!Passkey.isSupported) {
throw NotSupportedError;
}
Expand All @@ -119,8 +161,9 @@ export class Passkey {

if (Platform.OS === 'android') {
return PasskeyAndroid.authenticate(request);
} else {
return PasskeyiOS.authenticate(request, options.withSecurityKey ?? false);
}
return PasskeyiOS.authenticate(request, options.withSecurityKey ?? false);
}

/**
Expand Down
19 changes: 6 additions & 13 deletions src/__tests__/PasskeyAndroid.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
import { Platform, NativeModules } from 'react-native';
import { Passkey } from '../Passkey';

import AuthRequest from './testData/AuthRequest.json';
import RegRequest from './testData/RegRequest.json';

import AuthAndroidResult from './testData/AuthAndroidResult.json';
import RegAndroidResult from './testData/RegAndroidResult.json';

Expand All @@ -17,15 +14,15 @@ describe('Test Passkey Module', () => {
test('should return unsupported for Android Versions below 28', async () => {
(Platform as any).setVersion('26');

expect(await Passkey.isSupported()).toBeFalsy();
expect(Passkey.isSupported()).toBeFalsy();
});

test('should call native register method', async () => {
const registerSpy = jest
.spyOn(NativeModules.Passkey, 'register')
.spyOn(NativeModules.Passkey, 'create')
.mockResolvedValue(JSON.stringify(RegAndroidResult));

await Passkey.register(RegRequest);
await Passkey.create('zet', 'zet', 'zet');
expect(registerSpy).toHaveBeenCalled();
});

Expand All @@ -34,7 +31,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'authenticate')
.mockResolvedValue(JSON.stringify(AuthAndroidResult));

await Passkey.authenticate(AuthRequest);
await Passkey.sign(['zet'], 'zet');
expect(authSpy).toHaveBeenCalled();
});

Expand All @@ -43,9 +40,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'register')
.mockResolvedValue(JSON.stringify(RegAndroidResult));

await Passkey.register(RegRequest, {
withSecurityKey: true,
});
await Passkey.create('zet', 'zet', 'zet');
expect(registerSpy).toHaveBeenCalled();
});

Expand All @@ -54,9 +49,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'authenticate')
.mockResolvedValue(JSON.stringify(AuthAndroidResult));

await Passkey.authenticate(AuthRequest, {
withSecurityKey: true,
});
await Passkey.sign(['zet'], 'zet');
expect(authSpy).toHaveBeenCalled();
});
});
15 changes: 4 additions & 11 deletions src/__tests__/PasskeyiOS.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
import { Platform, NativeModules } from 'react-native';
import { Passkey } from '../Passkey';

import AuthRequest from './testData/AuthRequest.json';
import RegRequest from './testData/RegRequest.json';

import AuthiOSResult from './testData/AuthiOSResult.json';
import RegiOSResult from './testData/RegiOSResult.json';

Expand All @@ -25,7 +22,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'register')
.mockResolvedValue(RegiOSResult);

await Passkey.register(RegRequest);
await Passkey.create('zet', 'zet', 'zet');
expect(registerSpy).toHaveBeenCalled();
});

Expand All @@ -34,7 +31,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'authenticate')
.mockResolvedValue(AuthiOSResult);

await Passkey.authenticate(AuthRequest);
await Passkey.sign(['zet'], 'zet');
expect(authSpy).toHaveBeenCalled();
});

Expand All @@ -43,9 +40,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'register')
.mockResolvedValue(RegiOSResult);

await Passkey.register(RegRequest, {
withSecurityKey: true,
});
await Passkey.create('zet', 'zet', 'zet');
expect(registerSpy).toHaveBeenCalled();
});

Expand All @@ -54,9 +49,7 @@ describe('Test Passkey Module', () => {
.spyOn(NativeModules.Passkey, 'authenticate')
.mockResolvedValue(AuthiOSResult);

await Passkey.authenticate(AuthRequest, {
withSecurityKey: true,
});
await Passkey.sign(['zet'], 'zet');
expect(authSpy).toHaveBeenCalled();
});
});

0 comments on commit 27abd73

Please sign in to comment.