1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 05:30:01 +00:00

Add auth demo

This commit is contained in:
Bernd Schoolmann
2025-03-14 14:17:17 +01:00
parent 2c8754d7df
commit 3af12a2e15
6 changed files with 68 additions and 10 deletions

View File

@@ -230,6 +230,10 @@ export class ChangePasswordComponent
algorithm: "argon2id",
parameters: { memory: 256 * 1024, iterations: 3, parallelism: 4 },
});
await this.opaqueService.login(this.email, this.masterPassword, {
algorithm: "argon2id",
parameters: { memory: 256 * 1024, iterations: 3, parallelism: 4 },
});
await this.formPromise;
this.toastService.showToast({

View File

@@ -3,6 +3,9 @@ import { firstValueFrom } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { LoginFinishRequest } from "./models/login-finish.request";
import { LoginStartRequest } from "./models/login-start.request";
import { LoginStartResponse } from "./models/login-start.response";
import { RegistrationFinishRequest } from "./models/registration-finish.request";
import { RegistrationFinishResponse } from "./models/registration-finish.response";
import { RegistrationStartRequest } from "./models/registration-start.request";
@@ -43,10 +46,29 @@ export class DefaultOpaqueApiService implements OpaqueApiService {
return new RegistrationFinishResponse(response);
}
loginStart(): any {
throw new Error("Method not implemented");
async loginStart(request: LoginStartRequest): Promise<LoginStartResponse> {
const env = await firstValueFrom(this.environmentService.environment$);
const response = await this.apiService.send(
"POST",
`/opaque/start-login`,
request,
true,
true,
env.getApiUrl(),
);
return new LoginStartResponse(response);
}
loginFinish(): any {
throw new Error("Method not implemented");
async loginFinish(request: LoginFinishRequest): Promise<boolean> {
const env = await firstValueFrom(this.environmentService.environment$);
const response = await this.apiService.send(
"POST",
`/opaque/finish-login`,
request,
true,
true,
env.getApiUrl(),
);
return response.success;
}
}

View File

@@ -8,6 +8,8 @@ import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { UserKey } from "../../types/key";
import { CipherConfiguration, KsfConfig } from "./models/cipher-configuration";
import { LoginFinishRequest } from "./models/login-finish.request";
import { LoginStartRequest } from "./models/login-start.request";
import { RegistrationFinishRequest } from "./models/registration-finish.request";
import { RegistrationStartRequest } from "./models/registration-start.request";
import { OpaqueApiService } from "./opaque-api.service";
@@ -60,7 +62,32 @@ export class DefaultOpaqueService implements OpaqueService {
);
}
async login(masterPassword: string, ksfConfig: KsfConfig): Promise<Uint8Array> {
throw new Error("Method not implemented.");
async login(email: string, masterPassword: string, ksfConfig: KsfConfig): Promise<Uint8Array> {
const config = new CipherConfiguration(ksfConfig);
const cryptoClient = (await firstValueFrom(this.sdkService.client$)).crypto();
const loginStart = cryptoClient.opaque_login_start(masterPassword, config.toSdkConfig());
const loginStartResponse = await this.opaqueApiService.loginStart(
new LoginStartRequest(email, Utils.fromBufferToB64(loginStart.credential_request)),
);
const loginFinish = cryptoClient.opaque_login_finish(
masterPassword,
config.toSdkConfig(),
Utils.fromB64ToArray(loginStartResponse.credentialResponse),
loginStart.state,
);
const success = await this.opaqueApiService.loginFinish(
new LoginFinishRequest(
loginStartResponse.sessionId,
Utils.fromBufferToB64(loginFinish.credential_finalization),
),
);
if (!success) {
throw new Error("Login failed");
}
return loginFinish.export_key;
}
}

View File

@@ -1,7 +1,9 @@
import { OpaqueSessionId } from "@bitwarden/common/types/guid";
import { BaseResponse } from "../../../models/response/base.response";
export class LoginStartResponse extends BaseResponse {
sessionId: string;
sessionId: OpaqueSessionId;
credentialResponse: string;
constructor(response: any) {

View File

@@ -1,3 +1,6 @@
import { LoginFinishRequest } from "./models/login-finish.request";
import { LoginStartRequest } from "./models/login-start.request";
import { LoginStartResponse } from "./models/login-start.response";
import { RegistrationFinishRequest } from "./models/registration-finish.request";
import { RegistrationFinishResponse } from "./models/registration-finish.response";
import { RegistrationStartRequest } from "./models/registration-start.request";
@@ -8,6 +11,6 @@ export abstract class OpaqueApiService {
abstract registrationFinish(
request: RegistrationFinishRequest,
): Promise<RegistrationFinishResponse>;
abstract loginStart(): any;
abstract loginFinish(): any;
abstract loginStart(request: LoginStartRequest): Promise<LoginStartResponse>;
abstract loginFinish(request: LoginFinishRequest): Promise<boolean>;
}

View File

@@ -13,5 +13,5 @@ export abstract class OpaqueService {
* in combination with the rotateable keyset returned from the token endpoint.
* @returns The ExportKey obtained during the Opaque login flow.
*/
abstract login(masterPassword: string, ksfConfig: KsfConfig): Promise<Uint8Array>;
abstract login(email: string, masterPassword: string, ksfConfig: KsfConfig): Promise<Uint8Array>;
}