Cookies

We use analytics to see how the site is used so we can improve it.

Skip to content
Renada

Why your NinjaOne to HaloPSA device matching is case sensitive

A step by step walkthrough for MSPs who want NinjaOne assets to automatically attach to the right HaloPSA user, not just import as orphaned devices

17 December 2024 26 min watch Connor Fagan

The short version

This tutorial walks through matching NinjaOne devices to HaloPSA users so technicians can pick the right asset when logging a ticket. It covers building a custom field and automation in NinjaOne, mapping that field inside the HaloPSA NinjaOne integration, and getting the UPN into the Network Login field on the user record, including a case sensitivity issue that silently breaks the match.

What you'll take away

  • The setting behind the matching

    HaloPSA's NinjaOne integration has an option to attempt to match the user based on last logged in user, which compares a Ninja custom field against the Windows Username field on the user record.

  • Custom field must be text, device scoped

    Create the NinjaOne custom field as a text field, set automations to write, API to read, and definition scope to device.

  • Kelvin's PowerShell script does the trick

    The script runs as system but impersonates the logged in user so who am i /upn returns the actual person, not the system account.

  • Run it on user login, not on a schedule

    Scheduling the script hourly can miss users who log in and out within that window, so the automation triggers on user login instead.

  • Field name matching is case sensitive in HaloPSA

    Typing last Logged in user instead of last logged in user in the HaloPSA field mapping silently leaves the value blank on import.

  • UPN has to reach both sides of the match

    HaloPSA only links an asset to a user when the Network Login field on the user record matches the value pulled from NinjaOne, so CSP tenants need the UPN mapped in the Azure Active Directory integration too.

Key insights from the episode

  1. Build the NinjaOne custom field as text, with automations set to write and API set to read, scoped to device.

  2. Name the custom field exactly the same in NinjaOne and in the HaloPSA NinjaOne integration mapping, because the match is case sensitive.

  3. The field that HaloPSA actually stores this against is labelled Windows Username on screen but is called Network Login at the field level.

  4. Use who am i /upn rather than the older netbios-style who am i output, since UPN equals email address for Microsoft 365 users on Azure AD.

  5. Schedule the NinjaOne automation to run on user login rather than hourly, so short logins are not missed.

  6. For Microsoft CSP tenants, map the Azure AD field User Principal Name to the Login field inside the HaloPSA Azure Active Directory integration.

  7. For heavy on premise AD environments where the domain is not the email address, import Network Login values via CSV matched on first and last name instead.

  8. The NinjaOne integration in HaloPSA only runs once a day by default, so recent logins may not appear until the next sync unless you run the Halo integrator on premise.

Questions people actually ask

How do I match NinjaOne devices to users in HaloPSA?

You create a text custom field in NinjaOne that captures the logged in user's UPN, populate it with a scheduled automation that runs a PowerShell script on user login, then map that custom field in the HaloPSA NinjaOne integration to the Network Login field on the HaloPSA user record. When the two values match, HaloPSA links the asset to the user automatically on import.

Why is my NinjaOne custom field showing blank in HaloPSA after import?

The most common cause is a case mismatch between the NinjaOne custom field name and the name entered in the HaloPSA NinjaOne integration mapping. HaloPSA needs the field name, not the label, copied exactly as it appears in NinjaOne, including capitalisation.

What is the difference between who am i and who am i /upn in this setup?

Who am i returns an old style netbios domain and username combination, which is not useful for matching against Microsoft 365 accounts. Who am i /upn returns the user principal name, which equals the user's email address for Azure AD accounts, and is what HaloPSA needs in the Network Login field.

Why does the PowerShell script run as system instead of the logged in user?

Standard users logged into a NinjaOne managed device cannot update NinjaOne custom fields directly, so the script has to run at system level to have permission to write to the field. It then impersonates the logged in user so the who am i /upn output reflects that person rather than the system account.

How often does HaloPSA update the last logged in user from NinjaOne?

The NinjaOne integration inside HaloPSA currently only syncs once a day by default. If you need more frequent updates you either need to ask Halo about increasing that frequency or run the Halo integrator on premise yourself and set your own schedule.

Why is HaloPSA not matching a device to a user even though the fields look correct?

Check that the user exists at the same site as the asset in HaloPSA, since the match depends on site as well as field value. Also confirm the Network Login value on the user record matches the last logged in user value from NinjaOne exactly, though this particular comparison did not appear to be case sensitive.

Do I need Microsoft CSP integration for this to work in HaloPSA?

No, but if you do use Microsoft CSP you can map the Azure AD User Principal Name field directly to the Login field in the HaloPSA Azure Active Directory integration to keep Network Login populated automatically. Without CSP, you can import Network Login values via CSV instead, matching users on first and last name.

Full transcript

4,605 words

Read full transcript

Connor: Hello, good day. For it is I. Thank you for joining me. I'm excited to be able to deliver this video. Honestly I think the inner nerd is definitely flourished in me over the past few weeks doing this.

Before we get stuck into it too much, a big thank you to the guys over at NinjaOne, Stephen and Luke, for giving us a hand with this and chatting with Halo on our behalf. Tim from Halo for doing the dev work on this, getting this custom fields mapped through. Thank you to Kelvin from CIPP. We've stolen some of his PowerShell and he helped Robbie a little bit understanding how that all works. And I suppose thank you Robbie on our side for doing all of the documentation, the testing, the guides, all of that fun stuff.

But what am I talking about? I am talking about matching assets in NinjaOne to the users inside of Halo, inside of Halo, so that when we log a ticket for that user we can pick their asset. Something that seems quite simple but has actually been a long, windy road of complexity. But we've now put all the pieces of the puzzle together for you.

Before we get stuck into the how to do it, I'm going to show you what it's actually doing. Just going to jump into Halo into my test environment and I've got CMD open here. So what's going on? Well, in the NinjaOne integration, if I just go to that configuration very quickly, there is a setting in there which basically says if I could find NinjaOne here. We go. There's a setting in here which basically says attempt to match the user based on the last logged in user.

Okay, now what that is actually doing is it's saying match the field last logged in user, which we can now define to the field inside of Halo which is Windows username. Now what that field actually is at the user level is Network login. Don't get me started. Just trust me. It is the network login field.

And what NinjaOne pulls through, or what NinjaOne used to, or what NinjaOne still does pull through for last logged in user, I'll put it on annual cost, it doesn't matter. Is the field or the prefix. AURAD back slash Connor Fagan. Now this is with Entra ID. And what it does is it for the who am I response. So if I go to CMD and type in who am I, it pulls in I believe it's NetBIOS and username or bias and profile. I can't fully remember the syntax for this honestly, but this is like pre-2000 stuff right? We don't need this. What we need is the UPN.

So if we do who am I UPN, this is actually what we need. Now for anyone in Microsoft 365 who's using an Entra ID, their UPN should always be their email address. If you have a lot of on-premise clients, we'll have to discuss about this later. But the UPN is basically the user log name plus the domain. Now their domain could be contoso or local if they're old architectures. We'll touch on how to handle this separately.

The first bit of this video mainly is how we get the who am I UPN to come from NinjaOne instead of this field here, and how we get this to be under the Network login field inside of HaloPSA. We have documented all of this though for you. So there's going to be a link in the description below. So we've written a full written guide on this, which basically is linked just underneath here, and it'll step by step all of this out. And it also has the PowerShell script, which is the little bit we've done it re, but mainly just borrowed this from Kelvin. Thank you again for making this public Kelvin. This has been a huge help in all of this.

So let's stop rambling. Let's get stuck into how to do all of this. So part one is we need to be able to somehow display the UPN of the logged in user inside of NinjaOne, and to do that we need to make a custom field inside of NinjaOne.

So let's start with phase one, stage one: the custom field. We're going to either want to make a role-based custom field or a global custom field. Now the only difference is with a role-based custom field you can say only show me this field on certain asset types or whatever we define. For today I'm just going to use Global for this test, but in the guide we do actually use a role custom field just because it's a little bit easier to work with. It's the same outcome though fundamentally.

So what we're going to do is you're going to want to click on add in the top right and you want to click add a field. And you want to type in the label. Um, whatever you like, so this could be last logged in user. Okay. What is really important though is that for the name you make a note of this so you can call this whatever you want. I recommend calling it last logged in user just so it follows through on this video, but it's up to you what you want to call it in here.

And then what you want to do is basically say that this is a text field. So if we just go to here and type in text, make sure this is a text field. And as you'll see here, we've got one called last logged in user. And then once you make that, it's very, very particular that you set it up with these settings.

Technician can be read only or editable. That is completely up to you. What this means is when we go to the device, so this is my device here, and we click edit in the top right, can we edit this custom field or not inside of NinjaOne? Or sorry, can the technician edit it? It's not really that important.

Automations. So this is when we're running an automation inside of NinjaOne. What can NinjaOne do to this custom field? Uh, we want to write to it. So we're basically going to run a PowerShell script which writes the UPN to this field.

Then we have the API. So when Halo is trying to get this information, what can it do to this custom field? Well, we just want to be able to read from it. And again you can do read only, uh, read, write if you want to. We're trying to be as granular as we can here.

And then the uh definition scope is just going to be device. And that is all we need to worry about on the side of this custom field.

Once we've made the custom field, we then want to go to library and we want to go down to automations. And we basically want to make a new automation. So what you want to do is click add on the right hand side and you want to do a new script.

Once you do that you will get this page here. So give this script a name. Whatever your heart desires, doesn't really matter. Give it a category. This is just so you know where to find it and know where to look for it. Um, I've just done mine as uncategorised. Depending on how you've built out your NinjaOne and what other scripts you've got, pick a folder essentially that keeps that contained.

The language is PowerShell. This is in fact a PowerShell script. And the operating system is going to be there for Windows. In the architecture, um, this should work on both. I don't see why it wouldn't. So just select all.

And then what you basically want to do is go to our documentation once again linked below, click on the copy in the top right hand corner, go back into NinjaOne, and then copy that script in here like for like.

Now you remember at the start of this we made a custom field and we gave it a name. And that name is what is referenced in this script. Now this script is very, very complicated and very, very clever, I must say. But essentially what this is doing is this. It's running a script at a system level but is impersonating, why it's running it as a user at the system level. Um, I believe that's the right way to word that. Long story short, users logged into the system can't update custom fields in NinjaOne. So we need to run it at a system level to do that. The problem is once we run the script to a system level, the who am I or who am I UPN returns the system, not the logged in user. So we're kind of tricking this to say run it as the last logged in user but with the permissions of the system. I hope all that bit makes sense.

And I'll be honest with you, I've not gone through this line for line. This is Kelvin's wizardry. All I can tell you is it works. Now take that as you will. Run this at your own risk. We're using it, it's fine. All we've basically wrote is this tiny bit at the bottom. I can't take credit for Kelvin's work. But what we're basically saying is run a who am I UPN. If the device there on doesn't return anything when they do this, then just output the who am I and update that to the NinjaOne property set.

So this is a NinjaOne function. So update the custom field last logged in user with the output of that. So essentially stick Connor at Ren dot co dot UK into the custom field last logged in user. I hope all that makes sense.

Once you've done that, we've now got the custom field and we've now got the script. We now need to tie it all together so this script actually runs on a particular device. And what we've said, or the way we think the best way to do this is is if you go to devices. Um, no I want to go to. Um, where did I do it? Oh, let me check my guide where do we do this next bit? You can tell I don't use this every single day, can't you? We do this, we do that, we do this. We need to go to policies, policies, policies. Agent policies. And we want to basically apply this to whatever policy we want. We've applied this in our environment to the Windows workstation policy. And we're saying this is a scheduled automation.

So what you do is you click on here, add a scheduled automation. And then we want to select that script we've just done. So we want to select that get last logged in user. We want to run it as the system. And we want to basically click apply. And then we say when do we want this automation to run? Well, we only really want to get the last logged in user when people log in or get the current logged in user. Sorry, it's kind of what we're actually running is get current logged in user. When someone new logs in, we don't want to run this every hour because someone could log in and out within the hour so it wouldn't apply.

So what we say is run on user login, which is demonstrated down where do we put it in the guide here. So run on user login and give it a name. And then away we go.

Once we've done that and we've got the automation set up on that device, what we can do is we can go to one of our devices inside of NinjaOne. We can click on the run automation and run automation script. And we can then select our script and click run and then press yes. And then we can wait a second. So if we go to the overview, you will see that the um script has run. So the action has completed, get or run get the last logged in user. And then what we should notice in here is that it should then pull in either the who am I or the who am I UPN.

Now what we are noticing today, and I'm not sure if this is all the time or just today, this can take up to a minute to populate. So don't panic straight away if it doesn't appear. It's not broken potentially. Um, it just might take a minute to um appear. So I'm just going to pause at 14:07 and refresh this a couple of times just to see how long it takes. And then we'll reconvene in a moment.

And there we go. Look, updated a few seconds ago. And if you can see in the bottom right, it's still 4:07. So less than a minute. But what it's done is it has done what we said it should do and has pulled in our last logged in user, or should I say current logged in user, as Connor at Renada.co.uk, which is me.

So the NinjaOne part is done. We have a script. We have a custom field. We have an automation. It's updating what we want to do inside of here. Now just to add, if this isn't returning information that you need, you can obviously update and amend the script. Um, I know one of my friends suggested maybe you could pull in the primary email address from Outlook. So if they're logged in, um, and you know they maybe a shared device, you could pull in the Outlook email address. Um, you could hard code this here if you want it to every single device. So not have an automation, just have a custom field and you could have this hardcoded and set. For now we're automating it based on either who am I or who am I UPN.

So if they're not on a domain, the UPN won't be returned. It will just pull back in the who am I um or logged in user name. So that is a NinjaOne bit done. We can now close NinjaOne.

The next bit we need to do is inside of HaloPSA. So what we need to do is basically go into uh HaloPSA and go to the NinjaOne integration page. And what we want to do is we want to click add and we want to say NinjaOne custom field.

Now the NinjaOne custom field name. This isn't the label. This is the name. So in our scenario, this is the full string last logged in user, no spaces or anything. That is because in our guide, if you remember at the very start we give it the name last logged in user. So again, whatever you name this custom field name is what has to match inside of Halo.

We then need to map that to a field at the asset level inside of Halo. Now I like to use last logged in user. But if you wanted to you could make a new custom field. It literally doesn't matter. Um, as long as we're putting it somewhere on the asset. Okay. And then we're going to press save.

Now what you will notice unfortunately is when you import device, uh, the NinjaOne custom field is unfortunately blank. It's not returning the value. It does work. I'll demonstrate in a minute. But it is unfortunately blank. We're going to escalate that to Halo. See if they can fix it. But for now that is going to be blank.

Then what we want to do is select the box attempt to match user based on the last logged in user. And then what we want to say is um NinjaOne custom field to use for matching the user. And what we're going to say is make sure it's this here, last logged in user. In reality it's this here. So make sure that the NinjaOne custom field name is what is used inside in here. And again, it might be case sensitive. I don't think it is, but just be case aware. And again, update it here.

Well, that'll look like if all that is working is if I just go to assets and go to delete this one here. That should now be gone. Yeah, prediction is now gone. That's me.

If I go to the NinjaOne integration and if I import devices just down here and then press start, what I should expect is our assets to be imported again. Sorry, that was me testing something. Annual cost, get rid of that. That again, what I would expect is now when I go over to um that asset and look at the field last logged in user, I would expect that to actually be returning Connor. And the fact it hasn't is a interesting quandary. What have I done there?

So just going to go back to our integration very quickly. I'm just going to make sure I haven't mapped anything to that field. N custom field. Let's just do that. Map a NinjaOne custom field last logged in user to the Halo field last logged in user. Save. And just going to try that again.

There we go. Just going to go back to the assets very quickly. Prediction is weirdly not being set. Let me see what I've boiled up in testing and I'll be back in 30 seconds.

Eat my words live on recording. What a professional would do is restart this recording. But we're not going to do that. Um, we're now updating our guide on this one. It took about three seconds to figure this out. Um, but it is what I thought it is. Case sensitive. So what you need to make sure you do is that you copy this field name here. So last logged in user. Again, we're awful human beings. We've got uppercase and lower case and all sorts of camel case going on. But uh, do better than us obviously.

But what you need to make sure you do is just copy this field name and then inside of Halo on the NinjaOne integration on the field, make sure that you copy that exactly as is in here. If it's not 100% matched, it won't work. Also make sure you copy it into this box down here.

And to demonstrate that this is working, if I just find our asset quickly and delete it and import it again, we will hopefully see that the last logged in user is now populating with my email address.

But if I delete that asset and I change logged in to a lowercase L and reimport it, this time I would expect that to be blank. That last logged in user is not set. So be very careful with that one. Um, I'm just going to reimport that now. We should hopefully update that inside of Halo. But it is case sensitive.

There we go, that is now updated correctly. So one last time to really drill this one home: do your NinjaOne custom field mapping to Halo. But the NinjaOne custom field name must exactly match the name of that field inside of NinjaOne, not the label, not the value, the actual name.

Once you've done that, we then have all of our assets inside of Halo um with our last logged in username here. And what this box is saying is, sorry let me go back to that integration very quickly. What this box is now saying is we now want to match this field to the Windows username field at the user level, which is this network login field here.

Now there's a few ways to get this field populated with information. If you're running a lot of on-premise or your customers have a lot of local AD domains and they're domain or fully qualified domain name is not their email address, then you might want to import all of these via CSV. So you might want to do an export of their AD, match it based on first and last name, and then import it here in CSV.

However, if you're using Microsoft 365 CSP, we've got a workaround for you on that one as well. So the final part of this video is getting this network login to be what we need it to be, which in our case is the UPN of that user.

So I'm just going to jump into my sandbox environment where we set up our CSP. Um, I don't actually have our CSP running in our test environment. It kind of terrifies me a little bit. But super simple. All we need to do is go to our CSP integration. Um, if it's not set up, I will link a guide for that also in the comments below. We need to go to the Entra ID page.

Now if you are running Entra ID integrations for your tenants manually, the same process applies right. But all we need to do is we need to basically, and I'll just get rid of this one very quickly, is we need to add a field mapping. And we need to take the Entra ID field of user principal name. I'll zoom in a little bit here. And we need to match that to the login field inside of Halo.

So if I do save in that and then I import users, this is my test or dev environment, but I will show you what happens if we then import all of our users from that um to Halo. I'll stop that there. I demonstrate it. What we should expect now is that Lynn Robbins will have the network login as her UPN, which is here.

Hope that makes sense. Essentially we're trying to get this field populated. And if you're using CSP, we can again, this is in the guide, so don't panic, but we can basically say map their UPN to the login field inside of Halo.

And once you've got that, all of these moving pieces to slide together. So if I now go to an asset and click on the relationships tab, because this user Connor has the network login that matches the last logged in user field inside of NinjaOne, these two will match. Therefore saying this is the owner or the last logged in user of this device.

Now the reason I've written the guide is because this has been the most awkward video of my life to create because there's so many moving pieces. Um, it's been 23 minutes. I do apologise. But to surmise this video: we need to have a custom field inside a NinjaOne to grab the UPN. We need to make sure we map that to the NinjaOne integration inside of Halo. And then we need to make sure that we have the UPN mapped to the user inside of Halo as well.

And if all of those moving pieces exist, the next time you click import devices, this should show, um, ignore this, this is NinjaOne's field. We don't care about this field. We care about the hidden one that we've done over here. But this will update that and your assets should all match.

If they're not matching, just to clarify one last time, all you really have to do is make sure that the site is the same. Very particular. And the last logged in user is the same as the user. So in my case, Connor is existing at this site and that network login email address is matching what's in that field like this. And fortunately that doesn't look to be case sensitive so we can sleep easy.

And that is in my opinion a job well done from everyone involved. Not me. I'm just delivering the message. So don't shoot the messenger. Um, but yeah, guide attached below. Uh, full PowerShell script. Full written guide. We've added in the uh alerts as of two minutes ago on you know making sure the case is the same. Um, and hopefully that should now fix a big problem for a bunch of you out there.

Connor: Don't forget that the NinjaOne integration only currently runs once a day, so if it's last logged in user, or should I say current logged in user, is only going to be updated once a day. If for your business you need that to be running more frequently, then you will either need to have a conversation with Halo to see if they can increase that for you, or run the Halo integrator yourself on prem and then you can set when you want the schedule to run. The more assets you have the longer it's going to take, so just bear that in mind.

Connor: But that's it, I've been Connor. I hope this video helps. Any questions, please put it in the description below or comment section below. Please do like and subscribe for this one. This has been a big one, took us a lot of time to get all this together for you all, but yeah, we're happy. Have a beautiful day. I've been Connor, bye-bye for now.

HaloPSA is a great platform. Without Connor and Renada, though, we'd never have been able to utilize it to its full potential.
Granite Networks Google Logo

Our Core Services

Offering support to enable sustainable success for your organisation.

Consultation Harness the transformative potential of an agnostic advice tailored to your unique business needs. From PSA implementation to ongoing support, our exceptional consultation services pave the way for extraordinary success. Find out more
Virtual Admin Let us handle the technical heavy lifting. Our expert team builds solutions, creates powerful reports and dashboards, and develops automated integrations - giving you more time to focus on what matters most: your clients. Find out more
Product Onboarding We understand that the first steps in adopting a new product can be daunting, we are here to guide you through every stage of the process with precision and clarity. From initial setup to advanced features, maximise the value of your product from day one. Find out more
Virtual Chief Technology Officer (vCTO) Benefit from a remote and adaptable technology expert to seamlessly combine strategic guidance and effective leadership to propel your business to new heights and empower your organisation’s technology ability. Find out more
Where to next? Get the cutting-edge tools to support your MSP business. Contact us today to receive a bespoke quote tailored to your specific needs.