|
|
@@ -3,10 +3,12 @@ import { HttpClient } from '@angular/common/http';
|
|
|
import { Router } from '@angular/router';
|
|
|
import { Observable } from 'rxjs';
|
|
|
import { AuthResponse, LoginPayload, RegisterPayload } from '../interfaces/interface';
|
|
|
+import { AuthenticationResponseJSON, RegistrationResponseJSON, startAuthentication, startRegistration } from '@simplewebauthn/browser';
|
|
|
+import { A11yModule } from '@angular/cdk/a11y';
|
|
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
|
export class AuthService {
|
|
|
- private readonly baseUrl = 'https://a654-124-13-232-72.ngrok-free.app';
|
|
|
+ private readonly baseUrl = 'https://b8c8-115-132-229-66.ngrok-free.app/api';
|
|
|
private readonly tokenKey = 'auth_token';
|
|
|
private userName!: string
|
|
|
|
|
|
@@ -22,6 +24,90 @@ export class AuthService {
|
|
|
return this.http.post<AuthResponse>(`${this.baseUrl}/auth/login`, payload);
|
|
|
}
|
|
|
|
|
|
+ async webauthnRegister(username: string, email: string): Promise<AuthResponse> {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+
|
|
|
+ const options = await this.http
|
|
|
+ .post<any>(`${this.baseUrl}/auth/webauthn-register-options`, { username })
|
|
|
+ .toPromise();
|
|
|
+
|
|
|
+ if (!options) {
|
|
|
+ throw new Error('Registration options not received from server');
|
|
|
+ }
|
|
|
+
|
|
|
+ const attestationResponse: RegistrationResponseJSON = await startRegistration({
|
|
|
+ optionsJSON: options,
|
|
|
+ });
|
|
|
+
|
|
|
+ const credentialJSON = {
|
|
|
+ id: attestationResponse.id,
|
|
|
+ rawId: attestationResponse.rawId,
|
|
|
+ type: attestationResponse.type,
|
|
|
+ response: {
|
|
|
+ attestationObject: attestationResponse.response.attestationObject,
|
|
|
+ clientDataJSON: attestationResponse.response.clientDataJSON,
|
|
|
+ },
|
|
|
+ clientExtensionResults: attestationResponse.clientExtensionResults,
|
|
|
+ authenticatorAttachment: attestationResponse.authenticatorAttachment,
|
|
|
+ email: email,
|
|
|
+ name: username
|
|
|
+ };
|
|
|
+
|
|
|
+ // POST to /webauthn/register
|
|
|
+ this.http.post<AuthResponse>(`${this.baseUrl}/auth/webauthn-register`, credentialJSON).toPromise().then(res => {
|
|
|
+ if (!res) {
|
|
|
+ reject(res)
|
|
|
+ } else {
|
|
|
+ // Optionally store token and username
|
|
|
+ this.storeToken(res.access_token);
|
|
|
+ this.setUserName(res.name);
|
|
|
+ resolve(res)
|
|
|
+ }
|
|
|
+ }).catch((err) => reject(err))
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ async webauthnLogin(email: string): Promise<AuthResponse> {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ try {
|
|
|
+ // 1. Get options from backend
|
|
|
+ const options = await this.http
|
|
|
+ .post<any>(`${this.baseUrl}/auth/webauthn-login-options`, { email })
|
|
|
+ .toPromise();
|
|
|
+
|
|
|
+ if (!options) {
|
|
|
+ throw new Error('Login options not received from server');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. Start authentication with browser/device
|
|
|
+ const assertionResponse: AuthenticationResponseJSON = await startAuthentication({
|
|
|
+ optionsJSON: options,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 3. Attach email so backend knows which user to validate against
|
|
|
+ const loginPayload = {
|
|
|
+ ...assertionResponse,
|
|
|
+ email,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 4. POST to backend and verify
|
|
|
+ const res = await this.http
|
|
|
+ .post<AuthResponse>(`${this.baseUrl}/auth/webauthn-login`, loginPayload)
|
|
|
+ .toPromise();
|
|
|
+
|
|
|
+ if (!res || !res.access_token) {
|
|
|
+ reject(new Error('Invalid login response'));
|
|
|
+ } else {
|
|
|
+ this.storeToken(res.access_token);
|
|
|
+ this.setUserName(res.name);
|
|
|
+ resolve(res);
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ reject(err);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
reportAttendance(url: string): Observable<AuthResponse> {
|
|
|
let payload = {
|
|
|
name: this.userName,
|
|
|
@@ -69,8 +155,6 @@ export class AuthService {
|
|
|
}
|
|
|
|
|
|
getServerUrl(): Observable<string> {
|
|
|
- return this.http.get(`${this.baseUrl}/server`, {
|
|
|
- responseType: 'text'
|
|
|
- });
|
|
|
+ return this.http.get(`${this.baseUrl}/auth/server`, { responseType: 'text' });
|
|
|
}
|
|
|
}
|