integreat-io/integreat

View on GitHub
src/authenticators/token.ts

Summary

Maintainability
A
0 mins
Test Coverage
import type { Authenticator } from '../types.js'
import type { Authentication } from '../service/types.js'

interface TokenAuthentication extends Authentication {
  token?: string | null
  type?: string
  encode?: boolean
}

export interface TokenObject extends Record<string, unknown> {
  token?: string | null
  type?: string
}

export interface TokenHeaders extends Record<string, unknown> {
  Authorization?: string
}

const getTypeAndToken = (authentication: TokenAuthentication | null) => {
  const { status, token, type, encode } = authentication || {}
  if (status !== 'granted' || !token) {
    return {}
  }
  return {
    token: encode ? Buffer.from(token).toString('base64') : token,
    type,
  }
}

/**
 * The token strategy. The token is given as an option.
 */
const tokenAuth: Authenticator = {
  /**
   * Authenticate and return authentication object if authentication was
   * successful.
   * Would normaly perform an authentication request and set the token received,
   * but in the token strategy, we just set the token from the options object.
   */
  async authenticate(options) {
    const { token = null, type, encode = false } = options || {}
    return token
      ? { status: 'granted', token, type, encode }
      : { status: 'refused' }
  },

  /**
   * Check whether we've already ran authentication.
   * In the token strategy, this will be true if we get an authentication object
   * with granted status and a token.
   */
  isAuthenticated(authentication, _options, _action) {
    return !!(
      authentication &&
      authentication.status === 'granted' &&
      authentication.token
    )
  },

  authentication: {
    /**
     * Return an object with the information needed for authenticated requests
     * with this authenticator. The object will include `token` and `type` as
     * seperate properties. The token will be encoded when the `encode` option
     * is set true.
     */
    asObject(authentication: TokenAuthentication | null): TokenObject {
      return getTypeAndToken(authentication)
    },

    /**
     * Return a headers object with the headers needed for authenticated
     * requests with this authenticator. There will be only one property, namely
     * `Authorization`, which will consist of the type and the token, the latter
     * encoded if the `encode` option is true.
     */
    asHttpHeaders(authentication: TokenAuthentication | null): TokenHeaders {
      const { type, token } = getTypeAndToken(authentication)
      return token ? { Authorization: type ? `${type} ${token}` : token } : {}
    },
  },
}

export default tokenAuth