# Web Browser component login to website

**URL:** <https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219>\
**Category:** Ignition\
**Tags:** vision, ignition81\
**Created:** [June 19, 2023, 3:06pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219 "2023-06-19T15:06:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Micah\_Carr](https://avatars.discourse-cdn.com/v4/letter/m/bbe5ce/32.png) [@Micah\_Carr](https://forum.inductiveautomation.com/u/Micah_Carr)\
**Post date:** [June 19, 2023, 3:06pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/1 "2023-06-19T15:06:39Z")

</div>

I need to set up a script or something to allow the web browser component to automatically login to SharePoint webpage.

I have had a project deployed for over a year now that was able to access SharePoint documents; it automatically logged in based on the windows user. But something changed this weekend and it no longer works.

I have been struggling to find a way for a script to interact with the web page in order to login. Does anyone know how to accomplish this?

---

<div class="post-metadata">

**Author:** ![Micah\_Carr](https://avatars.discourse-cdn.com/v4/letter/m/bbe5ce/32.png) [@Micah\_Carr](https://forum.inductiveautomation.com/u/Micah_Carr)\
**Post date:** [June 19, 2023, 4:20pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/2 "2023-06-19T16:20:26Z")

</div>

I have been reading through the jxbrowser documentation and it looks like it has the capability to do this. But all of the examples are in java, I cannot figure out how to use these functions in a python script.

> **[DOM](https://jxbrowser-support.teamdev.com/docs/guides/dom.html)**
>
> JxBrowser getting started, guides, tutorials, examples, release notes, roadmap, blog, etc.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 19, 2023, 7:14pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/3 "2023-06-19T19:14:30Z")

</div>

> [@Micah\_Carr](#):
>
> how to use these functions in a python script

If you post the script you are trying to convert, one of us can walk you through how to convert it to jython. It's usually just just a matter of importing and creating instances of the objects you need rather than simply declaring them.

---

<div class="post-metadata">

**Author:** ![Micah\_Carr](https://avatars.discourse-cdn.com/v4/letter/m/bbe5ce/32.png) [@Micah\_Carr](https://forum.inductiveautomation.com/u/Micah_Carr)\
**Post date:** [June 19, 2023, 8:19pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/4 "2023-06-19T20:19:27Z")

</div>

I need to enter a username/password into text fields:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/3/53399deb2b41b0bdc6951f56a0e02016a3a27ef3.png)

And click a button:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/8/a8d8563f2ad25e0df36ab063f19808f3d674cda9.png)

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [June 19, 2023, 8:42pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/5 "2023-06-19T20:42:27Z")

</div>

The web browser component has a `.getBrowser()` scripting function so you should be able to get a reference to the DOM and thus documentElements.

You can use `dir()` to find what properties and methods are are your disposal. I don't have the Web Browser Component, so I'm going completely off of the manual.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 19, 2023, 10:24pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/6 "2023-06-19T22:24:08Z")

</div>

from the JxBrowser docs:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/c/2c99552c3297653b95c8e9123e42cfd709cca580.png)

This is not something I've ever messed with before, but it looks like you can ~~use the code as it is written~~ convert the code in the documentation to javascript and apply it in this way:

```auto
webComponent = event.source.parent.getComponent('Web Browser')#replace with relative path to your component
webbrowser = webComponent.browser
frame = webbrowser.focusedFrame()
if frame.isPresent():
	frame.get().executeJavaScript("const element = document.getElementById('firstname'); if (element !== null) {element.value = 'John';}")

```

**Edit:** Updated per feedback below

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 19, 2023, 10:34pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/7 "2023-06-19T22:34:30Z")

</div>

I'm pretty sure what you've written inside the 'executeJavascript' call there is more Java code. But the general principle is about right.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 19, 2023, 10:40pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/8 "2023-06-19T22:40:31Z")

</div>

> [@paul-griffith](#):
>
> is more Java code

I don't have a web page to test this on, but probing the component with `print dir(frame.get())` I see two methods that look useful: `execute` and `executeJavaScript`. Would you guess that execute is actually the correct one?

> **Full Console Output**
>
> ```auto
> [' __class__', ' __copy__', ' __deepcopy__', ' __delattr__', ' __doc__', ' __ensure_finalizer__', ' __eq__', 
> ' __format__', ' __getattribute__', ' __hash__', ' __init__', ' __ne__', ' __new__', ' __reduce__', 
> ' __reduce_ex__', ' __repr__', ' __setattr__', ' __str__', ' __subclasshook__', ' __unicode__', 'browser', 
> 'children', 'class', 'close', 'closed', 'createJsProxyFunction', 'createJsProxyObject', 'document', 
> 'domContext', 'equals', 'execute', 'executeJavaScript', 'find', 'findImpl', 'getClass', 'hasSelection', 
> 'hashCode', 'html', 'id', 'inspect', 'isClosed', 'isCommandEnabled', 'isMain', 'json', 'loadData', 'loadHtml', 
> 'loadUrl', 'localStorage', 'main', 'name', 'notify', 'notifyAll', 'of', 'onEvent', 'parent', 'print', 'renderProcess', 
> 'selectionAsHtml', 'selectionAsText', 'sessionStorage', 'toString', 'unregister', 'wait']
> 
> ```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 19, 2023, 10:49pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/9 "2023-06-19T22:49:16Z")

</div>

> [@justinedwards.jle](#):
>
> `"documentElement.findElementById('firstname').ifPresent(element ->((InputElement) element).value('John'));"`

I mean that this bit is still Java code. The point of the 'executeJavaScript' function is that you provide JS code (as a string) that will be run directly on the webpage.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 19, 2023, 11:01pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/10 "2023-06-19T23:01:07Z")

</div>

> [@paul-griffith](#):
>
> provide JS code (as a string)

Understood. I've corrected the above untested answer.

---

<div class="post-metadata">

**Author:** ![Micah\_Carr](https://avatars.discourse-cdn.com/v4/letter/m/bbe5ce/32.png) [@Micah\_Carr](https://forum.inductiveautomation.com/u/Micah_Carr)\
**Post date:** [June 20, 2023, 2:08pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/11 "2023-06-20T14:08:05Z")

</div>

With this I was able to fill in the text field.

When I attempt to fire the click event on the button, microsoft says it is an invalid username/email. But if I click on the button manually, it accepts it.

filling the password box doesn't seem to work either.  
(edit: It seems it will not fill in any of the text boxes after I click on the page. Until reloading the page)

```auto
if event.propertyName == "testbool":
	def fill_form():
		from time import sleep
		
		print "Starting login attempt"
		
		webComponent = event.source #replace with relative path to your component
		webbrowser = webComponent.browser
		frame = webbrowser.focusedFrame()
		
		if frame.isPresent():
			print "frame present"
			# fill email
			frame.get().executeJavaScript("const element = document.getElementById('i0116'); if (element !== 'null') {element.value = 'user@email.com';}")
			sleep(1)
			
			# press "next" button
			frame.get().executeJavaScript("const element2 = document.getElementById('idSIButton9'); if (element2 !== 'null') {element2.click();}")
# sleep(5)
#			
# # enter password
# frame.get().executeJavaScript("const element3 = document.getElementById('i0118'); if (element !== 'null') {element3.value = 'password';}")
# sleep(1)
#			
# # click "sign in" button
# frame.get().executeJavaScript("const element2 = document.getElementById('idSIButton9'); if (element2 !== 'null') {element2.click();}")
	
	
	if "authorize?client" in event.source.currentUrl:
		system.util.invokeAsynchronous(fill_form)

```

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/d/cd767f0290357d3137df9aa552b5f7e37c88aa5d.png)

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 20, 2023, 2:23pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/12 "2023-06-20T14:23:51Z")

</div>

I'm glad we have been able to make some progress on the problem. Unfortunately, I don't have an adequate test environment for this usage case, so I doubt I will be of much further assistance. My guess is that the problem is with my implementation of javascript, so perhaps somebody who works with this language on a regular basis, such as @victordcq, can offer you further guidance from here.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [June 20, 2023, 3:02pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/13 "2023-06-20T15:02:15Z")

</div>

ive done stuff similar like this before.

ill come back here tommorow

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [June 21, 2023, 7:28am UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/14 "2023-06-21T07:28:39Z")

</div>

eh we did this quite different...

Anyways the problems with accessing the browser in vision is that its super hard to know when the browser finishes with something.  
So this sleep thing is really not consistent.

the only kinda consistent thing i was able to do was access the localstorage( nd i assume cookies will be the same)  
since those work before the page is fully loaded.  
so like that you could technically log in even before the page is loaded and store the log in in one of those (you'll ahve to know what the site uses for this tho, and how to do that for microsoft)

idk what ms uses, but you can probably even get a token through python/java code

```auto
from com.teamdev.jxbrowser.navigation.event import NavigationFinished
from com.teamdev.jxbrowser.event import Event, Observer

class obs(Observer):	
	def __init__ (self,fn):   		
   		self.on=fn 
def login(ev):
  key= ?
  token= ?
  # if you need it... ev.frame().executeJavascript("")
  storage= ev.frame().localStorage()
  storage.putItem(key,token)
browser = system.gui.getParentWindow(event).getComponentForPath('Root Container.Web Browser').browser
browser.navigation().on(NavigationFinished,obs(lambda ev: login(ev)))

```

note this is for doing stuff before the page is loaded, you want be able to acces any buttons

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [June 21, 2023, 8:37am UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/15 "2023-06-21T08:37:57Z")

</div>

> [@Micah\_Carr](#):
>
> But something changed this weekend and it no longer works.

if its just a minor thing tho and it has worked before, i suggest trying to increase the sleep between actions and maybe check if the element id's are still the same

---

<div class="post-metadata">

**Author:** ![Micah\_Carr](https://avatars.discourse-cdn.com/v4/letter/m/bbe5ce/32.png) [@Micah\_Carr](https://forum.inductiveautomation.com/u/Micah_Carr)\
**Post date:** [June 21, 2023, 1:20pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/17 "2023-06-21T13:20:53Z")

</div>

In the past, It would just login on it's own, without any scripts.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 21, 2023, 1:22pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/18 "2023-06-21T13:22:17Z")

</div>

That might be related to a Windows security hole that got plugged, cutting off certain auto-login functions. I don't recall the details (a couple months or so ago?).

---

<div class="post-metadata">

**Author:** ![Micah\_Carr](https://avatars.discourse-cdn.com/v4/letter/m/bbe5ce/32.png) [@Micah\_Carr](https://forum.inductiveautomation.com/u/Micah_Carr)\
**Post date:** [June 21, 2023, 1:59pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/19 "2023-06-21T13:59:32Z")

</div>

Yesterday, I implemented a java.awt robot to simulate a user input to login. It is working, but I can foresee a few issues.

1. If a user interacts with the mouse/touchscreen during the login process, it might be interrupted and not login properly.

2. I have no way to check if an element is visible, since the username and password are on different elements that become visible at different times, It might be possible for the password to be typed in the username field or typed in before the page is ready to receive it.

3. This will also only work on the expected screen size. Which is not a problem for me, as all stations running this project use the same screen.

Property change on web browser component

```auto
if event.propertyName == "current_URL":
	
	from time import sleep
	from java.awt import Robot
	from java.awt.event import InputEvent
	from java.awt.event import KeyEvent
	import subprocess
	
	def login():
		username = "username"
		password = "password"
		
		def copy_paste(txt):
			cmd='echo ' + txt.strip()+'|clip'
			subprocess.check_call(cmd, shell=True)
			
			robot.keyPress(KeyEvent.VK_CONTROL)
			robot.keyPress(KeyEvent.VK_V)
			robot.keyRelease(KeyEvent.VK_CONTROL)
			robot.keyRelease(KeyEvent.VK_V)
			
			robot.keyPress(KeyEvent.VK_ENTER)
			robot.keyRelease(KeyEvent.VK_ENTER)
		
		# make sure login screen is still present
		if "authorize?client" in event.source.currentUrl:
			
			# Make component over web-component invisible so clicks can go through to web-component
			event.source.parent.getComponent('Swipe Scroll Area').visible = False
			
			robot = Robot()
			
			# Get coordinates of web-component position in ignition window
			# add mouse coordinates within web-page to click on textbox
			comp_coords = misc.get_abs_comp_coords(event)
			new_x = comp_coords[0] + 500
			new_y = comp_coords[1] + 570
			
			# move to textbox and click
			robot.mouseMove(new_x, new_y)
			robot.mousePress(InputEvent.BUTTON1_MASK)
			robot.keyRelease(InputEvent.BUTTON1_MASK)
			
			# copy username to clipboard and paste, then press enter
			copy_paste(username)
			
			# copy password to clipboard and paste, then press enter
			sleep(2)
			copy_paste(password)
			
			#accept "stay logged in" prompt
			sleep(2)
			robot.keyPress(KeyEvent.VK_ENTER)
			robot.keyRelease(KeyEvent.VK_ENTER)
			
# event.source.parent.getComponent('Swipe Scroll Area').visible = True
			
			
		
	
	def login_async():
		system.util.invokeAsynchronous(login)
	
	# if login page is present, invoke async login function later 
	if "authorize?client" in event.source.currentUrl:
		event.source.parent.getComponent('Swipe Scroll Area').visible = False
		system.util.invokeLater(login_async, 5000)
	
	# if no login page is present, make component over web-component visible to allow swipe scrolling
	elif "login.microsoftonline.com" not in event.source.currentUrl:
		def clicks_for_scroll():
			robot = Robot()
			robot.mouseMove(430, 1000)
			
			robot.mousePress(InputEvent.BUTTON1_MASK)
			robot.keyRelease(InputEvent.BUTTON1_MASK)
			
			robot.mouseMove(430, 1265)
			robot.mousePress(InputEvent.BUTTON1_MASK)
			robot.keyRelease(InputEvent.BUTTON1_MASK)
		
		event.source.parent.getComponent('Swipe Scroll Area').visible = True
		
		#needed to insure swipe scrolling works.
		system.util.invokeLater(clicks_for_scroll, 1000)

```

"misc" script

```auto
# gets coordinates of a component from an event relative to the ignition window
def get_abs_comp_coords(event):
	
	window = system.gui.getParentWindow(event)
	
	root_container = window.getRootContainer()
	
	container = event.source
	
	
	x = window.getX()
	y = window.getY()
	
	while container != root_container:
		
		x += container.x
		y += container.y
		
		container = container.parent
	
	
	return [x, y]

```

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [June 21, 2023, 2:23pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/20 "2023-06-21T14:23:31Z")

</div>

Idk what has changed.

But usually authentication for iframes (which is what the browser component basicly is) is done through temporary tokens. Be it stored through localstorage/cookies (with jwt which i used but not for ms). Or by creating a unique and temporary link.

Im pretty sure microsoft should have something like that. but its probably not something trivial to do

> **[What is single sign-on? - Microsoft Entra](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/what-is-single-sign-on)**
>
> Learn about single sign-on for enterprise applications in Azure Active Directory.

> **[Azure AD Connect: Seamless single sign-on - Microsoft Entra](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/connect/how-to-connect-sso)**
>
> This topic describes Azure Active Directory (Azure AD) Seamless single sign-on and how it allows you to provide true single sign-on for corporate desktop users inside your corporate network.

> **[Re: Is it possible to use an API Bearer to load a report preauthenticated](https://community.fabric.microsoft.com/t5/Developer/Is-it-possible-to-use-an-API-Bearer-to-load-a-report/m-p/944286)**
>
> Unfortunately I don't have an update as I can't raise a ticket to microsoft and I haven't got an answer here as yet. For my solution I ended up calling the browser and prompting the user to sign in (for a second time) which is a bit cumbersome but it...

meh, seems a bunch of work

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 21, 2023, 2:39pm UTC](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219/21 "2023-06-21T14:39:31Z")

</div>

I commend you for getting out of the box, and while I agree with Victor that robot doesn't seem like the ultimate approach, this does seem like a decent work around. With the exception of the occasional hiccups you've mentioned, this should buy you all the time you need to work out a proper behind the scenes handshake.

[Next page](https://forum.inductiveautomation.com/t/web-browser-component-login-to-website/75219.md?page=2)
