다음을 통해 공유


Avalonia 앱에 인증 추가

메모

이 제품은 사용 중지되었습니다. .NET 8 이상을 사용하는 프로젝트를 대체하려면 Community Toolkit Datasync 라이브러리참조하세요.

이 자습서에서는 Microsoft Entra ID를 사용하여 TodoApp 프로젝트에 Microsoft 인증을 추가합니다. 이 자습서를 완료하기 전에 프로젝트를 만들고 백 엔드배포했는지 확인합니다.

Microsoft Entra ID를 인증에 사용하지만 Azure Mobile Apps에서 원하는 모든 인증 라이브러리를 사용할 수 있습니다.

백 엔드 서비스에 인증 추가

백 엔드 서비스는 표준 ASP.NET 6 서비스입니다. ASP.NET 6 서비스에 인증을 사용하도록 설정하는 방법을 보여 주는 자습서는 Azure Mobile Apps에서 작동합니다.

백 엔드 서비스에 대해 Microsoft Entra 인증을 사용하도록 설정하려면 다음을 수행해야 합니다.

  • Microsoft Entra ID를 사용하여 애플리케이션을 등록합니다.
  • ASP.NET 6 백 엔드 프로젝트에 인증 검사를 추가합니다.

애플리케이션 등록

먼저 Microsoft Entra 테넌트에 웹 API를 등록하고 다음 단계에 따라 범위를 추가합니다.

  1. Azure Portal로그인합니다.

  2. 여러 테넌트에 액세스할 수 있는 경우 위쪽 메뉴에서 디렉터리 + 구독 필터를 사용하여 애플리케이션을 등록하려는 테넌트로 전환합니다.

  3. Microsoft Entra ID검색하여 선택합니다.

  4. 관리아래에서 새 등록앱 등록을 선택합니다.

    • 이름: 애플리케이션의 이름을 입력합니다. 예를 들어 TodoApp 빠른 시작. 앱 사용자에게 이 이름이 표시됩니다. 나중에 변경할 수 있습니다.
    • 지원되는 계정 유형: 모든 조직 디렉터리(모든 Microsoft Entra 디렉터리 - 다중 테넌트)의 계정 및 개인 Microsoft 계정(예: Skype, Xbox)
  5. 등록선택합니다.

  6. 관리아래에서 범위추가API 노출 선택합니다.

  7. 애플리케이션 ID URI경우 저장을 선택하고계속하여 기본값을 적용합니다.

  8. 다음 세부 정보를 입력합니다.

    • 범위 이름: access_as_user
    • 동의할 수 있는 사람은 누구인가요?: 관리자 및 사용자
    • 관리자 동의 표시 이름: Access TodoApp
    • 관리자 동의 설명: Allows the app to access TodoApp as the signed-in user.
    • 사용자 동의 표시 이름: Access TodoApp
    • 사용자 동의 설명: Allow the app to access TodoApp on your behalf.
    • 상태: 사용
  9. 범위 추가를 완료하려면 범위 추가를 선택합니다.

  10. api://<client-id>/access_as_user(Web API 범위참조)와 유사한 범위 값을 확인합니다. 클라이언트를 구성할 때 범위가 필요합니다.

  11. 개요선택합니다.

  12. Essentials 섹션(Web API 애플리케이션 ID참조)의 애플리케이션(클라이언트) ID 확인합니다. 백 엔드 서비스를 구성하려면 이 값이 필요합니다.

Visual Studio를 열고 TodoAppService.NET6 프로젝트를 선택합니다.

  1. TodoAppService.NET6 프로젝트를 마우스 오른쪽 단추로 클릭한 다음 NuGet 패키지 관리...선택합니다.

  2. 새 탭에서찾아보기 선택한 다음 검색 상자에 microsoft.Identity.Web 입력합니다.

    Visual Studio에서 M S AL NuGet을 추가하는 스크린샷

  3. 패키지를 선택한 다음 설치누릅니다.

  4. 프롬프트에 따라 패키지 설치를 완료합니다.

  5. Program.cs엽니다. using 문 목록에 다음을 추가합니다.

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
  1. builder.Services.AddDbContext()호출 바로 위에 다음 코드를 추가합니다.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
  1. app.MapControllers()호출 바로 위에 다음 코드를 추가합니다.
app.UseAuthentication();
app.UseAuthorization();

이제 Program.cs 다음과 같이 표시됩니다.

using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
  
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
  
if (connectionString == null)
{
  throw new ApplicationException("DefaultConnection is not set");
}
  
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
  
var app = builder.Build();
  
// Initialize the database
using (var scope = app.Services.CreateScope())
{
  var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
  
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
  1. Controllers\TodoItemController.cs편집합니다. 클래스에 [Authorize] 특성을 추가합니다. 클래스는 다음과 같습니다.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;

namespace TodoAppService.NET6.Controllers
{
  [Authorize]
  [Route("tables/todoitem")]
  public class TodoItemController : TableController<TodoItem>
  {
    public TodoItemController(AppDbContext context)
      : base(new EntityTableRepository<TodoItem>(context))
    {
    }
  }
}
  1. appsettings.json편집합니다. 다음 블록을 추가합니다.
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

<client-id> 앞에서 기록한 Web API 애플리케이션 ID 바꿉니다. 완료되면 다음과 같이 표시됩니다.

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Azure에 서비스를 다시 게시합니다.

  1. TodoAppService.NET6 프로젝트를 마우스 오른쪽 단추로 클릭한 다음 게시...선택합니다.
  2. 탭의 오른쪽 위 모서리에서 게시 단추를 선택합니다.

브라우저를 열어 https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0. 이제 서비스는 인증이 필요하다는 401 응답을 반환합니다.

오류를 보여 주는 브라우저의 스크린샷

ID 서비스에 앱 등록

Microsoft 데이터 동기화 프레임워크는 HTTP 트랜잭션의 헤더 내에서 JWT(Json Web Token)를 사용하는 모든 인증 공급자를 기본적으로 지원합니다. 이 애플리케이션은 MSAL(Microsoft 인증 라이브러리) 사용하여 이러한 토큰을 요청하고 로그인한 사용자에게 백 엔드 서비스에 권한을 부여합니다.

네이티브 클라이언트 애플리케이션 구성

MSAL(Microsoft Identity Library)과 같은 클라이언트 라이브러리를 사용하여 앱에서 호스트되는 웹 API에 대한 인증을 허용하도록 네이티브 클라이언트를 등록할 수 있습니다.

  1. Azure Portal새 등록Microsoft Entra ID앱 등록을 선택합니다.

  2. 애플리케이션 등록 페이지에서 다음을 수행합니다.

    • 앱 등록에 대한 이름 입력합니다. native-quickstart 이름을 사용하여 백 엔드 서비스에서 사용하는 이름과 구분할 수 있습니다.
    • 모든 조직 디렉터리(모든 Microsoft Entra 디렉터리 - 다중 테넌트) 및 개인 Microsoft 계정(예: Skype, Xbox)계정을 선택합니다.
    • 리디렉션 URI:
      • 공용 클라이언트(모바일 & 데스크톱)
      • URL quickstart://auth 입력합니다.
  3. 등록선택합니다.

  4. API 사용 권한을내 API사용 권한을 추가합니다.

  5. 백 엔드 서비스에 대해 이전에 만든 앱 등록을 선택합니다. 앱 등록이 표시되지 않으면 access_as_user 범위를 추가했는지 확인합니다.

    Azure Portal의 범위 등록 스크린샷

  6. 사용 권한선택하고 access_as_user선택한 다음사용 권한 추가를 선택합니다.

  7. 모바일 및 데스크톱 애플리케이션인증을 선택합니다.

  8. https://login.microsoftonline.com/common/oauth2/nativeclient옆의 확인란을 선택합니다.

  9. msal{client-id}://auth 옆의 확인란을 선택합니다({client-id} 애플리케이션 ID로 대체).

  10. URI추가를 선택한 다음, 추가 URI를 위해 필드에 http://localhost 추가합니다.

  11. 페이지 아래쪽에서 저장을 선택합니다.

  12. 개요선택합니다. 모바일 앱을 구성하는 데 필요한 애플리케이션(클라이언트) ID(Native Client 애플리케이션 ID참조)를 기록해 둡니다.

세 가지 리디렉션 URL을 정의했습니다.

  • http://localhost WPF 애플리케이션에서 사용됩니다.
  • https://login.microsoftonline.com/common/oauth2/nativeclient UWP 애플리케이션에서 사용됩니다.
  • msal{client-id}://auth 모바일(Android 및 iOS) 애플리케이션에서 사용됩니다.

앱에 Microsoft Identity Client 추가

Visual Studio에서 TodoApp.sln 솔루션을 열고 TodoApp.Avalonia프로젝트를 시작 프로젝트로 설정합니다. MSAL(Microsoft Identity Library)TodoApp.Avalonia 프로젝트에 추가합니다.

플랫폼 프로젝트에 MSAL(Microsoft Identity Library) 추가합니다.

  1. 프로젝트를 마우스 오른쪽 단추로 클릭한 다음 NuGet 패키지 관리...선택합니다.

  2. 찾아보기 탭을 선택합니다.

  3. 검색 상자에 Microsoft.Identity.Client 입력한 다음 Enter 키를 누릅니다.

  4. Microsoft.Identity.Client 결과를 선택한 다음 설치클릭합니다.

    Visual Studio에서 MSAL NuGet을 선택하는 스크린샷

  5. 설치를 계속하려면 사용권 계약에 동의합니다.

네이티브 클라이언트 ID 및 백 엔드 범위를 구성에 추가합니다.

TodoApp.Data 프로젝트를 열고 Constants.cs 파일을 편집합니다. ApplicationIdScopes대한 상수를 추가합니다.

  public static class Constants
  {
      /// <summary>
      /// The base URI for the Datasync service.
      /// </summary>
      public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";

      /// <summary>
      /// The application (client) ID for the native app within Microsoft Entra ID
      /// </summary>
      public static string ApplicationId = "<client-id>";

      /// <summary>
      /// The list of scopes to request
      /// </summary>
      public static string[] Scopes = new[]
      {
          "<scope>"
      };
  }

Microsoft Entra ID에 클라이언트 애플리케이션을 등록할 때 받은 Native Client 애플리케이션 ID, 서비스 애플리케이션을 등록하는 동안 API 노출하는 사용할 때 복사한 Web API 범위 바꿉니다.

TodoApp.Avalonia 프로젝트의 ViewModels 폴더에서 MainWindowViewModel.cs 파일을 엽니다.

파일 맨 위에 다음 using 문을 추가합니다.

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;
using System.Linq;

TodoService 속성을 제거하고 다음 코드로 바꿉다.

public MainWindowViewModel()
{
    IdentityClient = PublicClientApplicationBuilder.Create(Constants.ApplicationId)
        .WithAuthority(AzureCloudInstance.AzurePublic, "common")
        .WithRedirectUri("http://localhost")
        .Build();
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    TodoList = new TodoListViewModel(TodoService);
}

public IPublicClientApplication IdentityClient { get; }

public ITodoService TodoService { get; }

public TodoListViewModel TodoList { get; }

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    var accounts = await IdentityClient.GetAccountsAsync();
    AuthenticationResult? result = null;
    try
    {
        result = await IdentityClient
            .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        result = await IdentityClient
            .AcquireTokenInteractive(Constants.Scopes)
            .ExecuteAsync();
    }
    catch (Exception ex)
    {
        // Display the error text - probably as a pop-up
        Debug.WriteLine($"Error: Authentication failed: {ex.Message}");
    }

    return new AuthenticationToken
    {
        DisplayName = result?.Account?.Username ?? "",
        ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
        Token = result?.AccessToken ?? "",
        UserId = result?.Account?.Username ?? ""
    };
}

GetAuthenticationToken() 메서드는 MSAL(Microsoft Identity Library)과 함께 작동하여 로그인한 사용자에게 백 엔드 서비스에 권한을 부여하는 데 적합한 액세스 토큰을 가져옵니다. 그런 다음 이 함수는 클라이언트를 만들기 위해 RemoteTodoService 전달됩니다. 인증에 성공하면 각 요청에 권한을 부여하는 데 필요한 데이터를 사용하여 AuthenticationToken 생성됩니다. 그렇지 않은 경우 만료된 잘못된 토큰이 대신 생성됩니다.

앱 테스트

F5 눌러 앱을 실행할 수 있어야 합니다. 앱이 실행되면 인증을 요청하는 브라우저가 열립니다. 앱이 처음 실행되면 액세스에 동의하라는 메시지가 표시됩니다.

Microsoft Entra 동의 요청 스크린샷

눌러 앱을 계속 진행합니다. 앱은 이전과 같이 계속됩니다.

다음 단계

다음으로, 오프라인 저장소구현하는 오프라인으로 작동하도록 애플리케이션을 구성합니다.

추가 읽기