# CICADA

### File

`src/app/_services/auth.service.ts`

### Index

###### Properties

- mutableKeyStore
- trustedUsers
- Private trustedUsersList
- trustedUsersSubject

###### Methods

- addTrustedUser
- getChallenge
- getPrivateKey
- getPrivateKeyInfo
- Async getPublicKeys
- getSessionToken
- getTrustedUsers
- getWithToken
- Async init
- Async login
- loginView
- logout
- sendSignedChallenge
- Async setKey
- setSessionToken
- setState

### Constructor

`constructor(httpClient: HttpClient, loggingService: LoggingService, errorDialogService: ErrorDialogService)`
Defined in src/app/_services/auth.service.ts:23

Parameters :

Name | Type | Optional
httpClient | `HttpClient` | No
loggingService | `LoggingService` | No
errorDialogService | `ErrorDialogService` | No

### Methods

addTrustedUser
`addTrustedUser(user: Staff)`
Defined in src/app/_services/auth.service.ts:172

Parameters :

Name | Type | Optional
user | `Staff` | No

Returns : `void`

getChallenge
`getChallenge()`
Defined in src/app/_services/auth.service.ts:84
Returns : `Promise<any>`

getPrivateKey
`getPrivateKey()`
Defined in src/app/_services/auth.service.ts:202
Returns : `any`

getPrivateKeyInfo
`getPrivateKeyInfo()`
Defined in src/app/_services/auth.service.ts:206
Returns : `any`

Async getPublicKeys
`getPublicKeys()`
Defined in src/app/_services/auth.service.ts:190
Returns : `Promise<any>`

getSessionToken
`getSessionToken()`
Defined in src/app/_services/auth.service.ts:38
Returns : `string`

getTrustedUsers
`getTrustedUsers()`
Defined in src/app/_services/auth.service.ts:184
Returns : `void`

getWithToken
`getWithToken()`
Defined in src/app/_services/auth.service.ts:50
Returns : `Promise<boolean>`

Async init
`init()`
Defined in src/app/_services/auth.service.ts:31
Returns : `Promise<void>`

Async login
`login()`
Defined in src/app/_services/auth.service.ts:93
Returns : `Promise<boolean>`

loginView
`loginView()`
Defined in src/app/_services/auth.service.ts:128
Returns : `void`

logout
`logout()`
Defined in src/app/_services/auth.service.ts:166
Returns : `void`

sendSignedChallenge
`sendSignedChallenge(hobaResponseEncoded: any)`
Defined in src/app/_services/auth.service.ts:72

Parameters :

Name | Type | Optional
hobaResponseEncoded | `any` | No

Returns : `Promise<any>`

Async setKey
`setKey(privateKeyArmored)`
Defined in src/app/_services/auth.service.ts:138

Parameters :

Name | Optional | Description

privateKeyArmored

No

- Private key.

Returns : `Promise<boolean>`

setSessionToken
`setSessionToken(token)`
Defined in src/app/_services/auth.service.ts:42

Parameters :

Name | Optional
token | No

Returns : `void`

setState
`setState(s)`
Defined in src/app/_services/auth.service.ts:46

Parameters :

Name | Optional
s | No

Returns : `void`

### Properties

mutableKeyStore
Type : `MutableKeyStore`
Defined in src/app/_services/auth.service.ts:18

trustedUsers
Type : `Array<Staff>`
Default value : `[]`
Defined in src/app/_services/auth.service.ts:19

Private trustedUsersList
Type : `BehaviorSubject<Array<Staff>>`
Default value : `new BehaviorSubject<Array<Staff>>( this.trustedUsers )`
Defined in src/app/_services/auth.service.ts:20

trustedUsersSubject
Type : `Observable<Array<Staff>>`
Default value : `this.trustedUsersList.asObservable()`
Defined in src/app/_services/auth.service.ts:23

    import { Injectable } from '@angular/core';
    import { hobaParseChallengeHeader } from '@src/assets/js/hoba.js';
    import { signChallenge } from '@src/assets/js/hoba-pgp.js';
    import { environment } from '@src/environments/environment';
    import { LoggingService } from '@app/_services/logging.service';
    import { MutableKeyStore } from '@app/_pgp';
    import { ErrorDialogService } from '@app/_services/error-dialog.service';
    import { HttpClient } from '@angular/common/http';
    import { HttpError, rejectBody } from '@app/_helpers/global-error-handler';
    import { Staff } from '@app/_models';
    import { BehaviorSubject, Observable } from 'rxjs';
    import { KeystoreService } from '@app/_services/keystore.service';

    @Injectable({
      providedIn: 'root',
    })
    export class AuthService {
      mutableKeyStore: MutableKeyStore;
      trustedUsers: Array<Staff> = [];
      private trustedUsersList: BehaviorSubject<Array<Staff>> = new BehaviorSubject<Array<Staff>>(
        this.trustedUsers
      );
      trustedUsersSubject: Observable<Array<Staff>> = this.trustedUsersList.asObservable();

      constructor(
        private httpClient: HttpClient,
        private loggingService: LoggingService,
        private errorDialogService: ErrorDialogService
      ) {}

      async init(): Promise<void> {
        this.mutableKeyStore = await KeystoreService.getKeystore();
        if (localStorage.getItem(btoa('CICADA_PRIVATE_KEY'))) {
          await this.mutableKeyStore.importPrivateKey(localStorage.getItem(btoa('CICADA_PRIVATE_KEY')));
        }
      }

      getSessionToken(): string {
        return sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
      }

      setSessionToken(token): void {
        sessionStorage.setItem(btoa('CICADA_SESSION_TOKEN'), token);
      }

      setState(s): void {
        document.getElementById('state').innerHTML = s;
      }

      getWithToken(): Promise<boolean> {
        const headers = {
          Authorization: 'Bearer ' + this.getSessionToken,
          'Content-Type': 'application/json;charset=utf-8',
          'x-cic-automerge': 'none',
        };
        const options = {
          headers,
        };
        return fetch(environment.cicMetaUrl, options).then((response) => {
          if (!response.ok) {
            this.loggingService.sendErrorLevelMessage('failed to get with auth token.', this, {
              error: '',
            });

            return false;
          }
          return true;
        });
      }

      // TODO rename to send signed challenge and set session. Also separate these responsibilities
      sendSignedChallenge(hobaResponseEncoded: any): Promise<any> {
        const headers = {
          Authorization: 'HOBA ' + hobaResponseEncoded,
          'Content-Type': 'application/json;charset=utf-8',
          'x-cic-automerge': 'none',
        };
        const options = {
          headers,
        };
        return fetch(environment.cicMetaUrl, options);
      }

      getChallenge(): Promise<any> {
        return fetch(environment.cicMetaUrl).then((response) => {
          if (response.status === 401) {
            const authHeader: string = response.headers.get('WWW-Authenticate');
            return hobaParseChallengeHeader(authHeader);
          }
        });
      }

      async login(): Promise<boolean> {
        if (this.getSessionToken()) {
          sessionStorage.removeItem(btoa('CICADA_SESSION_TOKEN'));
        } else {
          const o = await this.getChallenge();

          const r = await signChallenge(
            o.challenge,
            o.realm,
            environment.cicMetaUrl,
            this.mutableKeyStore
          );

          const tokenResponse = await this.sendSignedChallenge(r).then((response) => {
            const token = response.headers.get('Token');
            if (token) {
              return token;
            }
            if (response.status === 401) {
              throw new HttpError('You are not authorized to use this system', response.status);
            }
            if (!response.ok) {
              throw new HttpError('Unknown error from authentication server', response.status);
            }
          });

          if (tokenResponse) {
            this.setSessionToken(tokenResponse);
            this.setState('Click button to log in');
            return true;
          }
          return false;
        }
      }

      loginView(): void {
        document.getElementById('one').style.display = 'none';
        document.getElementById('two').style.display = 'block';
        this.setState('Click button to log in with PGP key ' + this.mutableKeyStore.getPrivateKeyId());
      }

      /**
       * @throws
       * @param privateKeyArmored - Private key.
       */
      async setKey(privateKeyArmored): Promise<boolean> {
        try {
          const isValidKeyCheck = await this.mutableKeyStore.isValidKey(privateKeyArmored);
          if (!isValidKeyCheck) {
            throw Error('The private key is invalid');
          }
          // TODO leaving this out for now.
          // const isEncryptedKeyCheck = await this.mutableKeyStore.isEncryptedPrivateKey(privateKeyArmored);
          // if (!isEncryptedKeyCheck) {
          //   throw Error('The private key doesn\'t have a password!');
          // }
          const key = await this.mutableKeyStore.importPrivateKey(privateKeyArmored);
          localStorage.setItem(btoa('CICADA_PRIVATE_KEY'), privateKeyArmored);
        } catch (err) {
          this.loggingService.sendErrorLevelMessage(
            `Failed to set key: ${err.message || err.statusText}`,
            this,
            { error: err }
          );
          this.errorDialogService.openDialog({
            message: `Failed to set key: ${err.message || err.statusText}`,
          });
          return false;
        }
        this.loginView();
        return true;
      }

      logout(): void {
        sessionStorage.removeItem(btoa('CICADA_SESSION_TOKEN'));
        localStorage.removeItem(btoa('CICADA_PRIVATE_KEY'));
        window.location.reload();
      }

      addTrustedUser(user: Staff): void {
        const savedIndex = this.trustedUsers.findIndex((staff) => staff.userid === user.userid);
        if (savedIndex === 0) {
          return;
        }
        if (savedIndex > 0) {
          this.trustedUsers.splice(savedIndex, 1);
        }
        this.trustedUsers.unshift(user);
        this.trustedUsersList.next(this.trustedUsers);
      }

      getTrustedUsers(): void {
        this.mutableKeyStore.getPublicKeys().forEach((key) => {
          this.addTrustedUser(key.users[0].userId);
        });
      }

      async getPublicKeys(): Promise<any> {
        return new Promise((resolve, reject) => {
          fetch(environment.publicKeysUrl).then((res) => {
            if (!res.ok) {
              // TODO does angular recommend an error interface?
              return reject(rejectBody(res));
            }
            return resolve(res.text());
          });
        });
      }

      getPrivateKey(): any {
        return this.mutableKeyStore.getPrivateKey();
      }

      getPrivateKeyInfo(): any {
        return this.getPrivateKey().users[0].userId;
      }
    }

# result-matching ""

# No results matching ""