GraphQL with external authentication

GraphQL interface allows you to execute requests in the context of a logged-in end user (customer). The typical scenario where you would use this API, is to build user experience for your customers, in the form of a mobile app of web application.

This guide will explain how to access GraphQL interface using your own (or 3rd party) authentication provider.

📘

Note

The queries and mutations of the GraphQL interface are separate from the authentication-related functions. The latter are available under our REST-based Authentication Api.

Because of this, the authentication scheme for GraphQL is more complex. We have the notion of external authentication tokens, Shaype Access Tokens, and elevated access (required for high security operations, like executing a transfer).

We will discuss these concepts in the subsequent sections.

Access Tokens

Both GraphQL interface and Authentication API work with signed JWT tokens. You will receive Access Tokens from us, in response to a token exchange operation described in the next section.

To access GraphQL queries and mutations, you need to provide the acquired Access Token as the Authentication: Bearer HTTP header. Valid token will grant you access with the security context of the end user for whom it was issued.

Access Tokens are short-lived. After expiration, a new Access Token needs to be acquired by repeating the token exchange.

🚧

Refresh Tokens

Refresh Tokens are used by clients taking advantage of the Shaype authentication provider. You might notice that the token exchange operation also returns a Refresh Token, but this is a deprecated functionality and will be removed soon. Please don't rely on the Refresh Token to issue new Access Tokens when using external authentication provider - use the token exchange operation instead.

Getting the tokens

When using your own authentication provider, the process for getting the Access token involves asymmetric keys encryption. You will need to publish your public keys in a well-known location in a JWKS format (JSON Web Key Set) that we will use to validate your authentication tokens and exchange them for our Access tokens.

If you take a look at Create Customer REST API endpoint, you will notice the externalCustomerId property. This is a unique identifier of a customer in your system and has to be provided when adding customers if you plan to use your own authentication provider. We will use it when exchanging your authentication token (containing the external customer ID) for our Access Token (containing the customer ID on the Shaype platform). To execute token exchange, you need to call the Exchange External Token endpoint with a valid authentication header that is verifiable against a public key stored in your JWKS file. This endpoint doesn't take any payload, it operates strictly on the authentication header passed.

❗️

Important

When creating Customers, you MUST supply the externalCustomerId property if you want to use your own authentication provider.

Example authentication token

Header:
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "Abcdef-ghijkl..."
}

Payload:
{
  "scope": [
    "hay.auth.tokenexchange"
  ],
  "client_id": "12345678-90ab-cdef-1234-567890abcdef",
  "iat": 1648471572,
  "exp": 1648471632,
  "aud": "HayTokenExchange",
  "iss": "https://url-defining-your-issuer.com",
  "sub": "98765432-10fe-dcba-9876-543210fedcba"
}

Let's go through these fields one-by-one and describe what they mean, and what pieces of configuration need to be agreed between you and Shaype for a successful token exchange.

FieldDescription
algAsymmetric token signing algorithm, should be RS256
typToken type, needs to be JWT
kidPublic key identifier. The value provided in this field has to exactly match one of the public keys listed in the JWKS file that you host. We will use it to read your public key, and then validate the signature of your authentication token.
scopeScope claim. Mandatory, has to be hay.auth.tokenexchange.

Note: We support two formats of scope: It can be provided as a JSON array, like in the example above, or as a space-separated string, e.g.:

"scope": "hay.auth.tokenexchange"

Selection of the scope claim format is a part of the initial configuration of the integration.
Installation ID (client_id)Claim identifying the application sending the authentication token. It can be a single value that represents your web application, or a per-device identifier that represents individual mobile app installation.

Note: The name of this claim is configurable.
iatToken issue timestamp (seconds since UNIX epoch)
expToken expiration time (seconds since UNIX epoch)

Note: Use short expiration time.
audToken audience. Mandatory, has to be HayTokenExchange.
issIdentifier of the token issuer. This has to match exactly the issuer configured for you on Shaype side.
subToken subject - this is the externalCustomerId of the customer identified by the token.

Below is an example response that you will receive from the Exchange External Token endpoint:

{
  "access_expires_utc": 1648481632,
  "access_token": "abcde343233....",
  "installation_handle": "12345678-90ab-cdef-1234-567890abcdef",
    
  "refresh_expires_utc": 1668481632,
  "refresh_token": "xyz6454"
}

🚧

Note

Do not use the Refresh Token. It is deprecated and will soon disappear from this response. When the Access Token expires, execute the token exchange operation again to receive a new one.

After receiving the Access Token, you can pass it as Authentication: Bearer ... header to graphQL calls. They will be executed in the context of customer identified by the subject of your Authentication token.

Token elevation

Some of the GraphQL queries and mutations require an elevated security context. After you have received your Access Token, you can elevate its security context using the Elevate Access Token endpoint. This endpoint doesn't take any payload, it operates strictly on the headers passed.

For this operation, you will need to pass two JWT tokens:

  1. Your normal (pre-exchange) authentication token (exactly the same as you send to the Exchange External Token endpoint) sent as Authentication: Bearer HTTP header
  2. A step-up token sent as X-Authorization-StepUp HTTP header.

Step-up token should be constructed similarly to the authentication token, with the following differences:

  • Token scope should contain an elevated scope name agreed with Shaype during initial configuration (e.g. account-stepup),
  • Token cannot be older than 5 minutes,
  • Token can be used only once.

📘

Note

Please make sure that the step-up token uses HayTokenExchange audience, the same as authentication token. Authentication and step-up tokens should share exactly the same Subject (sub) and Issuer (iss) claims.

In response to this call you will receive a string called Elevation Header. This needs to be passed to GraphQL calls alongside the Access Token:

  • Access Token should be sent the usual way, as Authentication: Bearer header
  • Step-up Token should be sent as elevation HTTP header.

Authentication configuration

The table below summarises the configuration settings that need to be agreed with Shaype before you can start using your own authentication provider:

SettingDescription
IssuerIdentifier of the token issuer. Note: This setting has to match exactly the issuer you will be sending in your authentication tokens, or we won't be able to match them against our configuration.
JWKS file URLThe well-known location of the file containing your public key that we will use to validate authentication token signature.
Installation ID claim nameThe name on the claim containing an installation ID in the authentication tokens you will be sending. Examples: client_id or azp (used by Auth0).
Elevated scope nameName of the scope you will use for token elevation (see the section above).
Scope formatDefines whether the scope(s) will be provided as a JSON array, or a space-separated string.