Skip to content

Remote: Authentication

Gabriel Holodak edited this page Aug 25, 2022 · 4 revisions

Authentication

authenticate(options: object) : Promise

In situations where there is not a proxy providing auth, the NextCapital client needs to authenticate against the API before it can be used. More details can be found in the Authentication, Proxies, and Environments document. When a proxy does provide auth, this method should not be used and will raise an error if called.

The Authenticate call primarily registers a onNeedsAuthentication callback. This callback should handle establishing a valid session, using one of the login methods (probably jwtLogin). This callback will be called both immediately and whenever the authentication is lost (eg: token expired).

Our API client is smart enough to call the registered onNeedsAuthentication if a request fails due to auth being lost. Once auth is restored, it will automatically retry the request.

This method can only be called once. Future attempts to call this method will reject. The token will be stored only in-memory, so auth will be lost after a page refresh. You'll need to manually handle any session storage for the token.

Interface

Inputs

  • onNeedsAuthentication (function) - required: Method called whenever the client needs to (re)establish an authenticated session. This method will not be called with any arguments and is expected to return a promise that resolves after a session has been established.
  • token (string) - optional: If there is a valid API token (eg: from session storage, as implemented in your app), the client will attempt to use it.

Return Value

This method will always return a promise. It will resolve if a session has been established, and reject otherwise.

Potential Errors

This method can reject for many reasons, including:

  • If the onNeedsAuthentication callback returns a rejected promise
  • If the auth server or API server is down
  • Attempting to call the method more than once

Example

import { waitForConfiguredClient } from '@nextcapital/client';

import { getJWT } from './example-code';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  await Authentication.authenticate({
    onNeedsAuthentication: () => getJWT().then((jwt) => Authentication.jwtLogin({ jwt }))
  });

  // should now have a valid session
}

hasAuthenticated() : boolean

Returns true if the authenticate call has occurred or if the PROXY access type is used. Notably, this can still return true if the authenticate call is still running. So, the hasSession should be used to check for an active session.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  if (Authentication.hasAuthenticated()) {
    console.log('authenticate call has occurred');
  } else {
    console.log('authenticate call has NOT occurred');
  }
}

hasSession() : boolean

Returns true if the authenticate call has completed (or the PROXY access type is used), and there is an active session.

Notably, this means that the session was active as of the most recent API call. If the session has expired in the meantime, this can incorrectly return true. However, on the next API request, we'll detect this and call onNeedsAuthentication.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  if (Authentication.hasSession()) {
    console.log('there is an active API session');
  } else {
    console.log('there is NO active API session');
  }
}

hasLostAuth() : boolean

Returns true if the authenticate call has occurred, but there is no active session. This is generally only possible while the authenticate call is still occurring, or after the onNeedsAuthentication callback fails to restore the session.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  if (Authentication.hasLostAuth()) {
    console.log('there is NO active API session');
  } else {
    console.log('there is an active API session');
  }
}

waitForAuthentication() : Promise

Returns a promise that will resolve once the authenticate call completed (if required). If the authenticate call rejects, so will this.

When the PROXY access type is used, the will resolve immediately after the configure call completes.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  await Authentication.waitForAuthentication();

  // client is now authenticated!
}

jwtLogin({ jwt: string }) : Promise

Logs in using a JWT. This should be used in production.

This method should only be called inside of onNeedsAuthentication. It will raise an error if authenticate has not been called.

If the PROXY access type is used, this method will raise an error. The client should never attempt to authenticate in this case.

Interface

Inputs

  • jwt (string) - required: A valid JSON Web Token

Return Value

This method will always return a promise that resolves once the login has occurred and the session is active.

Potential Errors

This method will reject if the JWT is not valid.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

import { getJWT } from './example-code';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  await Authentication.authenticate({
    onNeedsAuthentication: () => getJWT().then((jwt) => Authentication.jwtLogin({ jwt }))
  });

  // should now have a valid session
}

getLocalToken() : String|null

Returns the local token if it is set, otherwise returning null. The local here refers to the fact this this method will only return the token if the token is set by the client. If the token is handled by a proxy, this will return null.

The primary use case of this method is to expose the token so that the parent application can store it on sessionStorage and provide it as the token option to the authenticate call after a refresh.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();

  await Authentication.waitForAuthentication();

  const token = Authentication.getLocalToken();
  sessionStorage.setItem('nc-local-token', token);
}

setHeader(header: string, value: string) : void

Sets a header on all requests that will hit the apiEndpoint. This is useful if the apiEndpoint is hitting a proxy that will provide the auth headers, as a CSRF token will likely need to be provided on all requests in this case.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();
  Authentication.setHeader("CSRF_TOKEN", "my-token-here");
}

clearHeader(header: string) : void

Removes a header set with setHeader from all requests that will hit the apiEndpoint.

Example

import { waitForConfiguredClient } from '@nextcapital/client';

export async function example() {
  const { Authentication } = await waitForConfiguredClient();
  Authentication.clearHeader("CSRF_TOKEN");
}