The CreatorCon Call for Content is officially open! Get started here.

widget impersonation (impersonate in code)

nic_2017
Mega Contributor

It's my understading that this used to work: gs.getSession().impersonate("usernameORsysid")

I have an error message in a widget, is not working anymore.

I googled it, I took a look at the documentation ... nothing.

How do I impersonate a user in script in Istambul?

Thank you,

Nick.

1 ACCEPTED SOLUTION

Hello Nicolae,



Actually, this is a use case where I wouldn't recommend the impersonate(), especially not to impersonate an admin, because that might be exploitable.



Instead, there's a read ACL on the 'incident' table you can use as a model, which uses this script:



current.opened_by == gs.getUserID() || current.caller_id == gs.getUserID() || current.watch_list.indexOf(gs.getUserID()) > -1;



This is what allows users to see their own incidents but not any other incidents (unless, of course, they have the 'itil' role, which is handled in a different ACL.



Just adjust it to whatever field you're using on this table to identify their own HR time off request.


View solution in original post

10 REPLIES 10

Dave Smith1
ServiceNow Employee
ServiceNow Employee

What we were using it for is when we query in GlideRecord via web service query, we want to enforce the queries on behalf of the logged in user, not on behalf of the service account that the web service is using.


Aha..... I see. Yes.   How come the web service can't execute in the context of the logged-in user?   It feels like a delegation workaround somehow.


In our case, .impersonate() allows us to implement better security because it ensures that the user doesn't access via web services something that they couldn't access through the UI.


Indeed - but curious to know why the code requires impersonate() to switch to the correct user context.


It's definitely something to be cautious and aware of.


Agreed - but thanks for the education and enlightenment.   I can see your justification... but feel it shouldn't be needed somehow.   Not going to argue that it works and would fail without it, but seems to be a workaround for something that shouldn't be broken.


The reason that the web service doesn't execute in the context of the logged-in user is because we don't give our web service access to the login credentials of the user. If we gave the web service the credentials to log in as the user, then we wouldn't need 'impersonate' -- but then we'd be storing a duplicate set of credentials for users, which we judged to be its own risk, as well as a possible data sync issue.



By using a service account and then impersonating the user, we only need to store one set of credentials to access ServiceNow -- and if our customer wants to lock our service out, all they have to do is mark that one user "active = false".


nic_2017
Mega Contributor

Hi Guy,


I would be happy to use some other way of doing it. If you can suggest one that would be great.



This is what I want to achieve:


1)I have a service portal application for "HR time off requests".


2)Anybody from the company can access my widget and put a request for a time off and send the request to his/her manager.



So ... I have a table with a role and no module (I don't want the users to see the application in CMS - that's the main SN interface - I want all of them instead to go to a page in Service Portal). Because of the above scenario I have to create a group and attach the application role to that group ... basically give everybody access to the application.



But I don't want to do this ... one of the smart guys my go in the main SN interface and type "tablename.list" and have access to the entire table. Can I modify the ACLs and dynamically give to a user access JUST to his/her own rows?



My idea was to give nobody access to anything ... modify instead the widget to impersonate "admin". When the user opens the portal the code detects the user and populates the table under admin (with a field populated using the connected user and another field populated using the manager). Using this implementation I can control everything from the widget/page.



So ... what is your suggestion? I will send this to Dave as well, not sure if the email is sent to everybody connected to this discussion.



Thank you.


Hi Dave,


I would be happy to use some other way of doing it. If you can suggest one that would be great.



This is what I want to achieve:


1)I have a service portal application for "HR time off requests".


2)Anybody from the company can access my widget and put a request for a time off and send the request to his/her manager.



So ... I have a table with a role and no module (I don't want the users to see the application in CMS - that's the main SN interface - I want all of them instead to go to a page in Service Portal). Because of the above scenario I have to create a group and attach the application role to that group ... basically give everybody access to the application.



But I don't want to do this ... one of the smart guys my go in the main SN interface and type "tablename.list" and have access to the entire table. Can I modify the ACLs and dynamically give to a user access JUST to his/her own rows?



My idea was to give nobody access to anything ... modify instead the widget to impersonate "admin". When the user opens the portal the code detects the user and populates the table under admin (with a field populated using the connected user and another field populated using the manager). Using this implementation I can control everything from the widget/page.



So ... what is your suggestion? I will send this to Guy as well, not sure if the email is sent to everybody connected to this discussion.



Thank you.


Hello Nicolae,



Actually, this is a use case where I wouldn't recommend the impersonate(), especially not to impersonate an admin, because that might be exploitable.



Instead, there's a read ACL on the 'incident' table you can use as a model, which uses this script:



current.opened_by == gs.getUserID() || current.caller_id == gs.getUserID() || current.watch_list.indexOf(gs.getUserID()) > -1;



This is what allows users to see their own incidents but not any other incidents (unless, of course, they have the 'itil' role, which is handled in a different ACL.



Just adjust it to whatever field you're using on this table to identify their own HR time off request.