Skip to main content

Overview

The 5Stack GraphQL API uses cookie-based authentication with credentials passed automatically by the browser. This provides a secure and seamless authentication experience for web applications.

Authentication Method

Authentication is handled through HTTP cookies that are automatically included with requests when using the credentials: 'include' option.

HTTP Requests

For standard GraphQL queries and mutations:
const httpLink = createHttpLink({
  credentials: 'include',
  uri: 'https://{API_DOMAIN}/v1/graphql',
});

WebSocket Connections

For real-time subscriptions:
const wsClient = createClient({
  url: 'wss://{API_DOMAIN}/v1/graphql',
  connectionParams: {
    credentials: 'include',
  },
});

Admin Operations

For server-side admin operations, you can use the Hasura admin secret header:
x-hasura-admin-secret
string
required
Your Hasura GraphQL admin secret for privileged operations
const response = await fetch('https://{API_DOMAIN}/v1/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-hasura-admin-secret': process.env.HASURA_GRAPHQL_ADMIN_SECRET,
  },
  body: JSON.stringify({
    query: `
      query GetPlayers {
        players {
          steam_id
          name
          elo
        }
      }
    `,
  }),
});
The admin secret should NEVER be exposed to the client. Only use it in server-side code or secure backend services.

Authorization Hooks

The API uses Hasura’s webhook authorization system to validate requests and determine user permissions. The webhook validates:
  • User authentication status
  • User roles (player, moderator, admin)
  • Resource ownership and permissions

Error Responses

When authentication fails, you’ll receive one of these error messages:

Unauthorized

{
  "errors": [
    {
      "message": "Unauthorized",
      "extensions": {
        "code": "UNAUTHORIZED"
      }
    }
  ]
}
This error is silently handled and typically triggers a redirect to the login page.

Invalid Authorization Hook Response

{
  "errors": [
    {
      "message": "Invalid response from authorization hook",
      "extensions": {
        "code": "AUTH_HOOK_ERROR"
      }
    }
  ]
}

Client Setup Example

Here’s a complete example of setting up an authenticated Apollo Client:
import { ApolloClient, InMemoryCache, createHttpLink, from } from '@apollo/client/core';
import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry';

const errorLink = onError((error) => {
  if (error.graphQLErrors) {
    for (const graphqlError of error.graphQLErrors) {
      if ([
        'Unauthorized',
        'webhook authentication request',
        'Invalid response from authorization hook'
      ].includes(graphqlError.message)) {
        // Silently handle authentication errors
        return;
      }
      
      // Display other errors to user
      console.error('GraphQL Error:', graphqlError.message);
    }
  }
});

const retryLink = new RetryLink({
  delay: {
    initial: 300,
    max: 60000,
    jitter: true,
  },
  attempts: (count, operation, error) => {
    // Don't retry unauthorized requests
    if (error?.response?.status === 401) return false;
    return count < 30;
  },
});

const httpLink = createHttpLink({
  credentials: 'include',
  uri: 'https://{API_DOMAIN}/v1/graphql',
});

const client = new ApolloClient({
  link: from([errorLink, retryLink, httpLink]),
  cache: new InMemoryCache(),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
    },
    query: {
      fetchPolicy: 'network-only',
    },
  },
});

Player Roles

The API recognizes the following user roles:

Player

Standard user with access to their own data and public resources

Moderator

Can manage matches, tournaments, and moderate player actions

Admin

Full system access including server management and configuration

Session Management

Checking Authentication Status

You can check if a user is authenticated by querying their profile:
import { generateQuery } from '@/graphql/graphqlGen';
import { meFields } from '@/graphql/meGraphql';

const query = generateQuery({
  players_by_pk: [
    { steam_id: $('steam_id', 'String!') },
    meFields
  ]
});

Logging Out

Authentication cookies are managed by your auth service. To log out, clear the session cookie through your authentication endpoint.

Security Best Practices

Always use HTTPS in production to protect authentication cookies from interception.
Never expose the Hasura admin secret to client-side code. Use environment variables and server-side operations only.
Always validate and sanitize user input before sending it to the API to prevent injection attacks.

Next Steps

Queries

Start querying player and match data

Mutations

Learn how to create and update resources

Build docs developers (and LLMs) love