Introduction

ROQ One supports common login methods for applications out-of-the-box with a username and password or single sign-on (currently we support Google, LinkedIn, and Apple). For privacy and security, users' passwords are always saved in the project's database and are never submitted to ROQ Platform.

When the login is complete the user holds several tokens for different use cases. Most of these are JSON Web Tokens that can easily be decoded using ➚jwt.io. The following diagram shows the two main tokens and how they are used:

As shown in the diagram, ROQ Platform maintains two graphs:

{URL}/v01/graphql

Graph for the client-side. Here you find queries, but no mutations. Therefore, this graph is read-only. To use this graph, you need a valid user token.

{URL}/v01/server/graphql

Graph for the server-side. Here you find all queries and mutations. This graph is protected by regular authentication via token and an  apiKey. For the production environment, we also recommend using IP whitelisting for additional security.

Token overview

User access token of ROQ One Backend

The user’s JWT access token is used for authentication against the project’s backend. This token is created during login and contains the user’s ID in ROQ One Backend (userId).

HTTP header

authorization

TTL

see the JWT section in backend/src/config/application.config.ts

User refresh token of ROQ One Backend

The user’s JWT refresh token that is used to create a new access token.

User access token of ROQ Platform

The user's JWT token here is used for queries and mutations on ROQ Platform. This token contains the tenantId of the project and the userId of the user on ROQ Platform. This ID is saved as roqIdentifier in your user-table.

HTTP header

roq-platform-authorization

How it works

If you are building on top of ROQ One, this logic is implemented and operational out of the box and requires no additional work from you! However, you may still want to read this documentation if you are looking to customize it or are just curious about how the system works.

How to protect a page in ROQ One Frontend

ROQ One Frontend is using a HOC to realize a secure user authentication, src/modules/auth/hocs/with-auth.hoc.tsx This HOC can be used inside of views to hide content from unauthenticated users:

import { withAuth } from 'modules/auth/hocs';
export const InviteNewUserView = withAuth()( ()=>{
// ...
)
TYPESCRIPT

Login flow

A user's login works like this:

  1. The user sends a username (can also be an email) and password using the login() mutation of ROQ Platform Backend

  2. If these credentials are correct, then all three tokens are created and returned to the client:

    • access and refresh tokens for ROQ One Backend, see AuthService::processLogin()

    • the access token for ROQ Platform. This token is retrieved by ROQ Platform's authorize() function, see PlatformHttpClientService::getAccessToken()

Registration flow

A user's registration works like this:

  1. The user enters the data into the registration form. Then the data is sent to the register() mutation of ROQ One Backend.

  2. Before the user is saved, ROQ One Backend sends the new user to ROQ Platform using the createUser() mutation.

  3. Then the user is saved to ROQ One's database. The field roqIdentifier represents the user's ID on ROQ Platform.

Service accounts

When ROQ One Backend communicates with ROQ Platform, that user’s access token is normally used. In some cases, however, there is no token available (for instance if the query or mutation is executed by a cron job). In this case, ROQ One can use ROQ Platform's authorizeServiceAccount() function. This service account represents a special type of user, which is identified by this email:

project-service-account@roq.tech
CODE

To use the service account you can use the PlatformServiceAccountClientService like this:

import { PlatformServiceAccountClientService } from 'src/platformClient/services';

export class MyClass {
  constructor(
    private platformServiceAccountClientService: PlatformServiceAccountClientService
  ) {}

  async myMethod(): Promise<void> {
    // ...
    await this.platformServiceAccountClientService.request(query, ...);
  }
}
TYPESCRIPT