# Session prop change script has no system.security.logout()?

**URL:** <https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [December 20, 2022, 6:48am UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818 "2022-12-20T06:48:21Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [December 20, 2022, 6:48am UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/1 "2022-12-20T06:48:21Z")

</div>

I'm trying to create my own auto-logout functionality, as our customer wants specific clients to be able to remain logged in under certain usernames.

So I added a custom session prop to act as a trigger to log the user off, however I found that `system.security.logout()` isn't available in the session prop's on change script scope..? Not sure why this wouldn't have access to this, since it has full awareness of the session?

Error running property change script on session.custom.security.autoLogout.logoutUserTrigger: Traceback (most recent call last): File "function:valueChanged", line 2, in valueChanged AttributeError: 'com.inductiveautomation.ignition.common.script.Imm' object has no attribute 'logout'

I don't really want to have to configure some obscure method using message handlers ☹

Edit: Even a Session Event message handler doesn't have the `logout` function available to it. I'm confused... Aside from adding a message handler to my navigation View which is absurd, I'm not sure how else I can do this?

---

<div class="post-metadata">

**Author:** ![djs](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@djs](https://forum.inductiveautomation.com/u/djs)\
**Post date:** [December 20, 2022, 2:53pm UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/2 "2022-12-20T14:53:25Z")

</div>

According to the docs [system.security.logout()](https://docs.inductiveautomation.com/display/DOC81/system.security.logout) is Vision specific. You might want to use [system.perspective.logout()](https://docs.inductiveautomation.com/display/DOC81/system.perspective.logout) if you're using Perspective.

---

<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:** [December 20, 2022, 4:53pm UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/3 "2022-12-20T16:53:00Z")

</div>

In 8.3, the plan is to move a lot of these misleading 'legacy' functions to `system.vision` for clarity.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [December 20, 2022, 7:30pm UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/4 "2022-12-20T19:30:05Z")

</div>

Derp, of course! Rookie mistake, thanks guys 🙂

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [December 21, 2022, 1:21am UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/5 "2022-12-21T01:21:23Z")

</div>

New problem. Using `system.perspective.logout()` (or `system.perspective.print` for that matter) on my session prop change script results in this:

```auto
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 2, in valueChanged at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.lambda$operateOnPage$0(AbstractScriptingFunctions.java:64) at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnSession(AbstractScriptingFunctions.java:120) at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnPage(AbstractScriptingFunctions.java:47) at com.inductiveautomation.perspective.gateway.script.PerspectiveScriptingFunctions.logout(PerspectiveScriptingFunctions.java:475) at jdk.internal.reflect.GeneratedMethodAccessor692.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No perspective page attached to this thread.

at org.python.core.Py.JavaError(Py.java:547)

at org.python.core.Py.JavaError(Py.java:538)

at org.python.core.PyReflectedFunction. __call__ (PyReflectedFunction.java:192)

at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction. __call__ (ScriptManager.java:552)

at org.python.core.PyObject. __call__ (PyObject.java:446)

at org.python.core.PyObject. __call__ (PyObject.java:450)

at org.python.pycode._pyx2668.valueChanged$1(:2)

at org.python.pycode._pyx2668.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyBaseCode.call(PyBaseCode.java:306)

at org.python.core.PyFunction.function ___call__ (PyFunction.java:474)

at org.python.core.PyFunction. __call__ (PyFunction.java:469)

at org.python.core.PyFunction. __call__ (PyFunction.java:464)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:846)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:828)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:828)

at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:1009)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:893)

at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:147)

at com.inductiveautomation.perspective.gateway.model.PropertyChangeScript.access$001(PropertyChangeScript.java:30)

at com.inductiveautomation.perspective.gateway.model.PropertyChangeScript$ScriptSequencer.run(PropertyChangeScript.java:156)

at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)

at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:58)

at java.base/java.lang.Thread.run(Unknown Source)

Caused by: org.python.core.PyException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No perspective page attached to this thread.

... 27 common frames omitted

Caused by: java.lang.IllegalArgumentException: No perspective page attached to this thread.

at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.lambda$operateOnPage$0(AbstractScriptingFunctions.java:64)

at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnSession(AbstractScriptingFunctions.java:120)

at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnPage(AbstractScriptingFunctions.java:47)

at com.inductiveautomation.perspective.gateway.script.PerspectiveScriptingFunctions.logout(PerspectiveScriptingFunctions.java:475)

at jdk.internal.reflect.GeneratedMethodAccessor692.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at org.python.core.PyReflectedFunction. __call__ (PyReflectedFunction.java:190)

```

Using this in the change script, I can see a valid session ID is printed, but the logout fails. I'm not sure where to go to from here as I can't get a page id from a session prop 😕 I wouldn't have thought that a page id is even needed, since it's the session that is logged out of, right?

```auto
id = self.props.id
print 'Session ID:', id
system.perspective.logout(sessionId = id)

```

---

<div class="post-metadata">

**Author:** ![djs](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@djs](https://forum.inductiveautomation.com/u/djs)\
**Post date:** [January 3, 2023, 9:00pm UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/6 "2023-01-03T21:00:41Z")

</div>

Seems like a pageId is required for the logout function...

You can get pageIds from [system.perspective.getSessionInfo()](https://docs.inductiveautomation.com/display/DOC81/system.perspective.getSessionInfo). You might be able to get what you want if you iterate over those and log the user out for each page. Perhaps something similar to this?

```auto
sessionId = self.props.id
pageIds = []
	
#Get page IDs
for session in system.perspective.getSessionInfo():
	if session['id'] == sessionId:
		pageIds = session['pageIds']
		break
#Logout each page
for pageId in pageIds:
	system.perspective.logout(sessionId, pageId)

```

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [January 3, 2023, 10:12pm UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/7 "2023-01-03T22:12:27Z")

</div>

Perhaps it's my misunderstanding, but I would have thought that logging in would be scoped to a session, not a page of a session? More a question for IA guys, but thanks for the code

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [January 3, 2023, 11:18pm UTC](https://forum.inductiveautomation.com/t/session-prop-change-script-has-no-system-security-logout/67818/8 "2023-01-03T23:18:41Z")

</div>

The session doesn't have it's own thread pool - all scripting needs to be supplied a page on which to act. We provide this in many instances behind the scenes by providing access to the page thread for Children of the page (components, View), but we can't do that for session events, Gateway Events, or Tag Change scripts because they obviously have no idea about which page is requesting the script to be executed.

If you invoke `system.perspective.logout()` from a component, you'll encounter no issue because we've handed the component a thread from the Page's allocated pool to execute the script with, and all of the relevant information is available on that thread.

And so I think the issue isn't that `system.perspective.logout()` needs the pageId arg because it cares about the page per se, rather, the script eventually gets run _on that Page's thread pool, where it has access to the needed information_.

You should be able to amend that script slightly and get the same result:

```auto
for session in system.perspective.getSessionInfo():
	if session['id'] == sessionId:
        system.perspective.logout(pageId=session['pageIds'][0])

```
