# Auth (legacy)

> Email and password services, kept for integrations that already use them.

Source: https://docs.stxapp.io/sdks/csharp/reference/auth-2fa/

:::note
This page covers the **legacy** email and password path. It is supported for integrations that already use it, and is not recommended for new work.

New integrations should use [API-key authentication](/sdks/csharp/authentication/), which has no login call, no token to expire, and no refresh cycle.
:::

## `STXLoginService`

```csharp
public class STXLoginService
{
    Task<STXUserDataCollection> LoginAsync(
        string email,
        string password,
        bool checkTermsAndConditions = false,
        bool keepSessionAlive = false,
        string deviceId = "C#SDK");
}
```

## `STXTokenService`

```csharp
public class STXTokenService
{
    Task<STXUserDataCollection> LoginAsync(
        string email,
        string password,
        bool keepSessionAlive,
        string deviceId = "C#SDK");

    Task<STXUserDataCollection> RefreshTokenAsync();

    STXTokens Tokens { get; }
}
```

### `STXUserDataCollection`

| | |
|---|---|
| `Token` | Bearer token attached to subsequent GraphQL calls |
| `RefreshToken` | Used by `RefreshTokenAsync` |
| `UserId`, `UserUid`, `SessionId` | Identifiers. `UserId` is what channel topics are keyed on |
| `CurrentLoginAt` | Login timestamp |
| `PromptTncAcceptance` | `true` if the current terms still need accepting |
| `DeviceId`, `AllowMultipleLogins` | Session context |

The token is cached in `STXUserStorage` and attached automatically. You never pass it by hand.

## Keeping the session alive

`keepSessionAlive: true` lets `STXSessionBackgroundService` refresh the token before it expires. It requires a real host, because background services only run under one:

```csharp
var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services => services.ConfigureSTXServices(STXEnvironment.OntarioDemo))
    .Build();
```

The credentials stay in memory in `STXUserStorage` so the background service can re-login if the refresh token itself expires. A failed refresh is reported through `SetSessionMessageAction` rather than thrown, so it cannot stop your host.

## Two-factor authentication

Not available through this SDK. The SDK has no method for completing a 2FA challenge, so an account with 2FA enabled cannot finish logging in through it.

API keys are the supported path for programmatic access and are unaffected by 2FA.

## Migrating

See [Existing integrations](/sdks/csharp/authentication/) for the steps. In short: swap the registration to the API-key overload, replace the user id from the login response with one `GetMeAsync()` call, and drop the `keepSessionAlive` handling.
