microsoft-azure-webjobs-extensions-authentication-events-dot
microsoft/skills
Azure Functions 트리거를 사용하여 사용자 지정 클레임, 속성 수집 및 OTP 전달을 통해 Microsoft Entra ID 인증 흐름을 확장합니다.
...모든 것을 확장하십시오Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents (.NET)
Microsoft Entra ID 사용자 지정 인증 이벤트를 처리하기 위한 Azure Functions 확장 기능입니다.
설치
dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
현재 버전: v1.1.0 (안정판)
지원되는 이벤트
| 이벤트 | 목적 |
|---|---|
| `OnTokenIssuanceStart` | 토큰 발급 중 사용자 지정 클레임 추가 |
| `OnAttributeCollectionStart` | 표시 전 속성 수집 UI 사용자 지정 |
| `OnAttributeCollectionSubmit` | 사용자 제출 후 속성 유효성 검사/수정 |
| `OnOtpSend` | 사용자 지정 OTP 전송(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("Token issuance event for user: {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("No user ID in request");
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. 속성 수집 - UI 사용자 지정(시작 이벤트)
표시되기 전에 속성 수집 페이지를 사용자 지정합니다.
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();
// 옵션 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 = "Sign-up is currently disabled."
// });
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 = "Sign-up from this email domain is not allowed."
});
return response;
}
// 유효성 검사 예시: 유효성 검사 오류 표시
if (string.IsNullOrEmpty(displayName) || displayName.Length
{
{ "displayName", "Name is too short" }
}
});
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, 이메일, 푸시 알림)을 통해 일회용 비밀번호를 전송합니다.
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
{
// SMS 공급자를 통해 OTP 전송
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)
{
// 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에서 사용자 지정 확장을 구성합니다:
- API 등록 Entra ID → 앱 등록
- 사용자 지정 인증 확장 생성 Entra ID → 외부 신원 → 사용자 지정 인증 확장
- 사용자 흐름에 연결 Entra ID → 외부 신원 → 사용자 흐름
필수 앱 등록 설정
Expose an API:
- Application ID URI: api://<your-function-app-name>.azurewebsites.net
- Scope: CustomAuthenticationExtension.Receive.Payload
API Permissions:
- Microsoft Graph: User.Read (delegated)
</your-function-app-name>모범 사례
- 모든 입력 유효성 검사 — 요청 데이터를 신뢰하지 말고 처리 전에 유효성 검사
- 오류 우아하게 처리 — 적절한 오류 응답 반환
- 상관 ID 로깅 — 문제 해결을 위해
CorrelationId사용 - 함수 속도 유지 — 인증 이벤트에는 시간 제한이 있음
- 관리된 신원 사용 — Azure 리소스에 안전하게 접근
- 외부 데이터 캐싱 — 모든 요청에서 느린 조회 피하기
- 로컬 테스트 — 샘플 페이로드와 함께 Azure Functions Core Tools 사용
- 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, "Error processing token issuance event");
// 빈 응답 반환 - 사용자 지정 클레임 없이 인증 계속
// 던지지 마세요 - 이렇게 하면 인증이 실패합니다.
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 |
|---|---|
| NuGet 패키지 | https://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 |
| GitHub 소스 | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents |
---
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 |
모든 파일
1개 파일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
복사





집
