Goal

In this how to guide, we will go over how to use Credentials-based auth sessions. For this example, we will use OrangeHRM (demo site) as the target service.

Follow this guide step by step or you can use the Credentials based auth sessions project template to get a jump start. You can also watch a walkthrough of this guide below:

Step by step

1. Create a project and enable auth-sessions

In this guide, we will use Credentials-based auth sessions. In this type of auth sessions, the user credentials are used to run a browser automation code that creates a session in the target service. We also persist the credentials to use when the session expires.

  1. Navigate to https://app.intuned.io/projects
  2. Click New to create a new project
  3. Navigate to Intuned.json, which serves as the IDE settings
  4. Select Auth Session tab and set the following configurations
    • Toggle Enable auth sessions on
    • Set Auth session type to API created

To learn more about credentials-based auth sessions, check out Credentials-based auth sessions.

2. implement the check, create and refresh functions

Credentials-based auth sessions require the following functions to be implemented:

  • check function: This function is called before executing any authenticated action (API). If the function returns false, this signals that the auth session is expired/invalid and the auth session will be marked as expired for Recorder-based auth sessions. The API that was called will return 401 in this case.

  • create function: this function is used when a new auth session needs to be created/updated. This function takes the user provides credentials and performs browser automation that logs the user into the target service.

  • refresh function: this function is used to auto refresh the auth session when it expires. In most cases, the logic of the create and refresh functions are identical.

  1. Navigate to auth-sessions folder and define the scripts needed to sign into the target service.
  • create.ts should be defined to log the user into the target service.
import { BrowserContext, Page } from "@intuned/playwright-core";
import { extendPlaywrightPage } from "@intuned/sdk/playwright";

export interface CreateParams {
  username: string;
  password: string;
}

export default async function* create(
  params: CreateParams,
  _playwrightPage: Page,
  context: BrowserContext,
  refresh: boolean
): AsyncGenerator<unknown, any, string> {
  const page = extendPlaywrightPage(_playwrightPage);
  await page.goto("https://opensource-demo.orangehrmlive.com/");
  await page.getByPlaceholder("Username").fill(params.username);
  await page.getByPlaceholder("Password").fill(params.password);
  await page.getByRole("button", { name: "Login" }).click();
  await page.waitForURL(
    "https://opensource-demo.orangehrmlive.com/web/index.php/dashboard/index"
  );
}

  • check.ts should be defined to verify that the auth session is valid.
import { BrowserContext, Page } from "@intuned/playwright-core";
import { extendPlaywrightPage } from "@intuned/sdk/playwright";

export default async function check(
  _playwrightPage: Page,
  context: BrowserContext
): Promise<boolean> {
  const page = extendPlaywrightPage(_playwrightPage);

  await page.goto(
    "https://opensource-demo.orangehrmlive.com/web/index.php/dashboard/index"
  );
  const redirectedToLogin =
    page.url() ===
    "https://opensource-demo.orangehrmlive.com/web/index.php/auth/login";

  return !redirectedToLogin;
}
  • in this example, the refresh function default implementation will call the create function. This is will work fine here - no need to change it.

3. Create the authenticated APIs

Create APIs for all actions you would like to automate.

  1. Create an API named add-new-user.ts and write the script to add a new user to the HR portal.
import { BrowserContext, Page } from "@intuned/playwright-core";
import { extendPlaywrightPage } from "@intuned/sdk/playwright";

interface Params {
  employeeName: string
  username: string
  password: string
}

export default async function handler(
  params: Params,
  _playwrightPage: Page,
  context: BrowserContext
) {
  const page = extendPlaywrightPage(_playwrightPage);
  await page.goto("https://opensource-demo.orangehrmlive.com/web/index.php/admin/viewSystemUsers")

  await page.getByRole('button', { name: 'Add' }).click();

  await page.locator(".oxd-select-text-input").nth(0).click();
  await page.getByRole('option', { name: 'Admin' }).click();

  await page.getByPlaceholder('Type for hints...').fill(params.employeeName);
  await page.getByRole('option', { name: params.employeeName }).click();

  await page.locator(".oxd-select-text-input").nth(1).click();
  await page.getByRole('option', { name: 'Enabled' }).click();

  await page.getByRole('textbox').nth(2).fill(params.username);

  await page.locator('[type="password"]').nth(0).fill(params.password)
  await page.locator('[type="password"]').nth(1).fill(params.password)

  await page.getByRole('button', { name: 'Save' }).click();

  await page.waitForTimeout(2_000);

  const errorsLocators = await page.locator(".oxd-input-group__message").all()
  const messages = await Promise.all(errorsLocators.map(i => i.textContent()))

  if (messages.length > 0) {
    return {
      success: false,
    }
  }

  return {
    success: true
  }

}
  1. Create an API named get-claims.ts and write the script to get the employee claims
import { BrowserContext, Page } from "@intuned/playwright-core";
import { extendPlaywrightPage } from "@intuned/sdk/playwright";

interface Params {}

export default async function handler(
  params: Params,
  _playwrightPage: Page,
  context: BrowserContext
) {
  const page = extendPlaywrightPage(_playwrightPage);
  await page.goto(
    "https://opensource-demo.orangehrmlive.com/web/index.php/claim/viewAssignClaim"
  );

  const claims = await page.extractStructuredData({
    label: "claims",
    dataSchema: {
      type: "object",
      properties: {
        claims: {
          type: "array",
          items: {
            type: "object",
            properties: {
              referenceId: {
                type: "string",
                description: "claim reference id",
              },
              employeeName: {
                type: "string",
                description: "claim employee name",
              },
              eventName: {
                type: "string",
                description: "event nam",
              },
              currency: {
                type: "string",
                description: "claim currency",
              },
              submittedDate: {
                type: "string",
                description: "when the claim was submitted",
              },
              status: {
                type: "string",
                description: "claim status",
              },
              amount: {
                type: "string",
                description: "claim amount",
              },
            },
            required: [
              "amount",
              "status",
              "submittedDate",
              "currency",
              "eventName",
              "employeeName",
              "referenceId",
            ],
          },
        },
      },
      required: ["claims"],
    },
  });

  return claims;
}

4. Validate the APIs in the IDE and Deploy

  1. Create an auth session in the IDE
  2. Validate add-new-user and get-claims APIs with the auth session you created in the previous step.

5. Deploy and validate the deployed APIs

  1. deploy the project

  2. Create auth session for the deployed project

  3. Validate add-new-user and get-claims APIs with an simple async request

(Optional) How to build UX to allow users to “connect to OrangeHRM”

One main use case of auth session is building integration with services that require user authentication and has no APIs. For example, lets assume that you are building a EHR/automation platform and you to automate the process of pulling claims. To do this on behalf of your users, you would need to build a UX that allows users to connect their OrangeHRM accounts to your EHR/automation platform. To see an example of this, please checkout the following project and use it as a guide:

(Optional) Build an authenticated scraper using service accounts

Lets assume that we have the above project and APIs created and that we want to use them to build an authenticated scraper that will retrieve all claims from a cretin account on a daily basis. Lets also assume that this account access will be done via a static set of credentials that we will have.

You can watch a walk through of this guide below:

1. Create an auth session using the Intuned UI

  1. Navigate to the project that you have created in the previous steps
  2. Click on the Auth Sessions tab
  3. Click on New Auth Session
  4. Provide an auth session name. For example, orange-hrm-service-account
  5. Paste new credentials for the target service
{
    "employeeName": "Service Account",
    "username": "test-123",
    "password": "test-123"
}

2. Create a job to retrieve all claims daily

Jobs are a way to schedule recurring or batched/grouped executions. For more info about Jobs, checkout Jobs.

In this example, we know that we need to call the get-claims API and send the result to a webhook. We will create a job that does this weekly.

Creating jobs can be done via UI or API. For this example, we will use the UI. Checkout Jobs API overview for more info.

  1. Get a webhook url, for testing, you can use https://webhook.site/ to get a temp url. In a real scenario, you will use your own webhook url and persist the data to store.

  2. Go to the Jobs tab in the UX and create a new job with the following config. Don’t forget to replace <YOUR_WEBHOOK_URL> with your webhook url.

{
  "id": "orange-hrm-claims-webhook",
  "configuration": {
    "retry": {
      "initialInterval": 60000,
      "maximumAttempts": 5,
      "backoffCoefficient": 2
    },
    "runMode": "Order-Irrelevant",
    "version": "v1",
    "maxConcurrentRequests": 3
  },
  "sink": {
    "type": "webhook",
    "url": "<YOUR_WEBHOOK_URL>"
  },
  "schedule": {
    "intervals": [
      {
        "every": "1d"
      }
    ]
  },
  "authSession": {
    "id": "orange-hrm-service-account",
  }
  "payload": [
    {
      "apiName": "get-claims",
      "parameters": { }
    }
  ]
}
  1. Now, what will happen is that every day, the job will run, get the data from the API and send the result to the webhook url you provided.