Authentication

The Source API authenticates requests in a number of different ways, depending on your needs. This page outlines the different authentication mechanisms, and when they'll be used.

Overview

There are currently three methods of authenticating to the API: API Keys, User Tokens, and Member Tokens. This section will go into the details of each of these methods, and how they can be used. In each case, the token should be supplied in the 'Authorization' HTTP header as a bearer token, i.e. Authorization: Bearer .

API Keys

You can use API keys to authenticate to the API for many actions. Your API keys will be provided by the Source team once your account is setup. Test mode secret keys have the prefix sk_test and live mode secret keys have the prefix sk_live. Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.

Use your API key by providing it as the username portion of a Basic authorization header, or by passing it as a bearer token.

User Tokens

When your team logs onto the platform, they'll have a user token generated for their session. This token is used with our API for actions performed by a specific person. We use information about the currently authenticated user to perform additional actions such as audit logging.

Note that as a user of the API, you will not be able to generate your own user tokens. User tokens are only issued after logging in on the Source login page.

Member Tokens

You can also generate member tokens, using the JSON Web Token standard, signed by your Source API key. These tokens allow your server to securely identify a member and share that information with Source.

Member tokens give you the ability to host your own fully-managed patient authentication experience, and simply provide a securely signed token to Source so that members and their caregivers can access their data through our API. You can read more about member tokens, and how you can generate them, in the next section.

Using Member Tokens

The JWT header for member tokens specifies the symmetric signing algorithm (HS256) and the ID of the Source API key that has signed the token. For example:

{
  "alg": "HS256",
  "kid": "key_xyz"
}

The payload of a token for a member logged in and acting as themselves their own data has their member ID in the sub (subject) field, issued-at and expires-at timestamps (seconds since the Unix epoch), and a set of permission scopes being granted (a planned feature, use an empty array for now).

{
  "sub": "mem_abc",
  "iat": 1655132531,
  "exp": 1655132831,
  "scopes": []
}

Caregiver Tokens

You can generate a member token for a caregiver who has an established relationship in Source, authorizing them to act on behalf of another member. In that case, the ID of the member receiving care must be in the sub (subject) field, and the ID of the authorized caregiver must be set in the act (actor) field. Source then confirms that the two members have an active relationship and authorizes access for the caregiver to the subject member. Source associates any actions the caregiver takes with the caregiver using the JWT's act field. For more information, see the Relationships API.

The payload of JWT for a member mem_2 acting as caregiver for a subject member mem_1 would look like this:

{
  "sub": "mem_1",
  "act": "mem_2",
  "iat": 1655132531,
  "exp": 1655132831,
  "scopes": []
}

Generating Member Tokens

Because the member tokens are signed by your secret key, this must be handled by your own server-side application and cannot be achieved solely in a frontend or mobile application.

Node JS Backend Stack

For an application based in JavaScript or TypeScript, you can use @source/client, our Node.js library, to generate a member JWT using your Source API keys. For example:

const jwt = await client.tokens.generate({
  subject: member.id,
  expiration: new Date(Date.now() + 1000 * 60 * 5), // 5 minutes
})
const client = new Source(new Token(jwt))

Other Backend Stacks

See the full documentation in the @source/client README.

If your application isn't based in JavaScript or you are not using the @source/client library, you can generate the member JWT yourself. For reference, the Typescript implementation (using the jose JWT library) looks like this, and can be adapted to JWT libraries available in all mainstream languages:

import { SignJWT } from 'jose/jwt/sign'

export interface TokenOptions {
  /**
   * 'Subject' member for which this token should be generated
   */
  subject: string

  /**
   * 'Actor' member, optional, the ID of the authorized member in the relationship acting on behalf of 'subject'.
   */
  actor?: string

  /**
   * Expiration time for the token. Must be no more than 24 hours from now.
   */
  expiration: Date

  /**
   * Scopes to apply to the token which may limit its access
   */
  scopes?: string[]
}

export default class TokenGenerator {
  private readonly encoder = new TextEncoder()

  public async generate(options: TokenOptions): Promise<string> {
    const signJWT = new SignJWT({
      sub: options.subject, // The source members id
      act: options.actor, // The optional actor member ID
      iat: Math.floor(Date.now() / 1_000), // The Issued At time
      exp: Math.floor(options.expiration.getTime() / 1_000), // The Expiration Time
      scopes: options.scopes ?? [], // The scopes to give this JWT - default to empty array.
    })

    return await signJWT
      .setProtectedHeader({ alg: 'HS256', kid: 'SOURCE_KEY_ID' })
      .sign(this.encoder.encode('SOURCE_KEY_SECRET'))
  }
}```

This is an abridged example, you can find the full implementation in the @source/client repo.