Skip to content

Commit

Permalink
Add login with menemonic
Browse files Browse the repository at this point in the history
  • Loading branch information
miladsoft committed Sep 14, 2024
1 parent 2b70059 commit 36e380c
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 33 deletions.
50 changes: 31 additions & 19 deletions src/app/components/auth/login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,10 @@
<div>Don't have an account?</div>
<a class="ml-1 text-primary-500 hover:underline" [routerLink]="['/register']">Register</a>
</div>
<!-- Alert -->
<angor-alert class="mt-8" [appearance]="'outline'" [showIcon]="false" [type]="'info'">
Privet key test = <strong>123</strong> <br>
Menemonic test = <strong>321</strong> <br>
</angor-alert>


<!-- Alert -->
<angor-alert *ngIf="showAlert" class="mt-8" [appearance]="'outline'" [showIcon]="false" [type]="alert.type"
[@shake]="alert.type === 'error'">
{{ alert.message }}
<angor-alert *ngIf="showSecAlert" class="mt-8" [appearance]="'outline'" [showIcon]="false" [type]="secAlert.type"
[@shake]="secAlert.type === 'error'">
{{ secAlert.message }}
</angor-alert>

<!-- Login form with Secret Key -->
Expand Down Expand Up @@ -74,7 +67,10 @@
<div class="mt-px flex-auto border-t"></div>
</div>


<angor-alert *ngIf="showMenemonicAlert" class="mt-8" [appearance]="'outline'" [showIcon]="false" [type]="menemonicAlert.type"
[@shake]="menemonicAlert.type === 'error'">
{{ menemonicAlert.message }}
</angor-alert>
<!-- Login form with Menemonic -->
<form class="mt-8" [formGroup]="MenemonicLoginForm" (ngSubmit)="loginWithMenemonic()">
<!-- Menemonic field -->
Expand All @@ -83,20 +79,35 @@
<input matInput formControlName="menemonic" autocomplete="menemonic" />
</mat-form-field>

<!-- Passphrase field -->
<mat-form-field class="w-full">
<mat-label>Passphrase (Optional)</mat-label>
<input matInput type="password" [formControlName]="'passphrase'" autocomplete="current-passphrase-menemonic"
#passphraseField />
<button mat-icon-button type="button" (click)="
passphraseField.type === 'password'
? (passphraseField.type = 'text')
: (passphraseField.type = 'password')
" matSuffix>
<mat-icon *ngIf="passphraseField.type === 'password'" class="icon-size-5" [svgIcon]="'heroicons_solid:eye'"></mat-icon>
<mat-icon *ngIf="passphraseField.type === 'text'" class="icon-size-5" [svgIcon]="'heroicons_solid:eye-slash'"></mat-icon>
</button>
<mat-error *ngIf="MenemonicLoginForm.get('passphrase').hasError('required')"> Passphrase is required
</mat-error>
</mat-form-field>

<!-- Password field -->
<mat-form-field class="w-full">
<mat-label>Password</mat-label>
<input matInput type="password" [formControlName]="'password'" autocomplete="current-password-menemonic"
#menemonicPasswordField />
<button mat-icon-button type="button" (click)="
menemonicPasswordField.type === 'password'
? (menemonicPasswordField.type = 'text')
: (menemonicPasswordField.type = 'password')
" matSuffix>
<mat-icon *ngIf="menemonicPasswordField.type === 'password'" class="icon-size-5"
[svgIcon]="'heroicons_solid:eye'"></mat-icon>
<mat-icon *ngIf="menemonicPasswordField.type === 'text'" class="icon-size-5"
[svgIcon]="'heroicons_solid:eye-slash'"></mat-icon>
menemonicPasswordField.type === 'password'
? (menemonicPasswordField.type = 'text')
: (menemonicPasswordField.type = 'password')
" matSuffix>
<mat-icon *ngIf="menemonicPasswordField.type === 'password'" class="icon-size-5" [svgIcon]="'heroicons_solid:eye'"></mat-icon>
<mat-icon *ngIf="menemonicPasswordField.type === 'text'" class="icon-size-5" [svgIcon]="'heroicons_solid:eye-slash'"></mat-icon>
</button>
<mat-error *ngIf="MenemonicLoginForm.get('password').hasError('required')"> Password is required
</mat-error>
Expand All @@ -112,6 +123,7 @@




<div *ngIf="isInstalledExtension">
<!-- Separator -->
<div class="mt-8 flex items-center">
Expand Down
31 changes: 19 additions & 12 deletions src/app/components/auth/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,19 @@ import { SignerService } from 'app/services/signer.service';
export class LoginComponent implements OnInit {
SecretKeyLoginForm: FormGroup;
MenemonicLoginForm: FormGroup;
alert = { type: 'error', message: '' };
showAlert = false;
secAlert = { type: 'error', message: '' };
showSecAlert = false;

menemonicAlert = { type: 'error', message: '' };
showMenemonicAlert = false;

loading = false;
isInstalledExtension = false;
privateKey: Uint8Array = new Uint8Array();
publicKey: string = "";
npub: string = "";
nsec: string = "";

constructor(
private _formBuilder: FormBuilder,
private _router: Router,
Expand All @@ -59,6 +64,7 @@ export class LoginComponent implements OnInit {

this.MenemonicLoginForm = this._formBuilder.group({
menemonic: ['', [Validators.required, Validators.minLength(3)]],
passphrase: [''], // Passphrase is optional
password: ['', Validators.required]
});
}
Expand All @@ -82,16 +88,16 @@ export class LoginComponent implements OnInit {
const password = this.SecretKeyLoginForm.get('password')?.value;

this.loading = true;
this.showAlert = false;
this.showSecAlert = false;

this._signerService.saveSecretKeyToSession(secretKey);
const success = this._signerService.handleLoginWithNsec(secretKey);

if (this._signerService.getPublicKey()) {
if (success) {
this._router.navigateByUrl('/home');
} else {
this.loading = false;
this.alert.message = 'Secret key is missing or invalid.';
this.showAlert = true;
this.secAlert.message = 'Secret key is missing or invalid.';
this.showSecAlert = true;
}
}

Expand All @@ -101,19 +107,20 @@ export class LoginComponent implements OnInit {
}

const menemonic = this.MenemonicLoginForm.get('menemonic')?.value;
const passphrase = this.MenemonicLoginForm.get('passphrase')?.value || ''; // Optional passphrase
const password = this.MenemonicLoginForm.get('password')?.value;

this.loading = true;
this.showAlert = false;
this.showMenemonicAlert = false;

this._signerService.saveSecretKeyToSession(menemonic);
const success = this._signerService.handleLoginWithMenemonic(menemonic, passphrase);

if (this._signerService.getPublicKey()) {
if (success) {
this._router.navigateByUrl('/home');
} else {
this.loading = false;
this.alert.message = 'Menemonic is missing or invalid.';
this.showAlert = true;
this.menemonicAlert.message = 'Menemonic is missing or invalid.';
this.showMenemonicAlert = true;
}
}

Expand Down
43 changes: 41 additions & 2 deletions src/app/services/signer.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Injectable } from '@angular/core';
import { UnsignedEvent, nip19, getPublicKey, nip04, Event } from 'nostr-tools';
import { Buffer } from 'buffer';
import { privateKeyFromSeedWords, accountFromSeedWords } from 'nostr-tools/nip06';


@Injectable({
Expand Down Expand Up @@ -183,8 +184,6 @@ export class SignerService {
localStorage.setItem("following", newFollowingList);
}



savePublicKeyToSession(publicKey: string): void {
const npub = nip19.npubEncode(publicKey);
window.localStorage.setItem(this.localStoragePublicKeyName, publicKey);
Expand Down Expand Up @@ -252,6 +251,46 @@ export class SignerService {





handleLoginWithMenemonic(mnemonic: string, passphrase: string = ''): boolean {
try {
// Index of the account (default to 0)
const accountIndex = 0;

// Generate private key (as a string) and public key from mnemonic and passphrase
const privateKey = privateKeyFromSeedWords(mnemonic, passphrase, accountIndex);

// Convert privateKey (hex string) to Uint8Array
const privateKeyUint8Array = Uint8Array.from(Buffer.from(privateKey, 'hex'));

// Generate the public key from the private key (Uint8Array)
const publicKey = getPublicKey(privateKeyUint8Array);

// Encode public key as npub and private key as nsec
const npub = nip19.npubEncode(publicKey);
const nsec = nip19.nsecEncode(privateKeyUint8Array);

// Save keys to session/localStorage
this.saveSecretKeyToSession(privateKey); // Save private key as hex (string)
this.savePublicKeyToSession(publicKey); // Save public key and npub
window.localStorage.setItem('nsec', nsec); // Save nsec to localStorage

console.log("Login with mnemonic successful!");
console.log("Public Key:", publicKey);
console.log("Private Key (hex):", privateKey);
console.log("npub:", npub);
console.log("nsec:", nsec);

return true;
} catch (error) {
console.error("Error during login with mnemonic:", error);
return false;
}
}



usingNostrBrowserExtension() {
if (this.usingSecretKey()) {
return false;
Expand Down

0 comments on commit 36e380c

Please sign in to comment.