有没有办法使用cypress/JS以编程方式通过Keycloak登录应用程序?

时间:2021-04-15 06:27:38

标签: javascript authentication jwt keycloak cypress

我在 Cypress 中为受 Keycloak 保护的 Web 应用程序编写了自动化测试。我已经设法从 keycloak 检索 jwt 令牌,但我不知道如何处理它。我已经看到,在您登录 keycloak 后,您被重定向到您的域,并且 keyclock 设置了 cookie、本地存储等。 当您登录他们的页面时,有没有办法以编程方式获得与 keyclock 相同的结果?换句话说,有类似的东西:

cy.getToken().then((token) => {
   cy.login(token);
   cy.visit(myDomain)
})

3 个答案:

答案 0 :(得分:4)

看看图书馆,cypress-keycloak-commands 是另一个更受欢迎的图书馆(大约是每周下载量的三倍)。

我喜欢它基于配置的方式,并且有 cy.kcFakeLogin() 用于基于夹具的模拟。

如果您想了解 Keycloak 的详细信息,还有此博客 Cypress.io Keycloak Integration

如果链接消失,请转载以备将来参考

Cypress.Commands.add('kcLogin', (username, password) => {
  const kcRoot = 'http://my.keycloak.com';
  const kcRealm = 'MYrealm';
  const kcClient = 'my-client';
  const kcRedirectUri = 'http://localhost:3000/';
  const loginPageRequest = {
    url: `${kcRoot}/auth/realms/${kcRealm}/protocol/openid-connect/auth`,
    qs: {
      client_id: kcClient,
      redirect_uri: kcRedirectUri,
      state: createUUID(),
      nonce: createUUID(),
      response_mode: 'fragment',
      response_type: 'code',
      scope: 'openid'
    }
  };
  // Open the KC login page, fill in the form with username and password and submit.
  return cy.request(loginPageRequest)
    .then(submitLoginForm);
  ////////////
  function submitLoginForm(response) {
    const _el = document.createElement('html');
    _el.innerHTML = response.body;
    // This should be more strict depending on your login page template.
    const loginForm = _el.getElementsByTagName('form');
    const isAlreadyLoggedIn = !loginForm.length;
    if (isAlreadyLoggedIn) {
      return;
    }
    return cy.request({
      form: true,
      method: 'POST',
      url: loginForm[0].action,
      followRedirect: false,
      body: {
        username: username,
        password: password        
      }
    });
  }
  // Copy-pasted code from KC javascript client. It probably doesn't need to be 
  // this complicated but I refused to spend time on figuring that out.
  function createUUID() {
    var s = [];
    var hexDigits = '0123456789abcdef';
    for (var i = 0; i < 36; i++) {
      s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = '4';
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
    s[8] = s[13] = s[18] = s[23] = '-';
    var uuid = s.join('');
    return uuid;
  }
});

答案 1 :(得分:1)

再次遇到这个问题。和 Boogie 一样,我们一直无法让 cypress.io 登录 keycloak。

有没有人在 Keycloak 和 Cypress.io 上取得过任何成功?我已经尝试了任何和所有的建议。我们在前端使用 Angular(8.2.14 版)、Keycloak(11.0.3 版)和 Cypress.io(7.3.0 版)。

尝试过但失败了:

cypress-keycloak 和 cypress-keycloak-command 库

此处找到的步骤https://vrockai.github.io/blog/2017/10/28/cypress-keycloak-intregration/

我们正在尝试什么:

  1. 使用visit()从keycloak获取登录页面,然后重定向false(成功)。

  2. 向我们自己的服务器发送身份验证请求并遵循重定向错误(成功)。

  3. 在 keycloak 页面提交登录凭据,点击登录按钮并等待(成功,因为我们可以在 keycloak 服务上看到用户已成功登录且没有错误)。

  4. 重定向到 Angular 站点永远不会发生。

使用任何浏览器手动执行登录步骤,效果很好。

我的智商已经不行了。欢迎提出任何建议。

答案 2 :(得分:0)

您可以使用插件 cypress-keycloak 来实现这一点。

安装后转到 cypress/support/commands.js 并写入:

// Using ES6
import 'cypress-keycloak';

OR

// using CommonJS
require('cypress-keycloak');

然后在您的测试中您可以编写(示例取自 cypress-keycloak npm 页面):

describe('thing', () => {
  beforeEach(() => {
    cy.login({
      root: 'https://keycloak.babangsund.com',
      realm: 'stage',
      username: 'babangsund',
      password: 'bacon',
      client_id: 'frontend',
      redirect_uri: 'https://babangsund.com/',
    });

    // or login with OTP
    cy.loginOTP({
      root: 'https://keycloak.babangsund.com',
      realm: 'stage',
      username: 'babangsund',
      password: 'bacon',
      client_id: 'frontend',
      redirect_uri: 'https://babangsund.com/',
      otp_secret: 'OZLDC2HZKM3QUC...', // e.g. 32 chars
      otp_credential_id: '5e231f20-8ca7-35e1-20a694b60181ca9', // e.g. 36 chars
    });
  });

  afterEach(() => {
    cy.logout({
      root: 'https://keycloak.babangsund.com',
      realm: 'stage',
      redirect_uri: 'https://babangsund.com/',
    });
  });
});
相关问题