Authentication with GraphQL endpoints - obtaining access tokens through API clients

I’m working with a CRM platform that uses Symphony on the backend and AngularJS for the frontend. The system relies heavily on GraphQL for API communication in version 8.x.

I want to authenticate programmatically using the same API calls that the Angular frontend uses. When I check the browser’s network panel, I can see the authentication flow:

  1. Initial POST request to site.com/auth
  2. Subsequent GraphQL calls to site.com/api/graphql

The authentication request shows:

POST request
200 response
Referrer Policy: strict-origin-when-cross-origin

The request body contains basic credentials in JSON format with username and password fields.

However, when I try to replicate this using API tools like Postman, Python requests, or n8n, I get a 401 error saying “Invalid CSRF token.”

Looking at the browser request headers, I notice several cookies being sent:

Cookie: app_theme=modern; lang_pref=en_us; session_id=abc123; auth_token=xyz789; PHPSESSID=session123; CSRF_TOKEN=token456

This suggests I need some kind of CSRF token before I can even authenticate. But how do I get this initial token if the login endpoint is supposedly the first step?

I’ve tried different approaches with request headers, body formats, and authorization methods in Postman, but nothing works. The system documentation is minimal, though the existing AngularJS code works perfectly.

How can I properly authenticate with this GraphQL API using external tools? What’s the correct sequence to obtain the necessary tokens?

symphony systems are notorious for CSRF issues. look for /api/token or /csrf endpoints - they’ll give you the token directly without parsing HTML. way easier than scraping meta tags from login pages.

Had this exact issue with a Symphony system last year. Symphony generates CSRF tokens dynamically and ties them to sessions. Your browser works because Angular probably makes an initial request during app startup that sets up the session - could be a preflight to /api/csrf or just loading the main page.

Try hitting your main app URL with a GET request first, then grab the CSRF token from the response. Symphony usually sticks them in meta tags like <meta name="csrf-token" content="..."> or dumps them in initial JSON.

I also had luck checking if the system supports API key auth instead of session-based stuff. Lots of Symphony setups have this option, even if it’s not documented.

If you’re still stuck, dig deeper into the Network tab for any XHR requests that fire before authentication. There’s probably a token grab step that Angular handles automatically during bootstrap that you’re missing.

This CSRF token issue is super common with Symphony apps. You’re missing a step - you need to establish a session before trying to authenticate.

Here’s what worked for me: Make a GET request to the main app URL or login page first. This creates the session and usually returns the CSRF token in a meta tag or response header. Then just include that token in your POST request as either a header or form field.

Symphony apps can be picky about token naming. Could be _token, csrf_token, or X-CSRF-TOKEN in the header. Check the Angular source to see exactly how it’s sending the token.

Also ran into issues with User-Agent strings. Some systems reject requests that don’t look like they’re from a real browser. Try adding a standard browser User-Agent header.

For debugging, use Burp Suite or OWASP ZAP to intercept the working Angular requests and compare them with your API calls. Usually it’s something small like header formatting or parameter names that’s causing the problem.

The Problem:

You’re struggling to authenticate with a Symphony CRM backend using GraphQL (v8.x) from external tools because of CSRF token issues. Your browser-based AngularJS frontend authenticates successfully, but attempts using Postman, Python requests, or n8n result in “Invalid CSRF token” errors. You understand that you need to obtain the CSRF token before authentication, but are unsure how to do this programmatically.

:thinking: Understanding the “Why” (The Root Cause):

The problem is a classic “chicken-and-egg” scenario common in web applications using CSRF protection. Your AngularJS frontend implicitly manages the session setup and CSRF token acquisition, likely through an initial request to the application that sets up the required session context and returns the necessary token. External tools like Postman or n8n don’t automatically handle this implicit session creation and token retrieval process. Simply sending a POST request to /site.com/auth without the proper context results in the CSRF validation failure.

:gear: Step-by-Step Guide:

  1. Automate the Authentication Flow: Instead of manually managing individual GET requests for tokens and POST requests for authentication, automate the entire process using a tool designed for creating multi-step workflows. This approach elegantly solves the order-dependent nature of obtaining the CSRF token and authenticating.

  2. Choose a Workflow Automation Tool: Select a tool that allows you to chain HTTP requests together, manage session cookies automatically, and handle potential token refresh mechanisms (in case your tokens expire). The tool should ideally provide a visual interface for easily building and debugging the sequence. Several products provide these capabilities.

  3. Build Your Workflow: Construct the following sequence of steps within your chosen tool:

    • Step 1: Initial GET Request: Begin with a GET request to your main application URL (site.com). This action establishes the necessary session. The response from this request might contain a CSRF token in a meta tag (<meta name="csrf-token" content="...">) or a header.

    • Step 2: Extract the CSRF Token: Extract the CSRF token from the response of Step 1. The method will vary depending on where the token is embedded (meta tag or header).

    • Step 3: Authentication POST Request: Send a POST request to /site.com/auth including your username and password. Crucially, include the CSRF token obtained in Step 2 within the request, either in the header (X-CSRF-Token or a similar naming convention – examine your browser’s network requests for the exact name) or as a form parameter (again, check your browser network traffic).

    • Step 4: Store Session Cookies and Headers: After successful authentication (200 response), your tool should automatically store the session cookies returned in the response. These cookies will be needed for subsequent GraphQL API calls.

    • Step 5: GraphQL API Calls: Now you can make GraphQL calls to /site.com/api/graphql, ensuring that the stored session cookies and headers are included in every request.

  4. Handle Token Expiration: Integrate a mechanism to refresh your tokens if the session expires. This usually involves checking response status codes and repeating the steps above if the authentication fails due to token expiry.

:mag: Common Pitfalls & What to Check Next:

  • CSRF Token Location: Double-check the precise location and name of the CSRF token in your application’s response. It might be in an unexpected location or have a slightly different name than you initially expected. Use your browser’s developer tools to inspect the network requests.

  • Header Names: Case sensitivity matters in HTTP headers! Ensure that the CSRF token header name exactly matches what the server expects.

  • User-Agent: Some systems might be configured to reject requests with unusual User-Agent strings. Try setting a standard browser User-Agent header in your requests.

  • Content-Type: Experiment with different Content-Type headers (e.g., application/json, application/x-www-form-urlencoded) in your POST request if authentication continues to fail.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!

Check if your Symphony installation has OAuth or API token endpoints. Most Symphony CRM setups have alternative auth methods that skip the CSRF headache completely. Had a client where session-based auth was driving us crazy. Found an undocumented /oauth/token endpoint that took client credentials and returned JWT tokens. Worked perfectly for GraphQL calls without any CSRF garbage. Also verify if Symphony needs specific Content-Type headers. I’ve seen systems reject application/json but accept application/x-www-form-urlencoded for auth, even though the payload looks like JSON in the browser. Check for a /api/session endpoint that returns session info with the CSRF token as JSON instead of HTML parsing. Way cleaner than scraping meta tags from login pages. If you’re stuck with session auth, grab the exact request timing from your browser’s network tab. Sometimes Symphony wants requests within a specific time window after token generation.

Been dealing with similar CSRF nightmares for years. You need to make an initial GET request to grab that CSRF token before attempting authentication.

Most CRM systems follow a predictable pattern:

  1. GET request to /auth or /login page to extract CSRF token from response headers or HTML
  2. POST to /auth with both credentials AND the CSRF token
  3. Use returned session cookies for GraphQL calls

The Angular app does this automatically, but external tools need to handle the token dance manually.

Here’s what I’d do differently. Instead of wrestling with CSRF tokens and session management, I built a workflow in Latenode that handles this entire authentication flow automatically.

It starts with a GET request to extract the CSRF token, then chains the POST authentication, and stores all the session data for subsequent GraphQL calls. The best part is it can refresh tokens automatically when they expire.

I use this same pattern for multiple CRM integrations now. Way cleaner than managing cookies and tokens manually in Python or Postman.

Latenode handles all the header manipulation and cookie persistence between requests, so you just focus on your actual business logic instead of authentication plumbing.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.