Feature/upgrade simplewebauthn dependencies to version 4.1.0 (#365)
* Upgrade @simplewebauthn dependencies to version 4.1.0 * @simplewebauthn/browser * @simplewebauthn/server * Update changelog
This commit is contained in:
parent
39f315aba0
commit
5ea455b98b
@ -12,6 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Added the annualized performance to the portfolio summary tab on the home page
|
||||
- Added the Ghostfolio Slack channel to the about page
|
||||
|
||||
### Changed
|
||||
|
||||
- Upgraded `@simplewebauthn/browser` and `@simplewebauthn/server` from version `3.0.0` to `4.1.0`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the sign in with fingerprint for some android devices
|
||||
|
||||
## 1.51.0 - 11.09.2021
|
||||
|
||||
### Changed
|
||||
|
@ -62,10 +62,10 @@ export class AuthController {
|
||||
}
|
||||
}
|
||||
|
||||
@Get('webauthn/generate-attestation-options')
|
||||
@Get('webauthn/generate-registration-options')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
public async generateAttestationOptions() {
|
||||
return this.webAuthService.generateAttestationOptions();
|
||||
public async generateRegistrationOptions() {
|
||||
return this.webAuthService.generateRegistrationOptions();
|
||||
}
|
||||
|
||||
@Post('webauthn/verify-attestation')
|
||||
|
@ -11,16 +11,16 @@ import {
|
||||
import { REQUEST } from '@nestjs/core';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import {
|
||||
GenerateAssertionOptionsOpts,
|
||||
GenerateAttestationOptionsOpts,
|
||||
VerifiedAssertion,
|
||||
VerifiedAttestation,
|
||||
VerifyAssertionResponseOpts,
|
||||
VerifyAttestationResponseOpts,
|
||||
generateAssertionOptions,
|
||||
generateAttestationOptions,
|
||||
verifyAssertionResponse,
|
||||
verifyAttestationResponse
|
||||
GenerateAuthenticationOptionsOpts,
|
||||
GenerateRegistrationOptionsOpts,
|
||||
VerifiedAuthenticationResponse,
|
||||
VerifiedRegistrationResponse,
|
||||
VerifyAuthenticationResponseOpts,
|
||||
VerifyRegistrationResponseOpts,
|
||||
generateAuthenticationOptions,
|
||||
generateRegistrationOptions,
|
||||
verifyAuthenticationResponse,
|
||||
verifyRegistrationResponse
|
||||
} from '@simplewebauthn/server';
|
||||
|
||||
import {
|
||||
@ -46,10 +46,10 @@ export class WebAuthService {
|
||||
return this.configurationService.get('ROOT_URL');
|
||||
}
|
||||
|
||||
public async generateAttestationOptions() {
|
||||
public async generateRegistrationOptions() {
|
||||
const user = this.request.user;
|
||||
|
||||
const opts: GenerateAttestationOptionsOpts = {
|
||||
const opts: GenerateRegistrationOptionsOpts = {
|
||||
rpName: 'Ghostfolio',
|
||||
rpID: this.rpID,
|
||||
userID: user.id,
|
||||
@ -63,7 +63,7 @@ export class WebAuthService {
|
||||
}
|
||||
};
|
||||
|
||||
const options = generateAttestationOptions(opts);
|
||||
const options = generateRegistrationOptions(opts);
|
||||
|
||||
await this.userService.updateUser({
|
||||
data: {
|
||||
@ -84,27 +84,27 @@ export class WebAuthService {
|
||||
const user = this.request.user;
|
||||
const expectedChallenge = user.authChallenge;
|
||||
|
||||
let verification: VerifiedAttestation;
|
||||
let verification: VerifiedRegistrationResponse;
|
||||
try {
|
||||
const opts: VerifyAttestationResponseOpts = {
|
||||
const opts: VerifyRegistrationResponseOpts = {
|
||||
credential,
|
||||
expectedChallenge,
|
||||
expectedOrigin: this.expectedOrigin,
|
||||
expectedRPID: this.rpID
|
||||
};
|
||||
verification = await verifyAttestationResponse(opts);
|
||||
verification = await verifyRegistrationResponse(opts);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new InternalServerErrorException(error.message);
|
||||
}
|
||||
|
||||
const { verified, attestationInfo } = verification;
|
||||
const { registrationInfo, verified } = verification;
|
||||
|
||||
const devices = await this.deviceService.authDevices({
|
||||
where: { userId: user.id }
|
||||
});
|
||||
if (verified && attestationInfo) {
|
||||
const { credentialPublicKey, credentialID, counter } = attestationInfo;
|
||||
if (registrationInfo && verified) {
|
||||
const { counter, credentialID, credentialPublicKey } = registrationInfo;
|
||||
|
||||
let existingDevice = devices.find(
|
||||
(device) => device.credentialId === credentialID
|
||||
@ -115,9 +115,9 @@ export class WebAuthService {
|
||||
* Add the returned device to the user's list of devices
|
||||
*/
|
||||
existingDevice = await this.deviceService.createAuthDevice({
|
||||
counter,
|
||||
credentialPublicKey,
|
||||
credentialId: credentialID,
|
||||
counter,
|
||||
User: { connect: { id: user.id } }
|
||||
});
|
||||
}
|
||||
@ -138,20 +138,20 @@ export class WebAuthService {
|
||||
throw new Error('Device not found');
|
||||
}
|
||||
|
||||
const opts: GenerateAssertionOptionsOpts = {
|
||||
timeout: 60000,
|
||||
const opts: GenerateAuthenticationOptionsOpts = {
|
||||
allowCredentials: [
|
||||
{
|
||||
id: device.credentialId,
|
||||
type: 'public-key',
|
||||
transports: ['internal']
|
||||
transports: ['internal'],
|
||||
type: 'public-key'
|
||||
}
|
||||
],
|
||||
userVerification: 'preferred',
|
||||
rpID: this.rpID
|
||||
rpID: this.rpID,
|
||||
timeout: 60000,
|
||||
userVerification: 'preferred'
|
||||
};
|
||||
|
||||
const options = generateAssertionOptions(opts);
|
||||
const options = generateAuthenticationOptions(opts);
|
||||
|
||||
await this.userService.updateUser({
|
||||
data: {
|
||||
@ -177,29 +177,29 @@ export class WebAuthService {
|
||||
|
||||
const user = await this.userService.user({ id: device.userId });
|
||||
|
||||
let verification: VerifiedAssertion;
|
||||
let verification: VerifiedAuthenticationResponse;
|
||||
try {
|
||||
const opts: VerifyAssertionResponseOpts = {
|
||||
const opts: VerifyAuthenticationResponseOpts = {
|
||||
credential,
|
||||
expectedChallenge: `${user.authChallenge}`,
|
||||
expectedOrigin: this.expectedOrigin,
|
||||
expectedRPID: this.rpID,
|
||||
authenticator: {
|
||||
credentialID: device.credentialId,
|
||||
credentialPublicKey: device.credentialPublicKey,
|
||||
counter: device.counter
|
||||
}
|
||||
},
|
||||
expectedChallenge: `${user.authChallenge}`,
|
||||
expectedOrigin: this.expectedOrigin,
|
||||
expectedRPID: this.rpID
|
||||
};
|
||||
verification = verifyAssertionResponse(opts);
|
||||
verification = verifyAuthenticationResponse(opts);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new InternalServerErrorException({ error: error.message });
|
||||
}
|
||||
|
||||
const { verified, assertionInfo } = verification;
|
||||
const { verified, authenticationInfo } = verification;
|
||||
|
||||
if (verified) {
|
||||
device.counter = assertionInfo.newCounter;
|
||||
device.counter = authenticationInfo.newCounter;
|
||||
|
||||
await this.deviceService.updateAuthDevice({
|
||||
data: device,
|
||||
|
@ -2,8 +2,8 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { GfLogoModule } from '@ghostfolio/ui/logo';
|
||||
import { WebauthnPageComponent } from '@ghostfolio/client/pages/webauthn/webauthn-page.component';
|
||||
import { GfLogoModule } from '@ghostfolio/ui/logo';
|
||||
|
||||
import { WebauthnPageRoutingModule } from './webauthn-page-routing.module';
|
||||
|
||||
|
@ -6,7 +6,10 @@ import {
|
||||
PublicKeyCredentialRequestOptionsJSON
|
||||
} from '@ghostfolio/api/app/auth/interfaces/simplewebauthn';
|
||||
import { SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service';
|
||||
import { startAssertion, startAttestation } from '@simplewebauthn/browser';
|
||||
import {
|
||||
startAuthentication,
|
||||
startRegistration
|
||||
} from '@simplewebauthn/browser';
|
||||
import { of } from 'rxjs';
|
||||
import { catchError, switchMap, tap } from 'rxjs/operators';
|
||||
|
||||
@ -32,7 +35,7 @@ export class WebAuthnService {
|
||||
public register() {
|
||||
return this.http
|
||||
.get<PublicKeyCredentialCreationOptionsJSON>(
|
||||
`/api/auth/webauthn/generate-attestation-options`,
|
||||
`/api/auth/webauthn/generate-registration-options`,
|
||||
{}
|
||||
)
|
||||
.pipe(
|
||||
@ -41,7 +44,7 @@ export class WebAuthnService {
|
||||
return of(null);
|
||||
}),
|
||||
switchMap((attOps) => {
|
||||
return startAttestation(attOps);
|
||||
return startRegistration(attOps);
|
||||
}),
|
||||
switchMap((attResp) => {
|
||||
return this.http.post<AuthDeviceDto>(
|
||||
@ -83,7 +86,7 @@ export class WebAuthnService {
|
||||
{ deviceId }
|
||||
)
|
||||
.pipe(
|
||||
switchMap(startAssertion),
|
||||
switchMap(startAuthentication),
|
||||
switchMap((assertionResponse) => {
|
||||
return this.http.post<{ authToken: string }>(
|
||||
`/api/auth/webauthn/verify-assertion`,
|
||||
|
@ -68,9 +68,9 @@
|
||||
"@nestjs/serve-static": "2.1.4",
|
||||
"@nrwl/angular": "12.8.0",
|
||||
"@prisma/client": "2.30.2",
|
||||
"@simplewebauthn/browser": "3.0.0",
|
||||
"@simplewebauthn/server": "3.0.0",
|
||||
"@simplewebauthn/typescript-types": "3.0.0",
|
||||
"@simplewebauthn/browser": "4.1.0",
|
||||
"@simplewebauthn/server": "4.1.0",
|
||||
"@simplewebauthn/typescript-types": "4.0.0",
|
||||
"@stripe/stripe-js": "1.15.0",
|
||||
"alphavantage": "2.2.0",
|
||||
"angular-material-css-vars": "2.1.2",
|
||||
|
42
yarn.lock
42
yarn.lock
@ -2519,7 +2519,7 @@
|
||||
consola "^2.15.0"
|
||||
node-fetch "^2.6.1"
|
||||
|
||||
"@peculiar/asn1-android@^2.0.26":
|
||||
"@peculiar/asn1-android@^2.0.38":
|
||||
version "2.0.38"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/asn1-android/-/asn1-android-2.0.38.tgz#193281f5a232e323d6f2c069c7a8e8e8f4a994bd"
|
||||
integrity sha512-krWyggV6FgYf3fEPKVNjHVecLcQWlAu3/YhOyN+/L43dNKcsmqiEvuhqplh3aiXF62Ds0pqzqttWmdvoVqmSVQ==
|
||||
@ -2528,7 +2528,7 @@
|
||||
asn1js "^2.1.1"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@peculiar/asn1-schema@^2.0.26", "@peculiar/asn1-schema@^2.0.38":
|
||||
"@peculiar/asn1-schema@^2.0.38":
|
||||
version "2.0.38"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.0.38.tgz#98b6f12daad275ecd6774dfe31fb62f362900412"
|
||||
integrity sha512-zZ64UpCTm9me15nuCpPgJghSdbEm8atcDQPCyK+bKXjZAQ1735NCZXCSCfbckbQ4MH36Rm9403n/qMq77LFDzQ==
|
||||
@ -2538,7 +2538,7 @@
|
||||
pvtsutils "^1.2.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@peculiar/asn1-x509@^2.0.26":
|
||||
"@peculiar/asn1-x509@^2.0.38":
|
||||
version "2.0.38"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/asn1-x509/-/asn1-x509-2.0.38.tgz#7ff3b5478d9c3784f0eb2fbe7693509da9de0a43"
|
||||
integrity sha512-10aK9fSxlc1DK9nEcwh+WPFNhAheXSE9RbI5MyS7FdBhgq+Mz4Z9JqFfaBZm1Qp+5mPtUMOP6cXVo7aaYlgq7A==
|
||||
@ -2613,32 +2613,32 @@
|
||||
"@angular-devkit/schematics" "12.1.4"
|
||||
jsonc-parser "3.0.0"
|
||||
|
||||
"@simplewebauthn/browser@3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@simplewebauthn/browser/-/browser-3.0.0.tgz#3d76b199c9f474408a7ed75d86004423dd6ae38a"
|
||||
integrity sha512-P661gZX/QW0Rg2NRAMtW84Q3u4nhXkPef9LLU4btLJFYoXO8RBFfxcmyqwyf2QEb4B7+lFdp5EWfZV5T7FvuHw==
|
||||
"@simplewebauthn/browser@4.1.0":
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@simplewebauthn/browser/-/browser-4.1.0.tgz#3e7fd66729405d6a2a2a187c93577b90a8e41786"
|
||||
integrity sha512-tIsEfShC1rrqrsNb44tOFuSriAFCz4tkdDnCjHfn2rYxgz+t+yqEvuIRfJHQpFrWSnZPdsjrAHtasj6lzfGI6w==
|
||||
|
||||
"@simplewebauthn/server@3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@simplewebauthn/server/-/server-3.0.0.tgz#eb1a5bbe2ecdda54363b178f4bb3e134f25641f0"
|
||||
integrity sha512-ymGX2obBrhY9R3OxrpCYaNGAovFHmMlQrGoNdVOe2R2JUBXC1Rg5JEUl1lGyaRykN1SyZqLgz86wAjDVuRITTA==
|
||||
"@simplewebauthn/server@4.1.0":
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@simplewebauthn/server/-/server-4.1.0.tgz#9ad2e32cffa83833ff8a633775b2ace5e6926fa0"
|
||||
integrity sha512-52X5/U+5Fo0XYG1TuBBGgG0ap9c0ffpeq0GZfFio/DZDW4He0Arb7Q/XkHw96JK0X1sfRKNmnfC+NImplvIimA==
|
||||
dependencies:
|
||||
"@peculiar/asn1-android" "^2.0.26"
|
||||
"@peculiar/asn1-schema" "^2.0.26"
|
||||
"@peculiar/asn1-x509" "^2.0.26"
|
||||
"@simplewebauthn/typescript-types" "^3.0.0"
|
||||
"@peculiar/asn1-android" "^2.0.38"
|
||||
"@peculiar/asn1-schema" "^2.0.38"
|
||||
"@peculiar/asn1-x509" "^2.0.38"
|
||||
"@simplewebauthn/typescript-types" "^4.0.0"
|
||||
base64url "^3.0.1"
|
||||
cbor "^5.1.0"
|
||||
elliptic "^6.5.3"
|
||||
jsrsasign "^10.2.0"
|
||||
jsrsasign "^10.4.0"
|
||||
jwk-to-pem "^2.0.4"
|
||||
node-fetch "^2.6.0"
|
||||
node-rsa "^1.1.1"
|
||||
|
||||
"@simplewebauthn/typescript-types@3.0.0", "@simplewebauthn/typescript-types@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@simplewebauthn/typescript-types/-/typescript-types-3.0.0.tgz#6712e9619d860f54f571cd27dbe167b2d9e5ab87"
|
||||
integrity sha512-bsk3EQWzPOZwP9C+ETVhcFDpZywY5sTqmNuGkNm3aNpc9Xh/mqZjy8nL0Sm7xwrlhY0zWAlOaIWQ3LvN5SoFhg==
|
||||
"@simplewebauthn/typescript-types@4.0.0", "@simplewebauthn/typescript-types@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@simplewebauthn/typescript-types/-/typescript-types-4.0.0.tgz#46ae4e69cb07305c57093a3ed99555437dfe0d49"
|
||||
integrity sha512-jqQ0bCeBO96CytB397vSrQ8ipozQzAmI57izA7izyglyu35JBV90I7+75fSX+ZGNHmMwDNnA3EGYtBLOIpkJEg==
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.8.3"
|
||||
@ -11343,7 +11343,7 @@ jsprim@^1.2.2:
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
jsrsasign@^10.2.0:
|
||||
jsrsasign@^10.4.0:
|
||||
version "10.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-10.4.0.tgz#362cc787079c03a363a958c03eb68d8545ba92f7"
|
||||
integrity sha512-C8qLhiAssh/b74KJpGhWuFGG9cFhJqMCVuuHXRibb3Z5vPuAW0ue0jUirpoExCdpdhv4nD3sZ1DAwJURYJTm9g==
|
||||
|
Loading…
x
Reference in New Issue
Block a user