<!-- This file was generated by @travetto/doc and should not be modified directly -->
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/auth/DOC.tsx and execute "npx trv doc" to rebuild -->
# Authentication

## Authentication scaffolding for the Travetto framework

**Install: @travetto/auth**
```bash
npm install @travetto/auth

# or

yarn add @travetto/auth
```

This module provides the high-level backdrop for managing security principals.  The goal of this module is to be a centralized location for various security frameworks to plug into.  The primary contributions are:
   *  Standard Types
   *  Authentication Contract
   *  Authorization Contract
   *  Authorization Services
   *  Authorization Context

## Standard Types
The module's goal is to be as flexible as possible.  To that end, the primary contract that this module defines, is that of the [Principal](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L7).

**Code: Principal**
```typescript
export interface Principal<D = AnyMap> {
  /**
   * Primary identifier for a user
   */
  readonly id: string;
  /**
   * Unique identifier for the principal's lifecycle
   */
  readonly sessionId?: string;
  /**
   * Date of expiration
   */
  expiresAt?: Date;
  /**
   * Date of issuance
   */
  issuedAt?: Date;
  /**
   * The source of the issuance
   */
  readonly issuer?: string;
  /**
   * Supplemental details
   */
  readonly details: D;
  /**
   * List of all provided permissions
   */
  readonly permissions?: string[];
}
```

As referenced above, a [Principal](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L7) is defined as a user with respect to a security context. This can be information the application knows about the user (authorized) or what a separate service may know about a user (3rd-party authentication).

## Authentication Contract

**Code: Authenticator**
```typescript
export interface Authenticator<T = unknown, C = unknown, P extends Principal = Principal> {
  /**
   * Retrieve the authenticator state for the given request
   */
  getState?(context?: C): Promise<AuthenticatorState | undefined> | AuthenticatorState | undefined;

  /**
   * Verify the payload, ensuring the payload is correctly identified.
   *
   * @returns Valid principal if authenticated
   * @returns undefined if authentication is valid, but incomplete (multi-step)
   * @throws AppError if authentication fails
   */
  authenticate(payload: T, context?: C): Promise<P | undefined> | P | undefined;
}
```

The [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L9) only requires one method to be defined, and that is `authenticate`. This method receives a generic payload, and a supplemental context as an input. The interface is responsible for converting that to an authenticated principal.

## Authorization Contract

**Code: Authorizer**
```typescript
export interface Authorizer<P extends Principal = Principal> {
  /**
   * Authorize inbound principal, verifying it's permission to access the system.
   * @returns New principal that conforms to the required principal shape
   */
  authorize(principal: P): Promise<P> | P;
}
```

Authorizers are generally seen as a secondary step post-authentication. Authentication acts as a very basic form of authorization, assuming the principal store is owned by the application. 

The [Authorizer](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) only requires one method to be defined, and that is `authorize`. This method receives an authenticated principal as an input, and is responsible for converting that to an authorized principal.

### Example
The [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") extension is a good example of an authenticator. This is a common use case for simple internal auth. 

Overall, the structure is simple, but drives home the primary use cases of the framework. The goals are:
   *  Be able to identify a user uniquely
   *  To have a reference to a user's set of permissions
   *  To have access to the principal

## Authorization Services

**Code: Authorization Service**
```typescript
export class AuthService {
  @Inject()
  /**
   * Get authenticators by keys
   */
  async getAuthenticators<T = unknown, C = unknown>(keys: symbol[]): Promise<Authenticator<T, C>[]>;
  /**
   * Authenticate. Supports multi-step login.
   * @param ctx The authenticator context
   * @param authenticators List of valid authentication sources
   */
  async authenticate<T, C>(payload: T, context: C, authenticators: symbol[]): Promise<Principal | undefined>;
  /**
   * Manage expiry state, renewing if allowed
   */
  manageExpiry(principal?: Principal): void;
  /**
   * Enforce expiry, invalidating the principal if expired
   */
  enforceExpiry(principal?: Principal): Principal | undefined;
}
```

The [AuthService](https://github.com/travetto/travetto/tree/main/module/auth/src/service.ts#L13) operates as the owner of the current auth state for a given "request". "Request" here implies a set of operations over a period of time, with the http request/response model being an easy point of reference.  This could also tie to a CLI operation, or any other invocation that requires some concept of authentication and authorization. 

The service allows for storing and retrieving the active [Principal](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L7), and/or the actively persisted auth token.  This is extremely useful for other parts of the framework that may request authenticated information (if available).  [Web Auth](https://github.com/travetto/travetto/tree/main/module/auth-web#readme "Web authentication integration support for the Travetto framework") makes heavy use of this state for enforcing endpoints when authentication is required. 

### Login
"Logging in" can be thought of going through the action of finding a single source that can authenticate the identity for the request credentials.  Some times there may be more than one valid source of authentication that you want to leverage, and the first one to authenticate wins. The [AuthService](https://github.com/travetto/travetto/tree/main/module/auth/src/service.ts#L13) operates in this fashion, in which a set of credentials and potential [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L9)s are submitted, and the service will attempt to authenticate.  

Upon successful authentication, an optional [Authorizer](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) may be invoked to authorize the authenticated user.  The [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L9) is assumed to be only one within the system, and should be tied to the specific product you are building for.  The [Authorizer](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) should be assumed to have multiple sources, and are generally specific to external third parties.  All of these values are collected via the [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support.") module and will be auto-registered on startup. 

If this process is too cumbersome or restrictive, manually authenticating and authorizing is still more than permissible, and setting the principal within the service is a logical equivalent to login.

## Authorization Context
When working with framework's authentication, the authenticated information is exposed via the [AuthContext](https://github.com/travetto/travetto/tree/main/module/auth/src/context.ts#L14), object. 

**Code: Auth Context Outline**
```typescript
export class AuthContext {
  @Inject()
  /**
   * Set principal
   */
  set principal(value: Principal | undefined);
  /**
   * Get the authentication token, if it exists
   */
  get authToken(): AuthToken | undefined;
  /**
   * Set/overwrite the user's authentication token
   */
  set authToken(token: AuthToken | undefined);
  /**
   * Get the authenticator state, if it exists
   */
  get authenticatorState(): AuthenticatorState | undefined;
  /**
   * Set/overwrite the authenticator state
   */
  set authenticatorState(state: AuthenticatorState | undefined);
  /**
   * Clear context
   */
  async clear(): Promise<void>;
}
```
