---
title: Append a raw Set-Cookie header
summary: Writes a cookie header value to the response without URL-encoding, for legacy-reader compatibility.
status: draft
owner: Framework
last_reviewed: 2026-10-02
library: SAIF.NetCore.LegacyAuth
reference_type: package
operation_id: OP-02
trigger: Called by Issue the legacy auth cookie (step 5), or directly by a consumer.
---

# Append a raw Set-Cookie header

This operation appends an additional `Set-Cookie` header value to the current response, deliberately bypassing `Response.Cookies.Append`'s automatic URL-encoding so the raw Base64 cookie value a legacy reader expects is not altered. It is public on `ILegacyAuthCookieService`, so a consumer can use it to write any cookie this way, not only `SAIFAUTH`.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-02 |
| **Trigger** | Called by [Issue the legacy auth cookie](issue-legacy-auth-cookie.md) step 5, or directly by a consumer |
| **Inputs** | cookie `key`, raw `value`, and the target `HttpContext` (an explicit parameter; the injected accessor is not used here) |
| **Outputs** | One extra `Set-Cookie` header value on `context.Response.Headers` |
| **Primary components** | `LegacyAuthCookieService.AddCookieToHeader` |
| **Entry point** | `src/SAIF.NetCore.LegacyAuth/src/SAIF.NetCore.LegacyAuth/SAIF.NetCore.LegacyAuth/LegacyAuthCookieService.cs` |

## Steps

1. Create a `SetCookieHeaderValue(key, value)` with `Path = "/"` and `HttpOnly = true` ([BR-05](../business-rules.md#br-05-no-url-encoding-on-cookie-value), [BR-06](../business-rules.md#br-06-cookie-attributes-omit-secure-and-samesite))
   - On failure: `SetCookieHeaderValue` validates the cookie name and value; an invalid cookie character throws `ArgumentException` (framework behavior)*.
2. Render it to a header string ([BR-05](../business-rules.md#br-05-no-url-encoding-on-cookie-value))
   - No URL-encoding is applied, leaving Base64 characters such as `+`, `/`, and `=` raw.
3. Append the string to any existing `Set-Cookie` values with `StringValues.Concat`.
   - On failure: if the response has already started, setting headers throws `InvalidOperationException` (framework behavior)*.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    Start(["Trigger: AddCookieToHeader called"]) --> S1["Build SetCookieHeaderValue:<br>Path=/, HttpOnly=true"]
    S1 --> D1{Invalid cookie<br>character?}
    D1 -->|Yes| ErrArg([ArgumentException])
    D1 -->|No| S2["Render to header string<br>no URL-encoding"]
    S2 --> S3["Append to existing<br>Set-Cookie values"]
    S3 --> D2{Response already<br>started?}
    D2 -->|Yes| ErrInv([InvalidOperationException])
    D2 -->|No| EndOk([Header value appended])
```

## Failure and edge-case behavior
- An invalid character in the cookie `key` or `value` throws `ArgumentException` from `SetCookieHeaderValue`'s own validation*.
- Calling this operation after the response has already started sending throws `InvalidOperationException` from the underlying `HttpResponse.Headers` setter*.
- Because no URL-encoding is applied, any raw Base64 ciphertext (including `+`, `/`, `=`) is sent unmodified, which is required for the legacy reader to decrypt it correctly ([BR-05](../business-rules.md#br-05-no-url-encoding-on-cookie-value))

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

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Sources
- `src/SAIF.NetCore.LegacyAuth/src/SAIF.NetCore.LegacyAuth/SAIF.NetCore.LegacyAuth/LegacyAuthCookieService.cs`
