npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@svalabs/cypress-keycloak-commands

v2.0.0

Published

Cypress commands for login with Keycloak

Downloads

2,575

Readme

cypress-keycloak-commands

All Contributors

Cypress commands for login with Keycloak.

  • Setup Keycloak configuration from Cypress configuration or environment variables
  • Use Fixtures to store users data
  • Returns you the tokens of the logged user for calling backend APIs from your test code
  • Fake login command for integration testing
  • Tested with Keycloak 5-20

Usage

Installing

Install the package using npm:

npm i -D cypress-keycloak-commands

or Yarn:

yarn add -D cypress-keycloak-commands

Import the package in the file cypress/support/commands.js (or cypress/support/commands.ts):

import "cypress-keycloak-commands";

Setup Keycloak configuration

Setup the Keycloak configuration in cypress.json configuration file:

{
  "env": {
    "auth_base_url": "https://auth.server/auth",
    "auth_realm": "my_realm",
    "auth_client_id": "my_client_id",
    "auth_client_secret": "my_client_secret"
  }
}

You can override this settings for some tests using Environment variables.

Login commands for E2E Tests

Cypress best practices

Cypress states in it's docs: "State reset should go before each test". We strongly agree with this best practice. Unfortunately or luckily, Keycloak 18 has better support for logout based on the OpenID Connect RP-Initiated Logout specification, see here, therefore we need to provide the id_token_hint when logging out. Hence, cy.kcLogout() depends on the token provided by cy.kcLogin() and it might be necessary to work with beforeEach() and afterEach() blocks.

For logging in with Keycloak there are two possibilities:

Using Variables

This is the recommended approach, since it enables the usage of Environment variables for production environments.

describe("Keycloak Login", () => {
  beforeEach(() => {
    cy.kcLogin({
      username: "user",
      password: "password"
    });
    cy.visit("/");
  });

  afterEach(() => {
    cy.kcLogout();
  });
});

Using fixtures

Create a fixture containing the user credentials under the directory cypress/fixtures/users. For example you can create a file cypress/fixtures/users/user.json with this content:

{
  "username": "user",
  "password": "password"
}

When you have a fixture you can login using the kcLogin command, passing the name of the fixture, and you can perform a logout using the kcLogout command:

describe("Keycloak Login", () => {
  beforeEach(() => {
    cy.kcLogin("user");
    cy.visit("/");
  });

  afterEach(() => {
    cy.kcLogout();
  });
});

You should always perform logout before logging in a user, following the best practice of cleaning the state in the beforeEach hook.

Login Options

Cypress will print the username and password combination in it's log. In case you want to mask the password, use the optional options interface.

describe("Keycloak Login", () => {
  beforeEach(() => {
    cy.kcLogin("user", { mask: true });
    cy.visit("/");
  });

  afterEach(() => {
    cy.kcLogout();
  });
});

Get user tokens for calling APIs from E2E tests

If you need to call backend APIs from your tests using the token of the logged user (for example to set up the state bypassing the UI) you can get the retrieved user tokes from the kcLogin command:

describe("Keycloak Login", () => {
  beforeEach(() => {
    cy.kcLogin("user").as("tokens");
    cy.visit("/");
  });

  afterEach(() => {
    cy.kcLogout();
  })

  it("should call an API with the token", () => {
    cy.get("@tokens").then(tokens => {
      cy.request({
        url: "/my_api"
        auth: {
          bearer: tokens.access_token
        }
      });
    });
  });
});

Note: if you use Typescript you have to specify the return type of the cy.get command:

cy.get<KcTokens>("@tokens");

Fake Login for Integration testing

If you are doing an integration test that doesn't call a real backend API, maybe you don't need to authenticate a real user to a running Keycloak instance, but if your app uses the Keycloak Javascript Adapter to check if a user is logged in, you will need to have a mocked user.

To create mocked user data, you need three tokens (access token, refresh token, id token) of a real user returned by your Keycloak instance. You can get them for example from the Dev Tools of your browser, searching for calls to the token endpoint of Keycloak. If your app calls the /account endpoint to retrieve user information you will also need to have the response returned for the API. Then you can create the fixture with the fake user data:

{
  "fakeLogin": {
    "access_token": "...",
    "refresh_token": "...",
    "id_token": "...",
    "account": {
      "username": "user",
      "firstName": "Sample",
      "lastName": "User",
      "email": "sample-user@example",
      "emailVerified": false,
      "attributes": {}
    }
  }
}

With the fixture in place, you can use the kcFakeLogin command to perform a fake login without hitting a real Keycloak instance.

The Fake Login is performed loading a page and passing some keycloak initialization parameters in the URL. If you need to visit a page different from the homepage you must pass its url to the kcFakeLogin command as second parameter (instead of using cy.visit):

describe("Keycloak Fake Login", () => {
  beforeEach(() => {
    cy.kcFakeLogin("user", "pageToVisit");
  });
});

Session Status iframe

At the moment within Cypress is not possible to mock iframe loading and APIs called from an iframe. For this reason, when you use kcFakeLogin you have to disable the Session Status iframe, otherwise the Javascript adapter will redirect you to the real Keycloak instance. You can disable it only when the app is running inside Cypress:

const checkLoginIframe = window.Cypress ? false : true;

var initOptions = {
  responseMode: "fragment",
  flow: "standard",
  onLoad: "login-required",
  checkLoginIframe
};

Acknowledgements

Other solutions that have inspired this library:

  • https://vrockai.github.io/blog/2017/10/28/cypress-keycloak-intregration/
  • https://www.npmjs.com/package/cypress-keycloak

License

MIT

Contributors ✨

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!