вариант
ДомДом Skill Безопасность microsoft-azure-webjobs-extensions-authentication-events-dot

microsoft-azure-webjobs-extensions-authentication-events-dot

microsoft/skills microsoft/skills

Расширьте потоки аутентификации Microsoft Entra ID с помощью пользовательских заявлений, сбора атрибутов и доставки одноразовых паролей (OTP) с помощью триггеров Azure Functions.

...Расширить все
39
Обновлено время 19 сентября 2026 г.

Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents (.NET)

Расширение Azure Functions для обработки пользовательских событий аутентификации Microsoft Entra ID.

Установка

dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents

Текущая версия: v1.1.0 (стабильная)

Поддерживаемые события

СобытиеНазначение
`OnTokenIssuanceStart`Добавление пользовательских утверждений (claims) в токены в процессе выдачи
`OnAttributeCollectionStart`Настройка интерфейса сбора атрибутов перед отображением
`OnAttributeCollectionSubmit`Проверка/изменение атрибутов после отправки пользователем
`OnOtpSend`Пользовательская доставка одноразовых паролей (SMS, электронная почта и т. д.)

Основные рабочие процессы

1. Обогащение токена (Добавление пользовательских утверждений)

Добавление пользовательских утверждений в токены доступа или токены идентификатора (ID) во время входа в систему.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Extensions.Logging;

public static class TokenEnrichmentFunction
{
    [FunctionName("OnTokenIssuanceStart")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
        ILogger log)
    {
        log.LogInformation("Событие выдачи токена для пользователя: {UserId}", 
            request.Data?.AuthenticationContext?.User?.Id);

        // Создание ответа с пользовательскими утверждениями
        var response = new WebJobsTokenIssuanceStartResponse();

        // Добавление утверждений в токен
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string>
            {
                { "customClaim1", "customValue1" },
                { "department", "Engineering" },
                { "costCenter", "CC-12345" },
                { "apiVersion", "v2" }
            }
        });

        return response;
    }
}
</string>

2. Обогащение токена с внешними данными

Получение утверждений из внешних систем (базы данных, API).

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Text.Json;

public static class TokenEnrichmentWithExternalData
{
    private static readonly HttpClient _httpClient = new();

    [FunctionName("OnTokenIssuanceStartExternal")]
    public static async Task<webjobsauthenticationeventresponse> Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
        ILogger log)
    {
        string? userId = request.Data?.AuthenticationContext?.User?.Id;

        if (string.IsNullOrEmpty(userId))
        {
            log.LogWarning("В запросе отсутствует идентификатор пользователя");
            return new WebJobsTokenIssuanceStartResponse();
        }

        // Получение данных пользователя из внешнего API
        var userProfile = await GetUserProfileAsync(userId);

        var response = new WebJobsTokenIssuanceStartResponse();
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string>
            {
                { "employeeId", userProfile.EmployeeId },
                { "department", userProfile.Department },
                { "roles", string.Join(",", userProfile.Roles) }
            }
        });

        return response;
    }

    private static async Task<userprofile> GetUserProfileAsync(string userId)
    {
        var response = await _httpClient.GetAsync($"https://api.example.com/users/{userId}");
        response.EnsureSuccessStatusCode();
        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<userprofile>(json)!;
    }
}

public record UserProfile(string EmployeeId, string Department, string[] Roles);
</userprofile></userprofile></string></webjobsauthenticationeventresponse>

3. Сбор атрибутов — Настройка интерфейса (Событие начала)

Настройка страницы сбора атрибутов перед её отображением.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class AttributeCollectionStartFunction
{
    [FunctionName("OnAttributeCollectionStart")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsAttributeCollectionStartRequest request,
        ILogger log)
    {
        log.LogInformation("Начало сбора атрибутов для корреляции: {CorrelationId}",
            request.Data?.AuthenticationContext?.CorrelationId);

        var response = new WebJobsAttributeCollectionStartResponse();

        // Вариант 1: Продолжить со стандартным поведением
        response.Actions.Add(new WebJobsContinueWithDefaultBehavior());

        // Вариант 2: Предварительно заполнить атрибуты
        // response.Actions.Add(new WebJobsSetPrefillValues
        // {
        //     Attributes = new Dictionary<string>
        //     {
        //         { "city", "Seattle" },
        //         { "country", "USA" }
        //     }
        // });

        // Вариант 3: Отобразить блокирующую страницу (запретить регистрацию)
        // response.Actions.Add(new WebJobsShowBlockPage
        // {
        //     Message = "Регистрация в настоящее время отключена."
        // });

        return response;
    }
}
</string>

4. Сбор атрибутов — Проверка отправки (Событие отправки)

Проверка и изменение атрибутов после отправки пользователем.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class AttributeCollectionSubmitFunction
{
    [FunctionName("OnAttributeCollectionSubmit")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsAttributeCollectionSubmitRequest request,
        ILogger log)
    {
        var response = new WebJobsAttributeCollectionSubmitResponse();

        // Доступ к отправленным атрибутам
        var attributes = request.Data?.UserSignUpInfo?.Attributes;

        string? email = attributes?["email"]?.ToString();
        string? displayName = attributes?["displayName"]?.ToString();

        // Пример проверки: блокировка определенных доменов электронной почты
        if (email?.EndsWith("@blocked.com") == true)
        {
            response.Actions.Add(new WebJobsShowBlockPage
            {
                Message = "Регистрация с этого домена электронной почты не разрешена."
            });
            return response;
        }

        // Пример проверки: отображение ошибки валидации
        if (string.IsNullOrEmpty(displayName) || displayName.Length 
                {
                    { "displayName", "Имя слишком короткое" }
                }
            });
            return response;
        }

        // Изменение атрибутов перед сохранением
        response.Actions.Add(new WebJobsModifyAttributeValues
        {
            Attributes = new Dictionary<string>
            {
                { "displayName", displayName.Trim() },
                { "city", attributes?["city"]?.ToString()?.ToUpperInvariant() ?? "" }
            }
        });

        return response;
    }
}
</string>

5. Пользовательская доставка OTP

Отправка одноразовых паролей через пользовательские каналы (SMS, электронная почта, push-уведомления).

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class CustomOtpFunction
{
    [FunctionName("OnOtpSend")]
    public static async Task<webjobsauthenticationeventresponse> Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsOnOtpSendRequest request,
        ILogger log)
    {
        var response = new WebJobsOnOtpSendResponse();

        string? phoneNumber = request.Data?.OtpContext?.Identifier;
        string? otp = request.Data?.OtpContext?.OneTimeCode;

        if (string.IsNullOrEmpty(phoneNumber) || string.IsNullOrEmpty(otp))
        {
            log.LogError("Отсутствует номер телефона или OTP");
            response.Actions.Add(new WebJobsOnOtpSendFailed
            {
                Error = "Отсутствуют необходимые данные"
            });
            return response;
        }

        try
        {
            // Отправка OTP через вашего провайдера SMS
            await SendSmsAsync(phoneNumber, $"Ваш код подтверждения: {otp}");

            response.Actions.Add(new WebJobsOnOtpSendSuccess());
            log.LogInformation("OTP успешно отправлен на {PhoneNumber}", phoneNumber);
        }
        catch (Exception ex)
        {
            log.LogError(ex, "Не удалось отправить OTP");
            response.Actions.Add(new WebJobsOnOtpSendFailed
            {
                Error = "Не удалось отправить код подтверждения"
            });
        }

        return response;
    }

    private static async Task SendSmsAsync(string phoneNumber, string message)
    {
        // Реализуйте интеграцию с вашим провайдером SMS (Twilio, Azure Communication Services и т. д.)
        await Task.CompletedTask;
    }
}
</webjobsauthenticationeventresponse>

6. Конфигурация приложения функций

Настройка приложения функций для событий аутентификации.

// Program.cs (Модель изолированного рабочего процесса)
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .Build();

host.Run();
// host.json
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true
      }
    }
  },
  "extensions": {
    "http": {
      "routePrefix": ""
    }
  }
}
// local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}

Справочник основных типов

ТипНазначение
`WebJobsAuthenticationEventsTriggerAttribute`Атрибут триггера функции
`WebJobsTokenIssuanceStartRequest`Запрос события выдачи токена
`WebJobsTokenIssuanceStartResponse`Ответ события выдачи токена
`WebJobsProvideClaimsForToken`Действие по добавлению утверждений
`WebJobsAttributeCollectionStartRequest`Запрос начала сбора атрибутов
`WebJobsAttributeCollectionStartResponse`Ответ начала сбора атрибутов
`WebJobsAttributeCollectionSubmitRequest`Запрос отправки атрибутов
`WebJobsAttributeCollectionSubmitResponse`Ответ отправки атрибутов
`WebJobsSetPrefillValues`Предварительное заполнение значений формы
`WebJobsShowBlockPage`Блокировка пользователя с сообщением
`WebJobsShowValidationError`Отображение ошибок проверки
`WebJobsModifyAttributeValues`Изменение отправленных значений
`WebJobsOnOtpSendRequest`Запрос события отправки OTP
`WebJobsOnOtpSendResponse`Ответ события отправки OTP
`WebJobsOnOtpSendSuccess`OTP успешно отправлен
`WebJobsOnOtpSendFailed`Не удалось отправить OTP
`WebJobsContinueWithDefaultBehavior`Продолжение со стандартным потоком

Конфигурация Entra ID

После развертывания вашего приложения функций настройте пользовательское расширение в Entra ID:

  1. Зарегистрируйте API в Entra ID → Регистрация приложений
  2. Создайте пользовательское расширение аутентификации в Entra ID → Внешние идентификаторы → Пользовательские расширения аутентификации
  3. Свяжите с потоком пользователей в Entra ID → Внешние идентификаторы → Потоки пользователей

Требуемые настройки регистрации приложения

Открыть API:
  - URI идентификатора приложения: api://<имя_вашего_приложения_функций>.azurewebsites.net
  - Область: CustomAuthenticationExtension.Receive.Payload

Разрешения API:
  - Microsoft Graph: User.Read (делегированные)
</your-function-app-name>

Рекомендуемые практики

  1. Проверяйте все входные данные — Никогда не доверяйте данным запроса; проверяйте их перед обработкой
  2. Обработка ошибок должна быть корректной — Возвращайте соответствующие ответы об ошибках
  3. Логируйте идентификаторы корреляции — Используйте CorrelationId для устранения неполадок
  4. Держите функции быстрыми — У событий аутентификации есть ограничения по времени ожидания
  5. Используйте управляемую идентификацию — Безопасный доступ к ресурсам Azure
  6. Кэшируйте внешние данные — Избегайте меденных запросов при каждом обращении
  7. Тестируйте локально — Используйте инструменты ядра Azure Functions с примерами полезной нагрузки
  8. Мониторинг с помощью App Insights — Отслеживайте выполнение функций и ошибки

Обработка ошибок

[FunctionName("OnTokenIssuanceStart")]
public static WebJobsAuthenticationEventResponse Run(
    [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
    ILogger log)
{
    try
    {
        // Ваша логика здесь
        var response = new WebJobsTokenIssuanceStartResponse();
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string> { { "claim", "value" } }
        });
        return response;
    }
    catch (Exception ex)
    {
        log.LogError(ex, "Ошибка при обработке события выдачи токена");

        // Возврат пустого ответа — аутентификация продолжается без пользовательских утверждений
        // НЕ выбрасывать исключение — это приведет к сбою аутентификации
        return new WebJobsTokenIssuanceStartResponse();
    }
}
</string>

Связанные SDK

SDKНазначениеУстановка
`Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents`События аутентификации (этот SDK)`dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents`
`Microsoft.Identity.Web`Аутентификация веб-приложений`dotnet add package Microsoft.Identity.Web`
`Azure.Identity`Аутентификация Azure`dotnet add package Azure.Identity`

Ссылки на справочные материалы

РесурсURL
Пакет NuGethttps://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
Обзор пользовательских расширенийhttps://learn.microsoft.com/entra/identity-platform/custom-extension-overview
События выдачи токенаhttps://learn.microsoft.com/entra/identity-platform/custom-extension-tokenissuancestart-setup
События сбора атрибутовhttps://learn.microsoft.com/entra/identity-platform/custom-extension-attribute-collection
Исходный код на GitHubhttps://github.com/Azure/azure-sdk-for-net/tree/main/sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
Посмотреть на GitHub
---
name: microsoft-azure-webjobs-extensions-authentication-events-dot
description: Extend Microsoft Entra ID authentication flows with custom claims, attribute collection, and OTP delivery using Azure Functions triggers.
license: MIT
---

# Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents (.NET)

Azure Functions extension for handling Microsoft Entra ID custom authentication events.

## Installation

```bash
dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
```

**Current Version**: v1.1.0 (stable)

## Supported Events

| Event | Purpose |
|-------|---------|
| `OnTokenIssuanceStart` | Add custom claims to tokens during issuance |
| `OnAttributeCollectionStart` | Customize attribute collection UI before display |
| `OnAttributeCollectionSubmit` | Validate/modify attributes after user submission |
| `OnOtpSend` | Custom OTP delivery (SMS, email, etc.) |

## Core Workflows

### 1. Token Enrichment (Add Custom Claims)

Add custom claims to access or ID tokens during sign-in.

```csharp
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Extensions.Logging;

public static class TokenEnrichmentFunction
{
    [FunctionName("OnTokenIssuanceStart")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
        ILogger log)
    {
        log.LogInformation("Token issuance event for user: {UserId}", 
            request.Data?.AuthenticationContext?.User?.Id);

        // Create response with custom claims
        var response = new WebJobsTokenIssuanceStartResponse();
        
        // Add claims to the token
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string, string>
            {
                { "customClaim1", "customValue1" },
                { "department", "Engineering" },
                { "costCenter", "CC-12345" },
                { "apiVersion", "v2" }
            }
        });

        return response;
    }
}
```

### 2. Token Enrichment with External Data

Fetch claims from external systems (databases, APIs).

```csharp
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Text.Json;

public static class TokenEnrichmentWithExternalData
{
    private static readonly HttpClient _httpClient = new();

    [FunctionName("OnTokenIssuanceStartExternal")]
    public static async Task<WebJobsAuthenticationEventResponse> Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
        ILogger log)
    {
        string? userId = request.Data?.AuthenticationContext?.User?.Id;
        
        if (string.IsNullOrEmpty(userId))
        {
            log.LogWarning("No user ID in request");
            return new WebJobsTokenIssuanceStartResponse();
        }

        // Fetch user data from external API
        var userProfile = await GetUserProfileAsync(userId);
        
        var response = new WebJobsTokenIssuanceStartResponse();
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string, string>
            {
                { "employeeId", userProfile.EmployeeId },
                { "department", userProfile.Department },
                { "roles", string.Join(",", userProfile.Roles) }
            }
        });

        return response;
    }

    private static async Task<UserProfile> GetUserProfileAsync(string userId)
    {
        var response = await _httpClient.GetAsync($"https://api.example.com/users/{userId}");
        response.EnsureSuccessStatusCode();
        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<UserProfile>(json)!;
    }
}

public record UserProfile(string EmployeeId, string Department, string[] Roles);
```

### 3. Attribute Collection - Customize UI (Start Event)

Customize the attribute collection page before it's displayed.

```csharp
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class AttributeCollectionStartFunction
{
    [FunctionName("OnAttributeCollectionStart")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsAttributeCollectionStartRequest request,
        ILogger log)
    {
        log.LogInformation("Attribute collection start for correlation: {CorrelationId}",
            request.Data?.AuthenticationContext?.CorrelationId);

        var response = new WebJobsAttributeCollectionStartResponse();

        // Option 1: Continue with default behavior
        response.Actions.Add(new WebJobsContinueWithDefaultBehavior());

        // Option 2: Prefill attributes
        // response.Actions.Add(new WebJobsSetPrefillValues
        // {
        //     Attributes = new Dictionary<string, string>
        //     {
        //         { "city", "Seattle" },
        //         { "country", "USA" }
        //     }
        // });

        // Option 3: Show blocking page (prevent sign-up)
        // response.Actions.Add(new WebJobsShowBlockPage
        // {
        //     Message = "Sign-up is currently disabled."
        // });

        return response;
    }
}
```

### 4. Attribute Collection - Validate Submission (Submit Event)

Validate and modify attributes after user submission.

```csharp
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class AttributeCollectionSubmitFunction
{
    [FunctionName("OnAttributeCollectionSubmit")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsAttributeCollectionSubmitRequest request,
        ILogger log)
    {
        var response = new WebJobsAttributeCollectionSubmitResponse();

        // Access submitted attributes
        var attributes = request.Data?.UserSignUpInfo?.Attributes;
        
        string? email = attributes?["email"]?.ToString();
        string? displayName = attributes?["displayName"]?.ToString();

        // Validation example: block certain email domains
        if (email?.EndsWith("@blocked.com") == true)
        {
            response.Actions.Add(new WebJobsShowBlockPage
            {
                Message = "Sign-up from this email domain is not allowed."
            });
            return response;
        }

        // Validation example: show validation error
        if (string.IsNullOrEmpty(displayName) || displayName.Length < 3)
        {
            response.Actions.Add(new WebJobsShowValidationError
            {
                Message = "Display name must be at least 3 characters.",
                AttributeErrors = new Dictionary<string, string>
                {
                    { "displayName", "Name is too short" }
                }
            });
            return response;
        }

        // Modify attributes before saving
        response.Actions.Add(new WebJobsModifyAttributeValues
        {
            Attributes = new Dictionary<string, string>
            {
                { "displayName", displayName.Trim() },
                { "city", attributes?["city"]?.ToString()?.ToUpperInvariant() ?? "" }
            }
        });

        return response;
    }
}
```

### 5. Custom OTP Delivery

Send one-time passwords via custom channels (SMS, email, push notification).

```csharp
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class CustomOtpFunction
{
    [FunctionName("OnOtpSend")]
    public static async Task<WebJobsAuthenticationEventResponse> Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsOnOtpSendRequest request,
        ILogger log)
    {
        var response = new WebJobsOnOtpSendResponse();

        string? phoneNumber = request.Data?.OtpContext?.Identifier;
        string? otp = request.Data?.OtpContext?.OneTimeCode;

        if (string.IsNullOrEmpty(phoneNumber) || string.IsNullOrEmpty(otp))
        {
            log.LogError("Missing phone number or OTP");
            response.Actions.Add(new WebJobsOnOtpSendFailed
            {
                Error = "Missing required data"
            });
            return response;
        }

        try
        {
            // Send OTP via your SMS provider
            await SendSmsAsync(phoneNumber, $"Your verification code is: {otp}");
            
            response.Actions.Add(new WebJobsOnOtpSendSuccess());
            log.LogInformation("OTP sent successfully to {PhoneNumber}", phoneNumber);
        }
        catch (Exception ex)
        {
            log.LogError(ex, "Failed to send OTP");
            response.Actions.Add(new WebJobsOnOtpSendFailed
            {
                Error = "Failed to send verification code"
            });
        }

        return response;
    }

    private static async Task SendSmsAsync(string phoneNumber, string message)
    {
        // Implement your SMS provider integration (Twilio, Azure Communication Services, etc.)
        await Task.CompletedTask;
    }
}
```

### 6. Function App Configuration

Configure the Function App for authentication events.

```csharp
// Program.cs (Isolated worker model)
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .Build();

host.Run();
```

```json
// host.json
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true
      }
    }
  },
  "extensions": {
    "http": {
      "routePrefix": ""
    }
  }
}
```

```json
// local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}
```

## Key Types Reference

| Type | Purpose |
|------|---------|
| `WebJobsAuthenticationEventsTriggerAttribute` | Function trigger attribute |
| `WebJobsTokenIssuanceStartRequest` | Token issuance event request |
| `WebJobsTokenIssuanceStartResponse` | Token issuance event response |
| `WebJobsProvideClaimsForToken` | Action to add claims |
| `WebJobsAttributeCollectionStartRequest` | Attribute collection start request |
| `WebJobsAttributeCollectionStartResponse` | Attribute collection start response |
| `WebJobsAttributeCollectionSubmitRequest` | Attribute submission request |
| `WebJobsAttributeCollectionSubmitResponse` | Attribute submission response |
| `WebJobsSetPrefillValues` | Prefill form values |
| `WebJobsShowBlockPage` | Block user with message |
| `WebJobsShowValidationError` | Show validation errors |
| `WebJobsModifyAttributeValues` | Modify submitted values |
| `WebJobsOnOtpSendRequest` | OTP send event request |
| `WebJobsOnOtpSendResponse` | OTP send event response |
| `WebJobsOnOtpSendSuccess` | OTP sent successfully |
| `WebJobsOnOtpSendFailed` | OTP send failed |
| `WebJobsContinueWithDefaultBehavior` | Continue with default flow |

## Entra ID Configuration

After deploying your Function App, configure the custom extension in Entra ID:

1. **Register the API** in Entra ID → App registrations
2. **Create Custom Authentication Extension** in Entra ID → External Identities → Custom authentication extensions
3. **Link to User Flow** in Entra ID → External Identities → User flows

### Required App Registration Settings

```
Expose an API:
  - Application ID URI: api://<your-function-app-name>.azurewebsites.net
  - Scope: CustomAuthenticationExtension.Receive.Payload

API Permissions:
  - Microsoft Graph: User.Read (delegated)
```

## Best Practices

1. **Validate all inputs** — Never trust request data; validate before processing
2. **Handle errors gracefully** — Return appropriate error responses
3. **Log correlation IDs** — Use `CorrelationId` for troubleshooting
4. **Keep functions fast** — Authentication events have timeout limits
5. **Use managed identity** — Access Azure resources securely
6. **Cache external data** — Avoid slow lookups on every request
7. **Test locally** — Use Azure Functions Core Tools with sample payloads
8. **Monitor with App Insights** — Track function execution and errors

## Error Handling

```csharp
[FunctionName("OnTokenIssuanceStart")]
public static WebJobsAuthenticationEventResponse Run(
    [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
    ILogger log)
{
    try
    {
        // Your logic here
        var response = new WebJobsTokenIssuanceStartResponse();
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string, string> { { "claim", "value" } }
        });
        return response;
    }
    catch (Exception ex)
    {
        log.LogError(ex, "Error processing token issuance event");
        
        // Return empty response - authentication continues without custom claims
        // Do NOT throw - this would fail the authentication
        return new WebJobsTokenIssuanceStartResponse();
    }
}
```

## Related SDKs

| SDK | Purpose | Install |
|-----|---------|---------|
| `Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents` | Auth events (this SDK) | `dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents` |
| `Microsoft.Identity.Web` | Web app authentication | `dotnet add package Microsoft.Identity.Web` |
| `Azure.Identity` | Azure authentication | `dotnet add package Azure.Identity` |

## Reference Links

| Resource | URL |
|----------|-----|
| NuGet Package | https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents |
| Custom Extensions Overview | https://learn.microsoft.com/entra/identity-platform/custom-extension-overview |
| Token Issuance Events | https://learn.microsoft.com/entra/identity-platform/custom-extension-tokenissuancestart-setup |
| Attribute Collection Events | https://learn.microsoft.com/entra/identity-platform/custom-extension-attribute-collection |
| GitHub Source | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents |

Установить microsoft-azure-webjobs-extensions-authentication-events-dot

Скачайте и извлеките файлы навыков в директорию .claude/skills/.

Скачать ZIP

Клонируйте репозиторий и скопируйте файлы навыка в свой проект.

git clone https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-dotnet/skills/microsoft-azure-webjobs-extensions-authentication-events-dotnet # Copy SKILL.md to your .claude/skills/ directory

Копировать Копировать
Быстрая настройка: Скопируйте папку навыка в .claude/skills/ Claude автоматически обнаружит и использует этот навык
Репозиторий microsoft/skills

Похожие навыки

gmgn-portfolio
Обновлено время 1 июля 2026 г.
device-integrity
Обновлено время 29 июня 2026 г.
zeroize-audit
Обновлено время 1 июля 2026 г.
flutter-use-http-package
Обновлено время 30 июня 2026 г.
OR