Skip to content

clsADUserServices

clsADUserServices is the sole service class hosted by this repository. It provisions, modifies, unlocks, and deletes Active Directory user accounts; manages group membership; reads directory attributes (email, fax, printer, last logon, group/resource membership); and implements the service's own IP-allow-list access-control primitive (CheckAccess). All directory access is concentrated in three private helpers (GetContext, GetUserPrincipal, GetGroupPrincipal) shared by every operation. No consumer of this service is identifiable from the repository.

Field Value
Service class ADUserServices.clsADUserServices
Marker file clsADUserServices.asmx
Codebehind src\ADUserServices\clsADUserServices.asmx.vb
SOAP namespace http://tempuri.org/
WSI conformance WsiProfiles.BasicProfile1_1
Base class System.Web.Services.WebService
ScriptService Commented out (not active)
Constructor work None - no class constructor exists in the codebehind
Shared state None process-wide; four Private instance fields live for one request only: m_CredUserId, m_CredPass (never assigned or read anywhere - dead), m_FoundUser (written/read only by dead code), m_LastMessage (written by the three directory helpers on exception, never read or returned by any operation)
Class-level authorization None in code - every check is per-operation
Operations 19
Also hosted in - (single host)

HelloWorld

Returns a constant greeting string; a connectivity/scaffolding check with no directory interaction.

Field Value
Operation name HelloWorld
Message name HelloWorld
SOAP action http://tempuri.org/HelloWorld
Implementing member clsADUserServices.HelloWorld (src\ADUserServices\clsADUserServices.asmx.vb:86-89)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/hello-world.md

HelloWorld - Input message

No input parts - the request message is empty.

HelloWorld - Output message

Field Value
Return type String
Response element HelloWorldResult
Meaning A constant greeting string, "Hello World", left over from Visual Studio ASMX project scaffolding
Empty-result behavior Never empty - the literal is hard-coded and always returned

HelloWorld - Faults

Failure Raised when Surfaced as Detail crosses the boundary
- Never Cannot fail - no branching, no directory call No

HelloWorld - Authorization

None in code. See Authentication and authorization.

HelloWorld - Side effects

Aspect Finding
Records written None
Downstream calls None
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result on every call

HelloWorld - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <HelloWorld xmlns="http://tempuri.org/" />
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <HelloWorldResponse xmlns="http://tempuri.org/">
      <HelloWorldResult>Hello World</HelloWorldResult>
    </HelloWorldResponse>
  </soap:Body>
</soap:Envelope>

AddUser

Creates an Active Directory user account in the external domain and sets its attributes.

Field Value
Operation name AddUser
Message name AddUser
SOAP action http://tempuri.org/AddUser
Implementing member clsADUserServices.AddUser (src\ADUserServices\clsADUserServices.asmx.vb:91-197)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked - If (Not CheckAccess().HasAccess) Then Return AccessDenied() (BR-01)
Process operations/add-user.md

AddUser - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inPassword String Yes - Initial password; empty string substitutes a hard-coded default password literal (never reproduced here - see tech-debt.md SEC-05)
inName String Yes - Directory Name attribute*
inGivenName String Yes - GivenName*
inSurName String Yes - Surname*
inDescription String Yes - Description*
inPhoneNum String Yes - telephoneNumber (written only when non-empty)*
inMailAddr String Yes - mail (written only when non-empty)*
inTitle String Yes - title (written only when non-empty)*
inInfo String Yes - info (written only when non-empty)*
inCompany String Yes - company (written only when non-empty)*
inFAXNum String Yes - facsimileTelephoneNumber (written only when non-empty)*
inDivision String Yes - division (written only when non-empty)*

AddUser - Output message

Field Value
Return type ADServiceResponse
Response element AddUserResult
Meaning Outcome of the account-creation attempt
Empty-result behavior Not applicable - the structure is always populated
Member Type Nullable Purpose
Message String Yes "" on success; "Access Denied" on denial; ex.Message on a caught save/commit failure
Response EResponse No Success, or Failure (denial, existing user TD-17, or a caught save/commit exception)

AddUser - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False ADServiceResponse{Response=Failure, Message="Access Denied"} No - handled, no fault
Existing user H2 finds an existing principal for inUserId ADServiceResponse{Response=Failure} - UserExists is set then immediately overwritten (TD-17, unreachable on the wire) No - handled, no fault
userPrin.Save() failure AD rejects the new principal (policy, duplicate, connectivity) ADServiceResponse{Response=Failure, Message=ex.Message} - execution continues into attribute writes on the unsaved principal (TD-18, HIGH) Yes - ex.Message copied into Message
dirEntry.CommitChanges() failure Attribute commit fails after a successful save ADServiceResponse{Response=Failure, Message=ex.Message} Yes - ex.Message copied into Message
Directory/context construction failure Failure in GetContext/New UserPrincipal/property assignment, outside both Try blocks SoapException produced by ASP.NET Yes

AddUser - Authorization

Access-checked: the operation's first statement is If (Not CheckAccess().HasAccess) Then Return AccessDenied() (BR-01). See Authentication and authorization.

AddUser - Side effects

Aspect Finding
Records written None (no database) - writes a new UserPrincipal/DirectoryEntry object under CN=Users, + the external container in Active Directory
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices
Files or messages produced None
Shared state touched None
Repeat-call behavior A second call with the same inUserId returns Response=Failure (the UserExists code is unreachable - TD-17); the account is not modified

AddUser - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <AddUser xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inPassword><value></inPassword>
      <inName><value></inName>
      <inGivenName><value></inGivenName>
      <inSurName><value></inSurName>
      <inDescription><value></inDescription>
      <inPhoneNum><value></inPhoneNum>
      <inMailAddr><value></inMailAddr>
      <inTitle><value></inTitle>
      <inInfo><value></inInfo>
      <inCompany><value></inCompany>
      <inFAXNum><value></inFAXNum>
      <inDivision><value></inDivision>
    </AddUser>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <AddUserResponse xmlns="http://tempuri.org/">
      <AddUserResult>
        <Message></Message>
        <Response>Success</Response>
      </AddUserResult>
    </AddUserResponse>
  </soap:Body>
</soap:Envelope>

UnlockAccount

Unlocks an Active Directory account in the external domain if it is currently locked out.

Field Value
Operation name UnlockAccount
Message name UnlockAccount
SOAP action http://tempuri.org/UnlockAccount
Implementing member clsADUserServices.UnlockAccount (src\ADUserServices\clsADUserServices.asmx.vb:200-226)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/unlock-account.md

UnlockAccount - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*

UnlockAccount - Output message

Field Value
Return type ADServiceResponse
Response element UnlockAccountResult
Meaning Outcome of the unlock attempt
Empty-result behavior Not applicable
Member Type Nullable Purpose
Message String Yes Free-text wording distinguishing "unlocked", "was not locked", and "not unlocked" - this distinction is not carried in Response
Response EResponse No UserDoesNotExist, Success (covers unlocked, already-unlocked, and unlock-did-not-take-effect), or Failure + ex.Message

UnlockAccount - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Any other exception The whole body is wrapped in Try/Catch ex As Exception Sentinel Failure + ex.Message Yes - ex.Message copied into Message

Never faults* - the entire operation body is inside a single Try/Catch.

UnlockAccount - Authorization

Access-checked (BR-01). See Authentication and authorization.

UnlockAccount - Side effects

Aspect Finding
Records written None (no database) - clears the AD lockout flag on the target principal when locked
Downstream calls Active Directory via System.DirectoryServices.AccountManagement
Files or messages produced None
Shared state touched None
Repeat-call behavior A second call on an already-unlocked account returns Success with "was not locked" wording

UnlockAccount - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <UnlockAccount xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
    </UnlockAccount>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <UnlockAccountResponse xmlns="http://tempuri.org/">
      <UnlockAccountResult>
        <Message></Message>
        <Response>Success</Response>
      </UnlockAccountResult>
    </UnlockAccountResponse>
  </soap:Body>
</soap:Envelope>

AddUserToGroup

Adds a user to a group in the external domain.

Field Value
Operation name AddUserToGroup
Message name AddUserToGroup
SOAP action http://tempuri.org/AddUserToGroup
Implementing member clsADUserServices.AddUserToGroup (src\ADUserServices\clsADUserServices.asmx.vb:228-267)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/add-user-to-group.md

AddUserToGroup - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inGroupName String Yes - Target group's SamAccountName*

AddUserToGroup - Output message

Field Value
Return type ADServiceResponse
Response element AddUserToGroupResult
Meaning Outcome of the membership-add attempt
Empty-result behavior Not applicable
Member Type Nullable Purpose
Message String Yes ex.Message on a generic failure; otherwise empty
Response EResponse No UserDoesNotExist, GroupDoesNotExist, UserAlreadyInGroup (detected via ex.Message.Contains("already exists")), Success, or Failure

AddUserToGroup - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Group not found H3 returns Nothing Sentinel GroupDoesNotExist No
Already a member groupPrin.Members.Add/.Save() throws an exception whose message contains "already exists" Sentinel UserAlreadyInGroup - locale- and provider-fragile* No
Any other exception groupPrin.Members.Add/.Save() fails for another reason Sentinel Failure + ex.Message Yes - via Message

Never faults.

AddUserToGroup - Authorization

Access-checked (BR-01). See Authentication and authorization.

AddUserToGroup - Side effects

Aspect Finding
Records written None (no database) - adds the user to the AD group's membership list
Downstream calls Active Directory via System.DirectoryServices.AccountManagement
Files or messages produced None
Shared state touched None
Repeat-call behavior A second call returns UserAlreadyInGroup (subject to the English-substring detection caveat above)

AddUserToGroup - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <AddUserToGroup xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inGroupName><value></inGroupName>
    </AddUserToGroup>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <AddUserToGroupResponse xmlns="http://tempuri.org/">
      <AddUserToGroupResult>
        <Message></Message>
        <Response>Success</Response>
      </AddUserToGroupResult>
    </AddUserToGroupResponse>
  </soap:Body>
</soap:Envelope>

DeleteUser

Deletes an Active Directory user account in the external domain.

Field Value
Operation name DeleteUser
Message name DeleteUser
SOAP action http://tempuri.org/DeleteUser
Implementing member clsADUserServices.DeleteUser (src\ADUserServices\clsADUserServices.asmx.vb:270-295)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/delete-user.md

DeleteUser - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*

DeleteUser - Output message

Field Value
Return type ADServiceResponse
Response element DeleteUserResult
Meaning Outcome of the deletion attempt
Empty-result behavior A missing user returns Success - the delete is a silent no-op, indistinguishable from a directory-lookup failure inside GetUserPrincipal (tech-debt.md)
Member Type Nullable Purpose
Message String Yes ex.Message on a caught delete failure; otherwise empty
Response EResponse No Success (deleted, or user absent/lookup failed) or Failure + ex.Message

DeleteUser - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
userPrin.Delete() failure Directory rejects the delete Sentinel Failure + ex.Message Yes - via Message
User not found / lookup failure H2 returns Nothing Sentinel Success (no-op) - the two cases are indistinguishable No

Never faults.

DeleteUser - Authorization

Access-checked (BR-01). See Authentication and authorization.

DeleteUser - Side effects

Aspect Finding
Records written None (no database) - removes the AD user object
Downstream calls Active Directory via System.DirectoryServices.AccountManagement
Files or messages produced None
Shared state touched None
Repeat-call behavior A second call returns Success (no-op) regardless of whether the first call deleted the account

DeleteUser - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DeleteUser xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
    </DeleteUser>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DeleteUserResponse xmlns="http://tempuri.org/">
      <DeleteUserResult>
        <Message></Message>
        <Response>Success</Response>
      </DeleteUserResult>
    </DeleteUserResponse>
  </soap:Body>
</soap:Envelope>

DeleteUserFromGroup

Removes a user from a group in the external domain.

Field Value
Operation name DeleteUserFromGroup
Message name DeleteUserFromGroup
SOAP action http://tempuri.org/DeleteUserFromGroup
Implementing member clsADUserServices.DeleteUserFromGroup (src\ADUserServices\clsADUserServices.asmx.vb:297-340)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/delete-user-from-group.md

DeleteUserFromGroup - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inGroupName String Yes - Target group's SamAccountName*

DeleteUserFromGroup - Output message

Field Value
Return type ADServiceResponse
Response element DeleteUserFromGroupResult
Meaning Outcome of the membership-removal attempt
Empty-result behavior Success is returned for a genuine removal, for "user was not a member", and for a genuine directory failure - the three are indistinguishable (tech-debt.md TD-20, HIGH)
Member Type Nullable Purpose
Message String Yes Always empty on this path - the Catch block is an explicit swallow
Response EResponse No GroupDoesNotExist or Success

DeleteUserFromGroup - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
Group not found H3 returns Nothing Sentinel GroupDoesNotExist No
Any directory failure (including a genuine removal failure) deGroup.Invoke("Remove", New Object() {deUser.Path})/CommitChanges() throws Caught and swallowed - Catch block contains the authored comment 'gobble - user is pribably not in the group; returns Success No - the failure is never surfaced to the caller in any form

Never faults. This is the most consequential fault-handling finding on this operation - see tech-debt.md TD-20 and faults.md.

DeleteUserFromGroup - Authorization

Access-checked (BR-01). See Authentication and authorization.

DeleteUserFromGroup - Side effects

Aspect Finding
Records written None (no database) - removes the user from the AD group's membership list via a DirectoryEntry.Invoke("Remove", New Object() {deUser.Path}) call (dropped to DirectoryEntry deliberately because the GroupPrincipal.Remove method fails on large groups, per an authored comment)
Downstream calls Active Directory via System.DirectoryServices
Files or messages produced None
Shared state touched None
Repeat-call behavior A second call returns Success regardless of whether the user was ever a member

DeleteUserFromGroup - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DeleteUserFromGroup xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inGroupName><value></inGroupName>
    </DeleteUserFromGroup>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DeleteUserFromGroupResponse xmlns="http://tempuri.org/">
      <DeleteUserFromGroupResult>
        <Message></Message>
        <Response>Success</Response>
      </DeleteUserFromGroupResult>
    </DeleteUserFromGroupResponse>
  </soap:Body>
</soap:Envelope>

DoesUserExist

Reports whether a user account exists in the requested domain.

Field Value
Operation name DoesUserExist
Message name DoesUserExist
SOAP action http://tempuri.org/DoesUserExist
Implementing member clsADUserServices.DoesUserExist (src\ADUserServices\clsADUserServices.asmx.vb:342-353)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/does-user-exist.md

DoesUserExist - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inExternalDomain Boolean Yes - Selects external.saif.com (True) vs corp.saif.com (False)

DoesUserExist - Output message

Field Value
Return type Boolean
Response element DoesUserExistResult
Meaning Whether a matching principal was found
Empty-result behavior Returns False both when the user is genuinely absent and when the directory lookup failed - the exception is swallowed inside GetUserPrincipal into the unread m_LastMessage field (tech-debt.md TD-22)

DoesUserExist - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User absent or directory failure H2 returns Nothing for either reason False No - the two cases are indistinguishable to the caller

Never faults.

DoesUserExist - Authorization

None in code. See Authentication and authorization.

DoesUserExist - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement (read-only)
Files or messages produced None
Shared state touched m_LastMessage - written on failure, never read by any caller-visible path
Repeat-call behavior Identical result for the same input

DoesUserExist - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DoesUserExist xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inExternalDomain><value></inExternalDomain>
    </DoesUserExist>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DoesUserExistResponse xmlns="http://tempuri.org/">
      <DoesUserExistResult>true</DoesUserExistResult>
    </DoesUserExistResponse>
  </soap:Body>
</soap:Envelope>

DoesUserHaveResource

Reports whether a user's authorization groups include a group named inResourceName.

Field Value
Operation name DoesUserHaveResource
Message name DoesUserHaveResource
SOAP action http://tempuri.org/DoesUserHaveResource
Implementing member clsADUserServices.DoesUserHaveResource (src\ADUserServices\clsADUserServices.asmx.vb:355-386)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/does-user-have-resource.md

DoesUserHaveResource - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inResourceName String Yes - Group name to match by equality against userPrin.GetAuthorizationGroups()*
inExternalDomain Boolean Yes - Selects the domain

DoesUserHaveResource - Output message

Field Value
Return type ADServiceResponse
Response element DoesUserHaveResourceResult
Meaning Whether the named group was found among the user's authorization groups
Empty-result behavior Not applicable - Message always carries the literal "True" or "False"
Member Type Nullable Purpose
Message String No Literal "True"/"False" - the answer travels in Message, not Response
Response EResponse No Success (answer computed) or UserDoesNotExist

DoesUserHaveResource - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Directory failure inside GetAuthorizationGroups No Try/Catch wraps the iteration SoapException produced by ASP.NET Yes

DoesUserHaveResource - Authorization

None in code. See Authentication and authorization.

DoesUserHaveResource - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement (read-only); an unused GetGroupPrincipal (H3) call is also made and its result discarded (tech-debt.md TD-23)
Files or messages produced None
Shared state touched m_FoundUser reset to False, never read afterward on this path
Repeat-call behavior Identical result for the same input

DoesUserHaveResource - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DoesUserHaveResource xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inResourceName><value></inResourceName>
      <inExternalDomain><value></inExternalDomain>
    </DoesUserHaveResource>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <DoesUserHaveResourceResponse xmlns="http://tempuri.org/">
      <DoesUserHaveResourceResult>
        <Message>True</Message>
        <Response>Success</Response>
      </DoesUserHaveResourceResult>
    </DoesUserHaveResourceResponse>
  </soap:Body>
</soap:Envelope>

ChangeUserAccount

Updates directory attributes on an existing user account (either domain, selected internally by the operation).

Field Value
Operation name ChangeUserAccount
Message name ChangeUserAccount
SOAP action http://tempuri.org/ChangeUserAccount
Implementing member clsADUserServices.ChangeUserAccount (src\ADUserServices\clsADUserServices.asmx.vb:388-469)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/change-user-account.md

ChangeUserAccount - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inGivenName String Yes - GivenName (written only when non-empty)*
inSurName String Yes - Surname (written only when non-empty)*
inDescription String Yes - Description (written only when non-empty)*
inPhoneNum String Yes - telephoneNumber (written only when non-empty)*
inMailAddr String Yes - mail (written only when non-empty)*
inTitle String Yes - title (written only when non-empty)*
inInfo String Yes - info (written only when non-empty; does not set the modified flag - tech-debt.md TD-19)*
inCompany String Yes - company (written only when non-empty; does not set the modified flag - TD-19)*
inFAXNum String Yes - facsimileTelephoneNumber (written only when non-empty)*

ChangeUserAccount - Output message

Field Value
Return type ADServiceResponse
Response element ChangeUserAccountResult
Meaning Outcome of the attribute-update attempt
Empty-result behavior A request that changes only inCompany and/or inInfo returns Success having committed nothing to the directory, because those two writes never set the modified flag that gates de.CommitChanges() (tech-debt.md TD-19, HIGH)
Member Type Nullable Purpose
Message String Yes ex.Message on a caught failure; otherwise empty
Response EResponse No UserDoesNotExist, Success, or Failure + ex.Message

ChangeUserAccount - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
User not found UserPrincipal.FindByIdentity returns Nothing (called directly, not through H2) Sentinel UserDoesNotExist No
Any exception inside the Try userPrin.Save()/de.CommitChanges()/property assignment fails Sentinel Failure + ex.Message Yes - via Message

Never faults. Unlike the other lookups this operation calls FindByIdentity directly rather than through H2, so a Nothing context (a directory failure, not just "user absent") would surface differently than in operations using H2.

ChangeUserAccount - Authorization

Access-checked (BR-01). See Authentication and authorization.

ChangeUserAccount - Side effects

Aspect Finding
Records written None (no database) - writes selected attributes on the AD user object
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices
Files or messages produced None
Shared state touched None
Repeat-call behavior Idempotent for the fields that do set modified; a repeat call touching only inCompany/inInfo never commits (TD-19)

ChangeUserAccount - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ChangeUserAccount xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inGivenName><value></inGivenName>
      <inSurName><value></inSurName>
      <inDescription><value></inDescription>
      <inPhoneNum><value></inPhoneNum>
      <inMailAddr><value></inMailAddr>
      <inTitle><value></inTitle>
      <inInfo><value></inInfo>
      <inCompany><value></inCompany>
      <inFAXNum><value></inFAXNum>
    </ChangeUserAccount>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ChangeUserAccountResponse xmlns="http://tempuri.org/">
      <ChangeUserAccountResult>
        <Message></Message>
        <Response>Success</Response>
      </ChangeUserAccountResult>
    </ChangeUserAccountResponse>
  </soap:Body>
</soap:Envelope>

ChangeUserPassword

Sets a new password for a user, swallowing any failure into the sentinel response.

Field Value
Operation name ChangeUserPassword
Message name ChangeUserPassword
SOAP action http://tempuri.org/ChangeUserPassword
Implementing member clsADUserServices.ChangeUserPassword (src\ADUserServices\clsADUserServices.asmx.vb:471-491)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/change-user-password.md

ChangeUserPassword - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inNewPassword String Yes - New password value - never reproduce a real value in examples

ChangeUserPassword - Output message

Field Value
Return type ADServiceResponse
Response element ChangeUserPasswordResult
Meaning Outcome of the password-change attempt
Empty-result behavior Not applicable
Member Type Nullable Purpose
Message String Yes ex.Message on any caught failure (policy, complexity, history, connectivity) - flattened into free text
Response EResponse No Success, UserDoesNotExist, or Failure

ChangeUserPassword - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
Any exception from the private ChangePassword helper (H6) Password rejected, user not found, or directory error Sentinel Failure + ex.Message Yes - via Message, raw .NET exception text

Never faults.

ChangeUserPassword - Authorization

Access-checked (BR-01). See Authentication and authorization.

ChangeUserPassword - Side effects

Aspect Finding
Records written None (no database) - sets the AD password via DirectoryEntry.Invoke("SetPassword", oPassword) and CommitChanges()
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices
Files or messages produced None
Shared state touched None
Repeat-call behavior Each call sets the password again; no history-of-calls tracking

ChangeUserPassword - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ChangeUserPassword xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inNewPassword><value></inNewPassword>
    </ChangeUserPassword>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ChangeUserPasswordResponse xmlns="http://tempuri.org/">
      <ChangeUserPasswordResult>
        <Message></Message>
        <Response>Success</Response>
      </ChangeUserPasswordResult>
    </ChangeUserPasswordResponse>
  </soap:Body>
</soap:Envelope>

ChangeUserPasswordOrGetException

Sets a new password for a user; the deliberately faulting counterpart of ChangeUserPassword - no exception handling.

Field Value
Operation name ChangeUserPasswordOrGetException
Message name ChangeUserPasswordOrGetException
SOAP action http://tempuri.org/ChangeUserPasswordOrGetException
Implementing member clsADUserServices.ChangeUserPasswordOrGetException (src\ADUserServices\clsADUserServices.asmx.vb:493-501)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization Access-checked (BR-01)
Process operations/change-user-password-or-get-exception.md

ChangeUserPasswordOrGetException - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inNewPassword String Yes - New password value - never reproduce a real value in examples

ChangeUserPasswordOrGetException - Output message

Field Value
Return type ADServiceResponse
Response element ChangeUserPasswordOrGetExceptionResult
Meaning Outcome of the password-change attempt
Empty-result behavior Not applicable
Member Type Nullable Purpose
Message String No String.Empty on success; not populated on failure - failure instead escapes as a fault
Response EResponse No Success or UserDoesNotExist on the non-faulting paths

ChangeUserPasswordOrGetException - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Access denied CheckAccess().HasAccess is False Sentinel Failure/"Access Denied" No
Any exception from the private ChangePassword helper (H6) Password rejected, user not found, or directory error - no Try/Catch SoapException produced by ASP.NET, carrying the .NET exception Yes

This operation is a deliberately faulting variant of ChangeUserPassword; the two are near-duplicates differing only in error strategy, and the naming does not make that difference discoverable from the WSDL (tech-debt.md TD-24).

ChangeUserPasswordOrGetException - Authorization

Access-checked (BR-01). See Authentication and authorization.

ChangeUserPasswordOrGetException - Side effects

Aspect Finding
Records written None (no database) - sets the AD password via DirectoryEntry.Invoke("SetPassword", oPassword) and CommitChanges()
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices
Files or messages produced None
Shared state touched None
Repeat-call behavior Each call sets the password again

ChangeUserPasswordOrGetException - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ChangeUserPasswordOrGetException xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inNewPassword><value></inNewPassword>
    </ChangeUserPasswordOrGetException>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ChangeUserPasswordOrGetExceptionResponse xmlns="http://tempuri.org/">
      <ChangeUserPasswordOrGetExceptionResult>
        <Message></Message>
        <Response>Success</Response>
      </ChangeUserPasswordOrGetExceptionResult>
    </ChangeUserPasswordOrGetExceptionResponse>
  </soap:Body>
</soap:Envelope>

GetUserEmail

Reads the mail attribute for a user.

Field Value
Operation name GetUserEmail
Message name GetUserEmail
SOAP action http://tempuri.org/GetUserEmail
Implementing member clsADUserServices.GetUserEmail (src\ADUserServices\clsADUserServices.asmx.vb:526-554)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/get-user-email.md

GetUserEmail - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inExternalDomain Boolean Yes - Selects the domain

GetUserEmail - Output message

Field Value
Return type ADServiceResponse
Response element GetUserEmailResult
Meaning The AD mail value for the user
Empty-result behavior An unset mail attribute surfaces as Failure + a .NET null-reference/cast message rather than as a distinct response code*
Member Type Nullable Purpose
Message String Yes The mail attribute value, or ex.Message on failure
Response EResponse No Success, UserDoesNotExist, or Failure

GetUserEmail - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Any exception (including unset mail) Late-bound de.Properties.Item("mail").Value assignment fails, or any directory error Sentinel Failure + ex.Message Yes - via Message

Never faults.

GetUserEmail - Authorization

None in code. See Authentication and authorization.

GetUserEmail - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same input

GetUserEmail - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserEmail xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inExternalDomain><value></inExternalDomain>
    </GetUserEmail>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserEmailResponse xmlns="http://tempuri.org/">
      <GetUserEmailResult>
        <Message><value></Message>
        <Response>Success</Response>
      </GetUserEmailResult>
    </GetUserEmailResponse>
  </soap:Body>
</soap:Envelope>

GetUserGroups

Lists the names of a user's authorization groups.

Field Value
Operation name GetUserGroups
Message name GetUserGroups
SOAP action http://tempuri.org/GetUserGroups
Implementing member clsADUserServices.GetUserGroups (src\ADUserServices\clsADUserServices.asmx.vb:556-580)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/get-user-groups.md

GetUserGroups - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inExternalDomain Boolean Yes - Selects the domain

GetUserGroups - Output message

Field Value
Return type ArrayList - untyped on the wire, serializes as unconstrained xsd:anyType (tech-debt.md TD-05, MEDIUM); the implementation only ever adds String (grp.Name)
Response element GetUserGroupsResult
Meaning Group names the user belongs to, per GetAuthorizationGroups()
Empty-result behavior An empty list means "no groups", "no such user", or "directory failure" - the empty Catch block (tech-debt.md TD-21, HIGH) makes all three indistinguishable

GetUserGroups - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Any failure (user not found, directory error) H2 fails, or GetAuthorizationGroups() throws Caught and swallowed by an empty Catch block - returns the (possibly still-empty) ArrayList No

Never faults.

GetUserGroups - Authorization

None in code. See Authentication and authorization.

GetUserGroups - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same input

GetUserGroups - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserGroups xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inExternalDomain><value></inExternalDomain>
    </GetUserGroups>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserGroupsResponse xmlns="http://tempuri.org/">
      <GetUserGroupsResult>
        <anyType xsi:type="xsd:string"><value></anyType>
      </GetUserGroupsResult>
    </GetUserGroupsResponse>
  </soap:Body>
</soap:Envelope>

GetUserResources

Lists a subset of a user's authorization groups whose name marks them as a "resource", filtered by environment.

Field Value
Operation name GetUserResources
Message name GetUserResources
SOAP action http://tempuri.org/GetUserResources
Implementing member clsADUserServices.GetUserResources (src\ADUserServices\clsADUserServices.asmx.vb:582-617)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/get-user-resources.md

GetUserResources - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inProdEnvironment Boolean Yes - Selects the production-vs-test resource-name branch
inExternalDomain Boolean Yes - Selects the domain

GetUserResources - Output message

Field Value
Return type ArrayList - untyped on the wire (tech-debt.md TD-05, MEDIUM); the implementation only ever adds String (grp.Name)
Response element GetUserResourcesResult
Meaning Names of groups matching "Resource", filtered by "TestResource" and inProdEnvironment
Empty-result behavior An empty list means "no matching groups", "no such user", or "directory failure" - same empty-Catch swallow as GetUserGroups (tech-debt.md TD-21, HIGH). Also note: when inProdEnvironment is True, a TestResource group is silently skipped by an empty branch body

GetUserResources - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Any failure (user not found, directory error) H2 fails, or GetAuthorizationGroups() throws Caught and swallowed by an empty Catch block No

Never faults.

GetUserResources - Authorization

None in code. See Authentication and authorization.

GetUserResources - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same input

GetUserResources - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserResources xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inProdEnvironment><value></inProdEnvironment>
      <inExternalDomain><value></inExternalDomain>
    </GetUserResources>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserResourcesResponse xmlns="http://tempuri.org/">
      <GetUserResourcesResult>
        <anyType xsi:type="xsd:string"><value></anyType>
      </GetUserResourcesResult>
    </GetUserResourcesResponse>
  </soap:Body>
</soap:Envelope>

GetUserFAX

Reads the facsimileTelephoneNumber attribute for a user.

Field Value
Operation name GetUserFAX
Message name GetUserFAX
SOAP action http://tempuri.org/GetUserFAX
Implementing member clsADUserServices.GetUserFAX (src\ADUserServices\clsADUserServices.asmx.vb:619-647)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/get-user-fax.md

GetUserFAX - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inExternalDomain Boolean Yes - Selects the domain

GetUserFAX - Output message

Field Value
Return type ADServiceResponse
Response element GetUserFAXResult
Meaning The AD facsimileTelephoneNumber value for the user
Empty-result behavior An unset attribute surfaces as Failure + a .NET exception message rather than as a distinct response code*
Member Type Nullable Purpose
Message String Yes The facsimileTelephoneNumber value, or ex.Message on failure
Response EResponse No Success, UserDoesNotExist, or Failure

GetUserFAX - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Any exception Late-bound property read fails, or any directory error Sentinel Failure + ex.Message Yes - via Message

Never faults.

GetUserFAX - Authorization

None in code. See Authentication and authorization.

GetUserFAX - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same input

GetUserFAX - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserFAX xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inExternalDomain><value></inExternalDomain>
    </GetUserFAX>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserFAXResponse xmlns="http://tempuri.org/">
      <GetUserFAXResult>
        <Message><value></Message>
        <Response>Success</Response>
      </GetUserFAXResult>
    </GetUserFAXResponse>
  </soap:Body>
</soap:Envelope>

GetUserLastLogon

Computes and reports a user's last-logon timestamp from lastLogonTimestamp.

Field Value
Operation name GetUserLastLogon
Message name GetUserLastLogon
SOAP action http://tempuri.org/GetUserLastLogon
Implementing member clsADUserServices.GetUserLastLogon (src\ADUserServices\clsADUserServices.asmx.vb:649-685)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/get-user-last-logon.md

GetUserLastLogon - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inExternalDomain Boolean Yes - Selects the domain

GetUserLastLogon - Output message

Field Value
Return type ADServiceResponse
Response element GetUserLastLogonResult
Meaning A DateTime.ToString() rendering of the last logon, derived from the lastLogonTimestamp FILETIME value
Empty-result behavior A user with no lastLogonTimestamp attribute yields Failure + a .NET exception message rather than InfoNotAvailable. The rendered timestamp string format depends on the server's current culture and time zone
Member Type Nullable Purpose
Message String Yes The computed last-logon DateTime.ToString(), or ex.Message on failure; empty for InfoNotAvailable
Response EResponse No Success, UserDoesNotExist, InfoNotAvailable (computed value < 1), or Failure

GetUserLastLogon - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Computed value < 1 The composed FILETIME value is less than 1 Sentinel InfoNotAvailable (the authored comment references defaulting to Jan 1, 2000, but no such date is actually applied) No
Any other exception Late-bound COM property access (HighPart/lowpart) fails, or any directory error Sentinel Failure + ex.Message Yes - via Message

Never faults.

GetUserLastLogon - Authorization

None in code. See Authentication and authorization.

GetUserLastLogon - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement and System.DirectoryServices (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Result changes only as the underlying lastLogonTimestamp changes

GetUserLastLogon - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserLastLogon xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inExternalDomain><value></inExternalDomain>
    </GetUserLastLogon>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserLastLogonResponse xmlns="http://tempuri.org/">
      <GetUserLastLogonResult>
        <Message><value></Message>
        <Response>Success</Response>
      </GetUserLastLogonResult>
    </GetUserLastLogonResponse>
  </soap:Body>
</soap:Envelope>

GetUserPrinter

Reads the extensionAttribute2 attribute for a user in the internal domain only.

Field Value
Operation name GetUserPrinter
Message name GetUserPrinter
SOAP action http://tempuri.org/GetUserPrinter
Implementing member clsADUserServices.GetUserPrinter (src\ADUserServices\clsADUserServices.asmx.vb:687-713)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/get-user-printer.md

GetUserPrinter - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName* - no domain parameter is offered; the operation is hard-wired to the internal domain (authored comment 'Assume internal domain)

GetUserPrinter - Output message

Field Value
Return type ADServiceResponse
Response element GetUserPrinterResult
Meaning The AD extensionAttribute2 value for the user
Empty-result behavior An unset attribute surfaces as Failure + a .NET exception message rather than as a distinct response code*
Member Type Nullable Purpose
Message String Yes The extensionAttribute2 value, or ex.Message on failure
Response EResponse No Success, UserDoesNotExist, or Failure

GetUserPrinter - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User not found H2 (internal domain, inExternalDomain = False) returns Nothing Sentinel UserDoesNotExist No
Any exception Late-bound property read fails, or any directory error Sentinel Failure + ex.Message Yes - via Message

Never faults.

GetUserPrinter - Authorization

None in code. See Authentication and authorization.

GetUserPrinter - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory (internal domain only) via System.DirectoryServices.AccountManagement and System.DirectoryServices (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same input

GetUserPrinter - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserPrinter xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
    </GetUserPrinter>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserPrinterResponse xmlns="http://tempuri.org/">
      <GetUserPrinterResult>
        <Message><value></Message>
        <Response>Success</Response>
      </GetUserPrinterResult>
    </GetUserPrinterResponse>
  </soap:Body>
</soap:Envelope>

IsUserInGroup

Reports direct (non-nested) membership of a user in a group.

Field Value
Operation name IsUserInGroup
Message name IsUserInGroup
SOAP action http://tempuri.org/IsUserInGroup
Implementing member clsADUserServices.IsUserInGroup (src\ADUserServices\clsADUserServices.asmx.vb:715-750)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code
Process operations/is-user-in-group.md

IsUserInGroup - Input message

Part Type Required Default Purpose
inUserId String Yes - Target sAMAccountName*
inGroupName String Yes - Target group's SamAccountName*
inExternalDomain Boolean Yes - Selects the domain

IsUserInGroup - Output message

Field Value
Return type ADServiceResponse
Response element IsUserInGroupResult
Meaning Whether groupPrin.Members.Contains(userPrin) is true - direct membership only, via GroupPrincipal.Members.Contains, unlike GetUserGroups/GetUserResources/DoesUserHaveResource, which walk GetAuthorizationGroups() and therefore include nested groups
Empty-result behavior Not applicable - Message always carries the literal "True" or "False" on the success path
Member Type Nullable Purpose
Message String Yes Literal "True"/"False", or ex.Message on failure
Response EResponse No Success, UserDoesNotExist, GroupDoesNotExist, or Failure

IsUserInGroup - Faults

Failure Raised when Surfaced as Detail crosses the boundary
User not found H2 returns Nothing Sentinel UserDoesNotExist No
Group not found H3 returns Nothing Sentinel GroupDoesNotExist No
Any other exception Membership check throws, or any directory error Sentinel Failure + ex.Message Yes - via Message

Never faults. Nested-group membership answers "False" even when the user is a member transitively, because GetAuthorizationGroups() is not used here.

IsUserInGroup - Authorization

None in code. See Authentication and authorization.

IsUserInGroup - Side effects

Aspect Finding
Records written None
Downstream calls Active Directory via System.DirectoryServices.AccountManagement (read-only)
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same input

IsUserInGroup - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <IsUserInGroup xmlns="http://tempuri.org/">
      <inUserId><value></inUserId>
      <inGroupName><value></inGroupName>
      <inExternalDomain><value></inExternalDomain>
    </IsUserInGroup>
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <IsUserInGroupResponse xmlns="http://tempuri.org/">
      <IsUserInGroupResult>
        <Message>True</Message>
        <Response>Success</Response>
      </IsUserInGroupResult>
    </IsUserInGroupResponse>
  </soap:Body>
</soap:Envelope>

CheckAccess

The service's own access-control primitive: reports whether the caller's observed remote address is local or on the configured IP allow-list.

Field Value
Operation name CheckAccess
Message name CheckAccess
SOAP action http://tempuri.org/CheckAccess
Implementing member clsADUserServices.CheckAccess (src\ADUserServices\clsADUserServices.asmx.vb:752-776)
Member kind Function - method with a return value
Attributes <WebMethod()>
Authorization None in code - this operation is itself the access-control primitive consumed by the other eight operations, and it is published and unauthenticated
Process operations/check-access.md

CheckAccess - Input message

No input parts - the request message is empty.

CheckAccess - Output message

Field Value
Return type HasAccessResponse
Response element CheckAccessResult
Meaning The access decision and its basis
Empty-result behavior Not applicable - always populated when no fault occurs
Member Type Nullable Purpose
HasAccess Boolean No Overall decision - True if local or allow-listed
Local Boolean No True when HttpContext.Current.Request.IsLocal
EnvironmentApi Boolean No True when the incoming IP matched an allow-list entry
RemoteAddress String No The caller's observed remote address (HTTP_X_FORWARDED_FOR, falling back to REMOTE_ADDR) - discloses the origin-check basis to any caller

CheckAccess - Faults

Failure Raised when Surfaced as Detail crosses the boundary
Environment-service failure GetAllowedIPs (constructing WebEnvironmentService or its .Split(",") call) throws - no Try/Catch SoapException produced by ASP.NET Yes

This is also the failure path that causes the eight gated operations to fault instead of returning the Access Denied sentinel - see tech-debt.md TD-12.

CheckAccess - Authorization

None in code. CheckAccess publishes the caller's observed remote address and the allow-list decision to any unauthenticated caller, functioning as an allow-list probing oracle. See Authentication and authorization.

CheckAccess - Side effects

Aspect Finding
Records written None
Downstream calls WebEnvironmentService (SAIF.Framework.Security) to read the aduserservices.allowedips setting
Files or messages produced None
Shared state touched None
Repeat-call behavior Identical result for the same caller address and allow-list configuration; re-reads the incoming IP on every allow-list comparison iteration rather than reusing the computed value (tech-debt.md TD-09)

CheckAccess - Example message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <CheckAccess xmlns="http://tempuri.org/" />
  </soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <CheckAccessResponse xmlns="http://tempuri.org/">
      <CheckAccessResult>
        <HasAccess>true</HasAccess>
        <Local>false</Local>
        <EnvironmentApi>true</EnvironmentApi>
        <RemoteAddress><value></RemoteAddress>
      </CheckAccessResult>
    </CheckAccessResponse>
  </soap:Body>
</soap:Envelope>

Coverage checklist

Member <WebMethod()> Documented section
String HelloWorld() Yes HelloWorld
ADServiceResponse AddUser(inUserId, inPassword, inName, inGivenName, inSurName, inDescription, inPhoneNum, inMailAddr, inTitle, inInfo, inCompany, inFAXNum, inDivision) Yes AddUser
ADServiceResponse UnlockAccount(inUserId) Yes UnlockAccount
ADServiceResponse AddUserToGroup(inUserId, inGroupName) Yes AddUserToGroup
ADServiceResponse DeleteUser(inUserId) Yes DeleteUser
ADServiceResponse DeleteUserFromGroup(inUserId, inGroupName) Yes DeleteUserFromGroup
Boolean DoesUserExist(inUserId, inExternalDomain) Yes DoesUserExist
ADServiceResponse DoesUserHaveResource(inUserId, inResourceName, inExternalDomain) Yes DoesUserHaveResource
ADServiceResponse ChangeUserAccount(inUserId, inGivenName, inSurName, inDescription, inPhoneNum, inMailAddr, inTitle, inInfo, inCompany, inFAXNum) Yes ChangeUserAccount
ADServiceResponse ChangeUserPassword(inUserId, inNewPassword) Yes ChangeUserPassword
ADServiceResponse ChangeUserPasswordOrGetException(inUserId, inNewPassword) Yes ChangeUserPasswordOrGetException
ADServiceResponse GetUserEmail(inUserId, inExternalDomain) Yes GetUserEmail
ArrayList GetUserGroups(inUserId, inExternalDomain) Yes GetUserGroups
ArrayList GetUserResources(inUserId, inProdEnvironment, inExternalDomain) Yes GetUserResources
ADServiceResponse GetUserFAX(inUserId, inExternalDomain) Yes GetUserFAX
ADServiceResponse GetUserLastLogon(inUserId, inExternalDomain) Yes GetUserLastLogon
ADServiceResponse GetUserPrinter(inUserId) Yes GetUserPrinter
ADServiceResponse IsUserInGroup(inUserId, inGroupName, inExternalDomain) Yes IsUserInGroup
HasAccessResponse CheckAccess() Yes CheckAccess
Enum EResponse No Not an operation - message type consumed by ADServiceResponse, not itself invocable
Structure ADServiceResponse No Not an operation - message type (response shape for most operations)
Structure HasAccessResponse No Not an operation - message type (response shape for CheckAccess)
EResponse ChangePassword(inUserId, inNewPassword) (Private) No Not an operation - private helper behind ChangeUserPassword/ChangeUserPasswordOrGetException
ADServiceResponse AccessDenied() (Private) No Not an operation - private helper that builds the Failure/"Access Denied" sentinel
List(Of String) GetAllowedIPs() (Private) No Not an operation - private helper reading the aduserservices.allowedips configuration setting
String GetIncomingIp() (Private) No Not an operation - private helper reading HTTP_X_FORWARDED_FOR/REMOTE_ADDR
String GetLocalIpAddress() (Private) No Not an operation - private helper, and dead code, never called
PrincipalContext GetContext(inExternalDomain, [inContainer]) (Private) No Not an operation - private helper building the directory context
UserPrincipal GetUserPrincipal(inUserId, inExternalDomain) (Private) No Not an operation - private helper resolving a user principal
GroupPrincipal GetGroupPrincipal(inGroupId, inExternalDomain) (Private) No Not an operation - private helper resolving a group principal
Sub FindUserInResource(ByRef inUserPrin As UserPrincipal, ByRef inGroupPrin As GroupPrincipal) (Private) No Not an operation - private helper, and dead code, never called

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src\ADUserServices\clsADUserServices.asmx
  • src\ADUserServices\clsADUserServices.asmx.vb
  • .saifdocgen\state\runs\20260922-101326-aduserservices\analysis\aduserservices-analysis.md
  • .saifdocgen\state\runs\20260922-101326-aduserservices\analysis\aduserservices-security-analysis.md