Skip to content

Authentication Flow

The Merq backend uses a robust JSON Web Token (JWT) based system for authentication and authorization. This ensures that all protected endpoints are secure and that users can only access data within their designated workspace.

The flow begins when a user signs in with their email and password.

  1. Client Request A POST request is sent to /api/office/v1/auth/signin (for web) or /api/app/v1/auth/signin (for mobile) with the user’s credentials. A mandatory X-Device-Fingerprint header must be included to uniquely identify the client device or browser session.

  2. Handler (auth_handler.go) The SignIn handler receives the request, validates the payload, and extracts the email, password, IP address, User-Agent, and X-Device-Fingerprint.

  3. Service (auth_service.go) The Login service method is called. It performs the core logic:

    • Finds the user by email in the database.
    • Verifies the password using bcrypt.
    • On success, it generates two tokens: a short-lived Access Token and a long-lived Refresh Token.
    • It also records a login_audits entry for security purposes.
  4. Client Response The service returns the access_token and refresh_token to the handler, which sends them back to the client. The client is now responsible for storing these tokens securely.


The access token is the key to accessing protected API resources.

  • Purpose: To authenticate and authorize subsequent API requests.
  • Lifetime: 24 hours.
  • Usage: The client must include it in the Authorization header of every request to a protected endpoint, formatted as Bearer <access_token>.

The JWT payload contains a set of “claims” that describe the user and their permissions.

id

The unique ID of the user.

workspace_id

The ID of the user’s workspace, critical for data scoping.

role_id

The ID of the user’s assigned role.

role_value

The string key of the role (e.g., “admin”).

permissions

A comma-separated string of all permissions granted to the user’s role.

exp

The standard JWT expiration timestamp.


Every protected API route is guarded by the AuthMiddleware.

  1. Header Check The middleware first checks for the Authorization: Bearer <token> header. If it’s missing or malformed, it immediately returns a 401 Unauthorized error.

  2. Token Validation It parses and validates the JWT signature and expiration time using the JWT_SECRET from the environment configuration.

  3. Claims Injection If the token is valid, the middleware extracts all the claims (id, workspace_id, role_id, etc.) from the token payload.

  4. Context Population It injects these claims into the gin.Context. Downstream handlers and services can then access this information to enforce business rules, such as checking permissions (RBACMiddleware) or filtering database queries by workspace_id.


When the 24-hour access token expires, the client can obtain a new one without forcing the user to log in again, using the refresh token.

  • Endpoint: POST /api/office/v1/auth/refresh
  • Refresh Token Lifetime: 30 days.
  1. Client Request The client sends a POST request with the refresh_token in the body. The same X-Device-Fingerprint header from the original login must be included.

  2. Device Fingerprint Verification The service validates that the refresh token and device fingerprint match a stored record. This prevents a stolen refresh token from being used on a different device.

  3. New Token Generation If the token is valid and linked to the correct device, the RefreshToken service generates a new access token and a new refresh token.

  4. Token Rotation The old refresh token is invalidated, and the new one is stored in the database. This is a security measure known as refresh token rotation.

  5. Client Response The new access_token and refresh_token are sent back to the client, which can then resume making authenticated requests.