---
title: Authorize a machine or service account
summary: Confirm machine membership in an AD group or resource group.
status: draft
owner: SAIF Framework
last_reviewed: 2026-07-30
library: SAIF.Framework.Security.EnvironmentApi
reference_type: package
operation_id: OP-ENV-007
trigger: Caller invokes MachineSecurityService.IsAuthorized
---

# Authorize a machine or service account

This operation is the library's general-purpose primitive for deciding whether a machine or service account belongs to an AD group. It optionally rewrites the requested group name to the SAIF resource-group convention, retrieves the effective membership for that group, compares normalized account names, and fails closed whenever the AD lookup itself fails.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-ENV-007 |
| **Trigger** | Caller requests machine or service-account authorization |
| **Inputs** | `machine`, `groupName`, `isResource`, `isProductionResource`, `recurse` |
| **Outputs** | Authorization `bool` and possibly rewritten `groupName` |
| **Primary components** | `MachineSecurityService.IsAuthorized` |
| **Entry point** | `SAIF.Framework.Security.EnvironmentApi\Core\Services\MachineSecurityService.cs` |

## Steps

1. If `isResource` is `true`, rewrite `groupName` to the SAIF resource convention: append `Test` first for non-production requests, then append `Resource` ([BR-007](../business-rules.md#br-007-production-vs-non-production-ad-resource-name-convention)).
2. Initialize the result to `false` so the method fails closed by default and only flips to `true` once membership is positively confirmed.
3. Retrieve the effective group membership from AD using the configured LDAP path, domain, and the caller's recursion setting.
   - Open the target domain context.
   - Resolve the group's distinguished name.
   - Enumerate nested groups (when requested) and direct users.

   > **Origin**: Step 3 is expanded in [Enumerate AD group membership](enumerate-ad-group-membership.md), which supplies the member list this step consumes.
4. Iterate the returned member names and compare `machine.Trim('$')` to each `member.Trim('$')` case-insensitively, returning `true` as soon as the first match is found ([BR-006](../business-rules.md#br-006-machineservice-account-authorization-via-ad-group-membership)).
5. If the AD lookup throws any exception, write the exception message to `Debug`, leave the result at `false`, and return that fail-closed decision rather than letting the exception escape.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Caller requests machine authorization]) --> Resource{Resource-group rewrite needed?}
	Resource -->|Yes| Rewrite[Append Test and or Resource suffixes]
	Resource -->|No| Members[Read AD membership]
	Rewrite --> Members
	Members --> Match{Normalized machine found?}
	Match -->|Yes| Allow([Return true])
	Match -->|No| Deny([Return false])
	Members -. exception .-> Deny
```

## Failure and edge-case behavior

- Group-name rewriting mutates the caller's `groupName` argument in place because it is passed by reference — callers should inspect the returned value if they need the resolved group name.
- Exceptions raised during the AD lookup never propagate; they are logged to `Debug` and treated as an authorization failure.
- Account-name comparisons ignore case and trim trailing `$` characters from both sides before comparing, so machine and service accounts compare consistently regardless of their AD-formatted suffix.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Security and authorization](../security-authorization.md)

## Sources
- SAIF.Framework.Security.EnvironmentApi\Core\Services\MachineSecurityService.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Services\ADService.cs
