# PLC Tag AD Authentication

**URL:** <https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233>\
**Category:** Ignition\
**Created:** [January 22, 2025, 3:01pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233 "2025-01-22T15:01:27Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 3:01pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/1 "2025-01-22T15:01:27Z")

</div>

Hello I am trying to figure out if there is a way I can have a username and password entered in a PLC and have Ignition authenticate the user using an already configured active directory. I know this is not the ideal way to do things just looking for some temporary solutions.

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [January 22, 2025, 3:49pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/2 "2025-01-22T15:49:59Z")

</div>

I would think that's possible. One thing you'll have to be careful with is that each client would need to point to a unique set of PLC tags (unless you will only have a single client, then that's easier). But essentially, you'd need to trigger a login using a PLC tag that's set up with a Client Tag Change Script. In that client tag change script, you'd then read the values of the username and password entries to automatically log the new user in using system.security.switchUser.  
(I believe this only works in Vision - I don't think there's a way to handle this with Perspective since perspective uses Identity Providers instead of the classic login.)

> **[system.security.switchUser | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-security/system-security-switchUser)**
>
> Attempts to switch the current user on the fly.

---

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 6:02pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/3 "2025-01-22T18:02:43Z")

</div>

This looks along the right path but what I am really looking to do is write a value to the plc based on whether the username and password are correct. For example if I enter a valid combination then a 1 would be written to the PLC tag or a specific value based on what AD group the user is a part of.

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [January 22, 2025, 6:04pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/4 "2025-01-22T18:04:52Z")

</div>

You'll probably want to use this instead so that it doesn't actually log the user into the Ignition client, but instead just validates the login is correct.

> **[system.security.validateUser | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-security/system-security-validateUser)**
>
> Tests credentials (username and password) against an authentication profile.

Although, this won't check roles, but only validates the login (user/password) are correct. I don't know if there's a way to validate roles without actually logging in the user, but there might be an undocumented way of doing so.

---

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 7:02pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/5 "2025-01-22T19:02:53Z")

</div>

Can this be used in tag script? This is what I entered into the script but does not seem to work.

```python
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
	CV = currentValue.value
	currentUser = "[WTA]Authentication/Username/STRING"
	password = "[WTA]Authentication/Password/STRING"
	if CV == 1:
		valid = system.security.validateUser(currentUser, password)
		if valid:
	   		system.tag.write("[WTA]Authentication/Authentication_Level", 17)
		else:
	   		system.tag.write("[WTA]Authentication/Authentication_Level", 99)

```

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [January 22, 2025, 7:10pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/7 "2025-01-22T19:10:58Z")

</div>

Regarding your question, are you proposing to hold a username and plain-text password in the PLC?  
This seems very insecure, as anyone with the ability to view the PLC status could read it and have the ability to log in to any company systems that AD gives them rights for. I doubt you'll win Cyber Security Team recognition award - or not the good kind.

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [January 22, 2025, 7:16pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/8 "2025-01-22T19:16:02Z")

</div>

While I agree with @Transistor on this from a cybersecurity standpoint, I'm guessing you're trying to workaround some other system that you need some sort of authentication with AD that's otherwise not possible. Ideally if you were only using Ignition, you could use the currently logged in user in Ignition to send a value to the PLC for the authentication level, but that's between you and your cybersecurity team (if you have one).

Here's an updated script. You need to read the values of your currentUser and currentPass (you can't just use the string values as they'll try to use that literal tag as the username and password). Then you can use writeAsync to update your PLC (`system.tag.write` is a deprecated function unless you're using an older version of Ignition like 7.9).

```python
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
	CV = currentValue.value
	currentUser = "[WTA]Authentication/Username/STRING"
	currentPass = "[WTA]Authentication/Password/STRING"
	username, password = [tag.value for tag in system.tag.readBlocking([currentUser, currentPass])]
	if CV == 1:
		valid = system.security.validateUser(username, password, 'default')
		if valid:
			system.tag.writeAsync(["[WTA]Authentication/Authentication_Level"], [17])
		else:
			system.tag.writeAsync(["[WTA]Authentication/Authentication_Level"], [99])

```

Edit: Added the 'default' user source as an example for the `validateUser` function.

---

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 7:38pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/9 "2025-01-22T19:38:40Z")

</div>

Yes I agree with @Transistor as well but these are the situations we get in sometimes.

I've added the below script as suggested but I still do not get any results.

```python
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
	CV = currentValue.value
	currentUser = system.tag.readAsync("[.]Username").value
	currentPass = system.tag.readAsync("[.]Password").value
	username, password = [tag.value for tag in system.tag.readBlocking([currentUser, currentPass])]
	if CV == 1:
		valid = system.security.validateUser(username, password)
		if valid:
			system.tag.writeAsync(["[.]Authentication_Level"], [17])
		else:
			system.tag.writeAsync(["[.]Authentication_Level"], [99])

```

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [January 22, 2025, 7:41pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/10 "2025-01-22T19:41:10Z")

</div>

The manual suggests using a authProfile as an optional argument for gateway scope scripting ([system.security.validateUser | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-security/system-security-validateUser#syntax-gateway)).

Since you're executing from a Tag Script, there is no associated project, so I would try to specify an authProfile and see what happens.

---

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 7:44pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/11 "2025-01-22T19:44:42Z")

</div>

I wondered that as well but was unsure what the authProfile would be. Is the name found on the gateway as the System Identity Provider?

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [January 22, 2025, 7:51pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/12 "2025-01-22T19:51:39Z")

</div>

It would be the name of the user source that you're authenticating against.

Example using the default internal user source:  
`valid = system.security.validateUser(username, password, 'default')`

---

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 7:59pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/13 "2025-01-22T19:59:36Z")

</div>

This did not work either. Thanks for the input, I'll keep trying.

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [January 22, 2025, 8:16pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/14 "2025-01-22T20:16:19Z")

</div>

> [@wayne\_heath](#):
>
> `username, password = [tag.value for tag in system.tag.readBlocking([currentUser, currentPass])]`

Well, it does work. I can confirm it does. You need to revisit your earlier code because there are fundamental issues with it. Specifically,

```python
username, password = [tag.value for tag in system.tag.readBlocking([currentUser, currentPass])]

```

readBlocking accept a list of tagPaths, but you are passing a list of tag values (currentUser and currentPass)

This may work better for you:

```python
username, password = [tag.value for tag in system.tag.readBlocking(["[.]Username", "[.]Password"])]

```

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [January 22, 2025, 8:23pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/15 "2025-01-22T20:23:13Z")

</div>

As @code_skin pointed out, since you didn't copy my code and made changes to it on your own, you converted the currentUser and currentPass to actual values vs I was modifying what you gave me and passed the tag paths into the `readBlocking` function. (You changed those lines to read the tags individually, which isn't a big deal on something small like this, but typically you'd read them in one call rather than 2 separate calls.) When doing it that way, you don't need the extra line I was using then to read those values.

---

<div class="post-metadata">

**Author:** ![wayne\_heath](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wayne_heath/32/26459_2.png) [@wayne\_heath](https://forum.inductiveautomation.com/u/wayne_heath)\
**Post date:** [January 22, 2025, 8:42pm UTC](https://forum.inductiveautomation.com/t/plc-tag-ad-authentication/101233/16 "2025-01-22T20:42:43Z")

</div>

My mistake, it is working now. Thank you both for your help, greatly appreciated.
