Automate login for a page that authenticates with OKTA

Hello. I am using our RPA tool in order to automate a process for an application that uses Okta authentication. When trying from chrome developer console, something like the following:
document.getElementById(“okta-signin-username”).value = “myuser@nice.com”;
document.getElementById(“okta-signin-password”).value = “myPassword”;
oktalogin
values are assigned on the page, but a message showing “Please enter a password” appears.
then Submit button does not work.

Is there a workaround for this?

1 Like

Did you ever find a solution to this?

The only working method I’ve discovered is using sendkeys in each input field to satisfy the validation prior to the “click()” function. Unfortunately this is not as consistent as I would like and can easily be interrupted by a user.

I’ve also tried using: document.getElementById(“form1”).submit(); instead of clicking “Sign In”, however it just redirects me to an OKTA 404 Page instead of successfully authenticating.

I’ve used Protractor to write end-to-end tests. Here’s a search test:

import { browser, by, element } from 'protractor';
import { LoginPage } from './login.po';

describe('Search', () => {
  let loginPage: LoginPage;

  beforeAll(async () => {
    loginPage = new LoginPage();
    await loginPage.login();
  });

  afterAll(async () => {
    await loginPage.logout();
  });

  beforeEach(async () => {
    await browser.get('/search');
  });

  it('should have an input and search button', () => {
    expect(element(by.css('app-root app-search form input')).isPresent()).toEqual(true);
    expect(element(by.css('app-root app-search form button')).isPresent()).toEqual(true);
  });

  it('should allow searching', async () => {
    const searchButton = element(by.css('button'));
    const searchBox = element(by.css('input'));
    await searchBox.sendKeys('A');
    await searchButton.click();
    const list = element.all(by.css('app-search table tbody tr'));
    expect(list.count()).toBe(3);
  });
});

The login.po.ts page is:

import { browser, by, element, ExpectedConditions as ec } from 'protractor';

export class LoginPage {
  username = element(by.name('username'));
  password = element(by.name('password'));
  // button on IdP sign-in form
  loginButton = element(by.css('input[type=submit]'));
  signInButton = element(by.id('login'));
  logoutButton = element(by.id('logout'));
  welcomeMessage = element(by.css('h2'));

  async login(): Promise<void> {
    await browser.get('/');
    await browser.wait(ec.visibilityOf(this.signInButton));
    await this.signInButton.click();
    // You must set E2E_USERNAME, E2E_PASSWORD, and E2E_NAME as environment variables
    await this.loginToIdP(process.env.E2E_USERNAME, process.env.E2E_PASSWORD);
    const welcome = new RegExp('Welcome, ' + process.env.E2E_NAME);
    await browser.wait(ec.visibilityOf(this.logoutButton));
    await browser.sleep(2000); // wait for user to resolve
    expect(this.welcomeMessage.getText()).toMatch(welcome);
  }

  async loginToIdP(username: string, password: string): Promise<void> {
    // Entering non angular site, tell webdriver to switch to synchronous mode.
    await browser.waitForAngularEnabled(false);
    await browser.wait(ec.visibilityOf(this.username));

    if (await this.username.isPresent()) {
      await this.username.sendKeys(username);
      await this.password.sendKeys(password);
      await this.loginButton.click();
      if (!(await this.username.isPresent())) {
        await browser.waitForAngularEnabled(true);
      }
    } else {
      // redirected back because already logged in
      await browser.waitForAngularEnabled(true);
    }
  }

  async logout(): Promise<void> {
    await browser.get('/');
    await browser.wait(ec.visibilityOf(this.logoutButton));
    await this.logoutButton.click();
    await browser.sleep(1000);
  }
}

Repo is at https://github.com/mraible/ng-demo/tree/okta.

Hi

I found a workaround using events emulation, after sending the value we sent keuyp and keydown, the it worked

Thanks

Edgar Moreno

@mraible Thank you for the prompt response. Our solution is end-user facing and we found if we use sendKeys for the full username and password it could easily be captured by launching Notepad and manually grabbing focus before those lines execute. I doubt anyone would replicate it in production, but we decided to scrap that due to the added security risk.

@emoreno Would you mind sharing some of your code used to accomplish this? If I’m understanding correctly, triggering or emulating a keypress event seems more direct then using sendKeys which can be interrupted by a user. Our current solution requires updating the input values normally ($el.value="") and then using sendKeys to send a single character and then a {BACKSPACE} for each field. This technically works, but is definitely not consistent if a user is multitasking and focusing other windows.

Hi

Our tool (NICE Real Time designer) has a way to fire events on a given html element:

image001.png

I think it injects javascript like this:

document.dispatchEvent(

new KeyboardEvent(“keydown”, {

key: “e”,

keyCode: 69, //

code: “KeyE”, //

which: 69,

shiftKey: false, //

ctrlKey: false, // if you aren’t going to use them.

metaKey: false //

})

);

https://stackoverflow.com/questions/596481/is-it-possible-to-simulate-key-press-events-programmatically?lq=1

thanks

emoreno