OIDC(OpenID Connect)를 사용하여 ASP.NET Core Blazor Web App 보호
이 문서에서는 GitHub 리포지토리(.NET 8 이상)에서 샘플 앱을 사용하여 OIDC(OpenID Connect)를 사용하여 웹앱을dotnet/blazor-samples
보호하는 Blazor 방법을 설명합니다(다운로드 방법).
이 버전의 문서에서는 BFF(백 엔드 for Frontend) 패턴을 채택 하지 않고 OIDC 구현에 대해 설명합니다. BFF 패턴은 외부 서비스에 대해 인증된 요청을 만드는 데 유용합니다. 앱의 사양에서 BFF 패턴 채택을 요구하는 경우 BFF 패턴을 사용하여 아티클 버전 선택기를 OIDC로 변경합니다.
다음 사양이 적용됩니다.
- 웹앱은 Blazor 전역 대화형 작업과 함께 자동 렌더링 모드를 사용합니다.
- 사용자 지정 인증 상태 공급자 서비스는 서버 및 클라이언트 앱에서 사용자의 인증 상태를 캡처하고 서버와 클라이언트 간에 이동하는 데 사용됩니다.
- 이 앱은 모든 OIDC 인증 흐름의 시작점입니다. OIDC는 앱에서 수동으로 구성되며 Microsoft Entra ID 또는 Microsoft 웹 패키지를 사용하지 않으며 샘플 앱에 Microsoft Azure 호스팅이 필요하지 않습니다. Identity 그러나 샘플 앱은 Entra, Microsoft Identity Web과 함께 사용되며 Azure에서 호스트될 수 있습니다.
- 비대화형 토큰 자동 새로 고침
- 서버 프로젝트에서 데이터에 대한 (웹) API를 안전하게 호출합니다.
샘플 앱
샘플 앱은 다음 두 개의 프로젝트로 구성됩니다.
BlazorWebAppOidc
: 날씨 데이터에 대한 최소 API 엔드포인트 예제를 포함하는 웹앱의 Blazor 서버 쪽 프로젝트입니다.BlazorWebAppOidc.Client
: 웹앱의 Blazor 클라이언트 쪽 프로젝트입니다.
다음 링크를 사용하여 리포지토리 루트의 최신 버전 폴더를 통해 샘플 앱에 액세스합니다. 프로젝트는 BlazorWebAppOidc
.NET 8 이상 폴더에 있습니다.
서버 쪽 Blazor 웹앱 프로젝트(BlazorWebAppOidc
)
이 BlazorWebAppOidc
프로젝트는 웹앱의 Blazor 서버 쪽 프로젝트입니다.
이 파일은 BlazorWebAppOidc.http
날씨 데이터 요청을 테스트하는 데 사용할 수 있습니다. 엔드포인트를 BlazorWebAppOidc
테스트하려면 프로젝트를 실행해야 하며 엔드포인트는 파일로 하드 코딩됩니다. 자세한 내용은 Visual Studio 2022에서 .http 파일 사용을 참조 하세요.
참고 항목
서버 프로젝트는 대화형으로 렌더링된 구성 요소에는 사용되지 IHttpContextAccessor/HttpContext않지만 사용하지 않습니다. 자세한 내용은 ASP.NET Core Blazor 대화형 서버 쪽 렌더링에 대한 위협 완화 지침을 참조하세요.
구성
이 섹션에서는 샘플 앱을 구성하는 방법을 설명합니다.
참고 항목
Microsoft Entra ID 및 Azure AD B2C의 경우 적절한 기본값으로 OIDC 및 Cookie 인증 처리기를 모두 추가하는 Microsoft Identity Web(Microsoft.Identity.Web
NuGet 패키지, API 설명서)에서 사용할 AddMicrosoftIdentityWebApp 수 있습니다. 샘플 앱 및 이 섹션의 지침은 Microsoft Identity Web을 사용하지 않습니다. 이 지침에서는 모든 OIDC 공급자에 대해 OIDC 처리기를 수동으로 구성하는 방법을 보여 줍니다. Microsoft Identity Web 구현에 대한 자세한 내용은 연결된 리소스를 참조하세요.
다음 OpenIdConnectOptions 구성은 호출 시 프로젝트의 Program
파일에서 찾을 수 있습니다 AddOpenIdConnect.
SignInScheme: 인증에 성공한 후 사용자의 ID를 유지하는 미들웨어에 해당하는 인증 체계를 설정합니다. OIDC 처리기는 요청 간에 사용자 자격 증명을 유지할 수 있는 로그인 체계를 사용해야 합니다. 다음 줄은 데모용으로만 제공됩니다. 생략 DefaultSignInScheme 하면 대체 값으로 사용됩니다.
oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
범위 및
openid
profile
(Scope선택 사항):openid
OIDC 처리기가 작동하려면 기본적으로 범위와profile
범위가 구성되지만 범위가 구성에Authentication:Schemes:MicrosoftOidc:Scope
포함된 경우 이를 다시 추가해야 할 수 있습니다. 일반적인 구성 지침은 ASP.NET Core 및 ASP.NET Core Blazor 구성의 구성을 참조하세요.oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
SaveTokens: 성공적인 권한 부여 후에 액세스 및 새로 고침 토큰을 저장할 AuthenticationProperties 지 여부를 정의합니다. 이 속성은 최종 인증cookie의 크기를 줄이기 위해 기본적으로 설정
false
됩니다.oidcOptions.SaveTokens = false;
오프라인 액세스 범위(Scope):
offline_access
새로 고침 토큰에 범위가 필요합니다.oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
Authority 및 ClientId: OIDC 호출에 대한 기관 및 클라이언트 ID를 설정합니다.
oidcOptions.Authority = "{AUTHORITY}"; oidcOptions.ClientId = "{CLIENT ID}";
예시:
- 기관(
{AUTHORITY}
):https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/
(테넌트 IDa3942615-d115-4eb7-bc84-9974abcf5064
사용) - 클라이언트 ID(
{CLIENT ID}
):4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
oidcOptions.Authority = "https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/"; oidcOptions.ClientId = "4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
Microsoft Azure "공통" 기관의 예:
다중 테넌트 앱에 "공통" 기관을 사용해야 합니다. 단일 테넌트 앱에 대해 "공통" 기관을 사용할 수도 있지만 이 섹션의 뒷부분에 나와 있는 것처럼 사용자 지정 IssuerValidator 이 필요합니다.
oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
- 기관(
ClientSecret: OIDC 클라이언트 암호입니다.
다음 예제는 테스트 및 데모용으로만 사용됩니다. 앱의 어셈블리에 클라이언트 비밀을 저장하거나 비밀을 소스 제어에 확인하지 마세요. 사용자 비밀, Azure Key Vault 또는 환경 변수에 클라이언트 비밀을 저장합니다.
인증 체계 구성은 자리 표시자가 기본적으로 체계
MicrosoftOidc
인 위치에서{SCHEME NAME}
builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]
자동으로 읽습니다. 구성이 미리 구성되어 있으므로 구성 키를 통해Authentication:Schemes:MicrosoftOidc:ClientSecret
클라이언트 암호를 자동으로 읽을 수 있습니다. 환경 변수를 사용하는 서버에서 환경 변수Authentication__Schemes__MicrosoftOidc__ClientSecret
의 이름을 다음과 같이 지정합니다.set Authentication__Schemes__MicrosoftOidc__ClientSecret={CLIENT SECRET}
데모 및 테스트 전용인 ClientSecret 경우 직접 설정할 수 있습니다. 배포된 프로덕션 앱에 대한 값을 직접 설정하지 마세요. 보안을 약간 향상하려면 기호를 사용하여 줄을 조건부로 컴파일 합니다
DEBUG
.#if DEBUG oidcOptions.ClientSecret = "{CLIENT SECRET}"; #endif
예시:
클라이언트 암호(
{CLIENT SECRET}
):463471c8c4...f90d674bc9
(표시용으로 단축됨)#if DEBUG oidcOptions.ClientSecret = "463471c8c4...137f90d674bc9"; #endif
ResponseType: 권한 부여 코드 흐름만 수행하도록 OIDC 처리기를 구성합니다. 이 모드에서는 암시적 권한 부여 및 하이브리드 흐름이 필요하지 않습니다.
Entra 또는 Azure Portal의 암시적 권한 부여 및 하이브리드 흐름 앱 등록 구성에서 액세스 토큰 또는 ID 토큰을 반환할 권한 부여 엔드포인트에 대한 확인란을 선택하지 마세요. OIDC 처리기는 권한 부여 엔드포인트에서 반환된 코드를 사용하여 적절한 토큰을 자동으로 요청합니다.
oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
MapInboundClaims및 구성 NameClaimType 및RoleClaimType: 많은 OIDC 서버는 SOAP/WS-Fed 기본값 ClaimTypes대신 "
name
" 및 "role
"를 사용합니다. 설정false
되면 MapInboundClaims 처리기는 클레임 매핑을 수행하지 않으며 JWT의 클레임 이름은 앱에서 직접 사용됩니다. 다음 예제에서는 역할 클레임 유형을 "roles
"로 설정하며 이는 MICROSOFT Entra ID(ME-ID)에 적합합니다. 자세한 내용은 ID 공급자의 설명서를 참조하세요.
참고 항목
MapInboundClaims 는 클레임 이름을 바꾸는 것을 false
방지하는 대부분의 OIDC 공급자에 대해 설정해야 합니다.
oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
경로 구성: 경로는 OIDC 공급자에 애플리케이션을 등록할 때 구성된 리디렉션 URI(로그인 콜백 경로) 및 로그아웃 후 리디렉션(로그아웃 콜백 경로) 경로와 일치해야 합니다. Azure Portal에서 경로는 앱 등록의 인증 블레이드에서 구성됩니다. 로그인 및 로그아웃 경로는 모두 리디렉션 URI로 등록해야 합니다. 기본값은 다음과 같습니다
/signin-oidc
/signout-callback-oidc
.CallbackPath: 사용자 에이전트가 반환되는 앱의 기본 경로 내의 요청 경로입니다.
Entra 또는 Azure Portal에서 웹 플랫폼 구성의 리디렉션 URI에서 경로를 설정합니다.
https://localhost/signin-oidc
참고 항목
Microsoft Entra ID를 사용하는 경우 주소에 포트
localhost
가 필요하지 않습니다. 대부분의 다른 OIDC 공급자에는 올바른 포트가 필요합니다.SignedOutCallbackPath: ID 공급자에서 로그아웃한 후 사용자 에이전트가 반환되는 앱의 기본 경로 내의 요청 경로입니다.
Entra 또는 Azure Portal에서 웹 플랫폼 구성의 리디렉션 URI에서 경로를 설정합니다.
https://localhost/signout-callback-oidc
참고 항목
Microsoft Entra ID를 사용하는 경우 주소에 포트
localhost
가 필요하지 않습니다. 대부분의 다른 OIDC 공급자에는 올바른 포트가 필요합니다.참고 항목
Microsoft Identity Web을 사용하는 경우 공급자는 현재 기관(
https://login.microsoftonline.com/{TENANT ID}/v2.0/
)이 사용되는 경우에만microsoftonline.com
다시 SignedOutCallbackPath 리디렉션됩니다. Microsoft Identity Web에서 "공통" 기관을 사용할 수 있는 경우에는 이 제한이 없습니다. 자세한 내용은 기관 URL에 테넌트 ID(AzureAD/microsoft-authentication-library-for-js
#5783)가 포함된 경우 postLogoutRedirectUri가 작동하지 않음을 참조하세요.RemoteSignOutPath: 이 경로에서 수신된 요청으로 인해 처리기가 로그아웃 체계를 사용하여 로그아웃을 호출합니다.
Entra 또는 Azure Portal에서 프런트 채널 로그아웃 URL을 설정합니다.
https://localhost/signout-oidc
참고 항목
Microsoft Entra ID를 사용하는 경우 주소에 포트
localhost
가 필요하지 않습니다. 대부분의 다른 OIDC 공급자에는 올바른 포트가 필요합니다.
oidcOptions.CallbackPath = new PathString("{PATH}"); oidcOptions.SignedOutCallbackPath = new PathString("{PATH}"); oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
예제(기본값):
oidcOptions.CallbackPath = new PathString("/signin-oidc"); oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
(Microsoft Azure는 "공통" 엔드포인트만 사용) TokenValidationParameters.IssuerValidator: 많은 OIDC 공급자가 기본 발급자 유효성 검사기를 사용하지만, 반환된
https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
테넌트 ID({TENANT ID}
)로 매개 변수가 있는 발급자를 고려해야 합니다. 자세한 내용은 OpenID Connect 및 Azure AD "공통" 엔드포인트를 사용하는 SecurityTokenInvalidIssuerException(AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
#1731)을 참조하세요."공통" 엔드포인트가 있는 Microsoft Entra ID 또는 Azure AD B2C를 사용하는 앱에만 해당합니다.
var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority); oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
샘플 앱 코드
샘플 앱에서 다음 기능을 검사합니다.
- 사용자 지정 새로 고침(
CookieOidcRefresher.cs
)의 도움으로 자동 비대화 cookie 형 토큰 새로 고침 PersistingAuthenticationStateProvider
클래스(PersistingAuthenticationStateProvider.cs
)는 인증 상태를 클라이언트로 이동하는 데 사용하는 PersistentComponentState 서버 쪽 AuthenticationStateProvider 이며 WebAssembly 애플리케이션의 수명 동안 고정됩니다.- 날씨 데이터에 대한 웹앱에 Blazor 대한 요청 예제는 파일()의 최소 API 엔드포인트(
/weather-forecast
Program.cs
)에Program
의해 처리됩니다. 엔드포인트를 호출 RequireAuthorization하려면 권한 부여가 필요합니다. 프로젝트에 추가하는 모든 컨트롤러의 경우 컨트롤러 또는 작업에 특성을 추가[Authorize]
합니다. - 앱은 서버 프로젝트에서 날씨 데이터에 대한 (웹) API를 안전하게 호출합니다.
- 서버에서
Weather
구성 요소를 렌더링할 때 구성 요소는 서버에서ServerWeatherForecaster
날씨 데이터를 직접 가져옵니다(웹 API 호출을 통해서가 아님). - 구성 요소가 클라이언트에서 렌더링될 때 구성 요소는 미리 구성된 HttpClient (클라이언트 프로젝트의 파일)를 사용하여 서버 프로젝트에
Program
대한 웹 API 호출을 만드는 서비스 구현을 사용합니다ClientWeatherForecaster
. 서버 프로젝트의 파일에 정의된 최소 API 엔드포인트(/weather-forecast
)는Program
날씨 데이터를 가져와ServerWeatherForecaster
서 클라이언트에 반환합니다.
- 서버에서
Web Apps에서 서비스 추상화를 사용하여 (웹) API 호출에 Blazor 대한 자세한 내용은 ASP.NET Core Blazor 앱에서 웹 API 호출을 참조하세요.
클라이언트 쪽 Blazor 웹앱 프로젝트(BlazorWebAppOidc.Client
)
이 BlazorWebAppOidc.Client
프로젝트는 웹앱의 Blazor 클라이언트 쪽 프로젝트입니다.
PersistentAuthenticationStateProvider
클래스(PersistentAuthenticationStateProvider.cs
)는 서버에서 렌더링될 때 페이지에 유지되는 데이터를 검색하여 사용자의 인증 상태를 결정하는 클라이언트 쪽 AuthenticationStateProvider 입니다. 인증 상태는 WebAssembly 애플리케이션의 수명 동안 고정됩니다.
사용자가 로그인하거나 로그아웃해야 하는 경우 전체 페이지 다시 로드가 필요합니다.
샘플 앱은 표시 목적으로 사용자 이름과 이메일만 제공합니다. 후속 요청을 할 때 서버에 인증하는 토큰은 포함되지 않습니다. 이 토큰은 서버에 대한 HttpClient 요청에 포함된 토큰을 cookie 사용하여 별도로 작동합니다.
이 버전의 문서에서는 BFF(백 엔드 for Frontend) 패턴을 사용하여 OIDC 구현에 대해 설명합니다. 앱의 사양에서 BFF 패턴 채택을 요구하지 않는 경우 BFF 패턴 없이 아티클 버전 선택기를 OIDC로 변경합니다.
다음 사양이 적용됩니다.
- 웹앱은 Blazor 전역 대화형 작업과 함께 자동 렌더링 모드를 사용합니다.
- 사용자 지정 인증 상태 공급자 서비스는 서버 및 클라이언트 앱에서 사용자의 인증 상태를 캡처하고 서버와 클라이언트 간에 이동하는 데 사용됩니다.
- 이 앱은 모든 OIDC 인증 흐름의 시작점입니다. OIDC는 앱에서 수동으로 구성되며 Microsoft Entra ID 또는 Microsoft 웹 패키지를 사용하지 않으며 샘플 앱에 Microsoft Azure 호스팅이 필요하지 않습니다. Identity 그러나 샘플 앱은 Entra, Microsoft Identity Web과 함께 사용되며 Azure에서 호스트될 수 있습니다.
- 비대화형 토큰 자동 새로 고침
- BFF(프런트 엔드용 백 엔드) 패턴은 백 엔드 앱의 일기 예보 엔드포인트에 대한 요청을 프록시하기 위해 서비스 검색을 위한 .NET Aspire 및 YARP를 사용하여 채택됩니다.
- 백 엔드 웹 API는 JWT 전달자 인증을 사용하여 로그인cookie에서 웹앱에서 저장한 Blazor JWT 토큰의 유효성을 검사합니다.
- Aspire는 .NET 클라우드 네이티브 앱을 빌드하는 환경을 개선합니다. 분산 앱을 빌드하고 실행하기 위한 일관되고 의견 있는 도구 및 패턴 집합을 제공합니다.
- YARP(Yet Another Reverse Proxy)는 역방향 프록시 서버를 만드는 데 사용되는 라이브러리입니다.
.NET Aspire에 대한 자세한 내용은 .NET Aspire의 일반 공급: .NET 클라우드 네이티브 개발 간소화(2024년 5월)를 참조하세요.
전제 조건
.NET Aspire 에는 Visual Studio 버전 17.10 이상이 필요합니다.
샘플 앱
샘플 앱은 다음 5개의 프로젝트로 구성됩니다.
- .NET 갈망:
Aspire.AppHost
: 앱의 높은 수준의 오케스트레이션 문제를 관리하는 데 사용됩니다.Aspire.ServiceDefaults
: 필요에 따라 확장 및 사용자 지정할 수 있는 기본 .NET Aspire 앱 구성을 포함합니다.
MinimalApiJwt
: 날씨 데이터에 대한 최소 API 엔드포인트 예제 를 포함하는 백 엔드 웹 API 입니다.BlazorWebAppOidc
: 웹앱의 Blazor 서버 쪽 프로젝트입니다.BlazorWebAppOidc.Client
: 웹앱의 Blazor 클라이언트 쪽 프로젝트입니다.
다음 링크를 사용하여 리포지토리 루트의 최신 버전 폴더를 통해 샘플 앱에 액세스합니다. 프로젝트는 BlazorWebAppOidcBff
.NET 8 이상 폴더에 있습니다.
.NET Aspire 프로젝트
.NET Aspire 사용에 대한 자세한 내용 및 .ServiceDefaults
샘플 앱의 프로젝트에 대한 .AppHost
자세한 내용은 .NET Aspire 설명서를 참조하세요.
.NET Aspire의 필수 구성 요소를 충족했는지 확인합니다. 자세한 내용은 빠른 시작: 첫 번째 .NET Aspire 앱 빌드의 필수 구성 요소 섹션을 참조하세요.
샘플 앱은 개발 테스트 중에 사용할 안전하지 않은 HTTP 시작 프로필(http
)만 구성합니다. 안전하지 않고 안전한 시작 설정 프로필의 예를 비롯한 자세한 내용은 .NET Aspire(.NET Aspire 설명서)에서 안전하지 않은 전송 허용을 참조하세요.
서버 쪽 Blazor 웹앱 프로젝트(BlazorWebAppOidc
)
이 BlazorWebAppOidc
프로젝트는 웹앱의 Blazor 서버 쪽 프로젝트입니다. 이 프로젝트는 YARP를 사용하여 인증cookie에 저장된 백 엔드 웹 API 프로젝트(MinimalApiJwt
)access_token
의 일기 예보 엔드포인트에 대한 요청을 프록시합니다.
이 파일은 BlazorWebAppOidc.http
날씨 데이터 요청을 테스트하는 데 사용할 수 있습니다. 엔드포인트를 BlazorWebAppOidc
테스트하려면 프로젝트를 실행해야 하며 엔드포인트는 파일로 하드 코딩됩니다. 자세한 내용은 Visual Studio 2022에서 .http 파일 사용을 참조 하세요.
참고 항목
서버 프로젝트는 대화형으로 렌더링된 구성 요소에는 사용되지 IHttpContextAccessor/HttpContext않지만 사용하지 않습니다. 자세한 내용은 ASP.NET Core Blazor 대화형 서버 쪽 렌더링에 대한 위협 완화 지침을 참조하세요.
구성
이 섹션에서는 샘플 앱을 구성하는 방법을 설명합니다.
참고 항목
Microsoft Entra ID 및 Azure AD B2C의 경우 적절한 기본값으로 OIDC 및 Cookie 인증 처리기를 모두 추가하는 Microsoft Identity Web(Microsoft.Identity.Web
NuGet 패키지, API 설명서)에서 사용할 AddMicrosoftIdentityWebApp 수 있습니다. 샘플 앱 및 이 섹션의 지침은 Microsoft Identity Web을 사용하지 않습니다. 이 지침에서는 모든 OIDC 공급자에 대해 OIDC 처리기를 수동으로 구성하는 방법을 보여 줍니다. Microsoft Identity Web 구현에 대한 자세한 내용은 연결된 리소스를 참조하세요.
다음 OpenIdConnectOptions 구성은 호출 시 프로젝트의 Program
파일에서 찾을 수 있습니다 AddOpenIdConnect.
SignInScheme: 인증에 성공한 후 사용자의 ID를 유지하는 미들웨어에 해당하는 인증 체계를 설정합니다. OIDC 처리기는 요청 간에 사용자 자격 증명을 유지할 수 있는 로그인 체계를 사용해야 합니다. 다음 줄은 데모용으로만 제공됩니다. 생략 DefaultSignInScheme 하면 대체 값으로 사용됩니다.
oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
범위 및
openid
profile
(Scope선택 사항):openid
OIDC 처리기가 작동하려면 기본적으로 범위와profile
범위가 구성되지만 범위가 구성에Authentication:Schemes:MicrosoftOidc:Scope
포함된 경우 이를 다시 추가해야 할 수 있습니다. 일반적인 구성 지침은 ASP.NET Core 및 ASP.NET Core Blazor 구성의 구성을 참조하세요.oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
SaveTokens: 성공적인 권한 부여 후에 액세스 및 새로 고침 토큰을 저장할 AuthenticationProperties 지 여부를 정의합니다. 이 값은 백 엔드 웹 API 프로젝트(
MinimalApiJwt
)의 날씨 데이터에 대한 요청을 인증하도록true
설정됩니다.oidcOptions.SaveTokens = true;
오프라인 액세스 범위(Scope):
offline_access
새로 고침 토큰에 범위가 필요합니다.oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
웹 API에서 날씨 데이터를 가져오는 범위(Scope): 범위는
Weather.Get
API 노출 아래의 Azure 또는 Entra 포털에서 구성됩니다. 이는 백 엔드 웹 API 프로젝트(MinimalApiJwt
)가 전달자 JWT를 사용하여 액세스 토큰의 유효성을 검사하는 데 필요합니다.oidcOptions.Scope.Add("{APP ID URI}/{API NAME}");
예시:
- 앱 ID URI(
{APP ID URI}
):https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
- 디렉터리 이름(
{DIRECTORY NAME}
):contoso
- 애플리케이션(클라이언트) ID(
{CLIENT ID}
):4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
- 디렉터리 이름(
- ()의
MinimalApiJwt
{API NAME}
날씨 데이터에 대해 구성된 범위:Weather.Get
oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f/Weather.Get");
앞의 예제는 AAD B2C 테넌트 유형을 사용하여 테넌트에 등록된 앱과 관련이 있습니다. 앱이 ME-ID 테넌트에 등록된 경우 앱 ID URI가 다르므로 범위가 다릅니다.
예시:
- 앱 ID URI(
{APP ID URI}
):api://{CLIENT ID}
애플리케이션(클라이언트) ID({CLIENT ID}
):4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
- ()의
MinimalApiJwt
{API NAME}
날씨 데이터에 대해 구성된 범위:Weather.Get
oidcOptions.Scope.Add("api://4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f/Weather.Get");
- 앱 ID URI(
Authority 및 ClientId: OIDC 호출에 대한 기관 및 클라이언트 ID를 설정합니다.
oidcOptions.Authority = "{AUTHORITY}"; oidcOptions.ClientId = "{CLIENT ID}";
예시:
- 기관(
{AUTHORITY}
):https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/
(테넌트 IDa3942615-d115-4eb7-bc84-9974abcf5064
사용) - 클라이언트 ID(
{CLIENT ID}
):4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
oidcOptions.Authority = "https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/"; oidcOptions.ClientId = "4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
Microsoft Azure "공통" 기관의 예:
다중 테넌트 앱에 "공통" 기관을 사용해야 합니다. 단일 테넌트 앱에 대해 "공통" 기관을 사용할 수도 있지만 이 섹션의 뒷부분에 나와 있는 것처럼 사용자 지정 IssuerValidator 이 필요합니다.
oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
- 기관(
ClientSecret: OIDC 클라이언트 암호입니다.
다음 예제는 테스트 및 데모용으로만 사용됩니다. 앱의 어셈블리에 클라이언트 비밀을 저장하거나 비밀을 소스 제어에 확인하지 마세요. 사용자 비밀, Azure Key Vault 또는 환경 변수에 클라이언트 비밀을 저장합니다.
인증 체계 구성은 자리 표시자가 기본적으로 체계
MicrosoftOidc
인 위치에서{SCHEME NAME}
builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]
자동으로 읽습니다. 구성이 미리 구성되어 있으므로 구성 키를 통해Authentication:Schemes:MicrosoftOidc:ClientSecret
클라이언트 암호를 자동으로 읽을 수 있습니다. 환경 변수를 사용하는 서버에서 환경 변수Authentication__Schemes__MicrosoftOidc__ClientSecret
의 이름을 다음과 같이 지정합니다.set Authentication__Schemes__MicrosoftOidc__ClientSecret={CLIENT SECRET}
데모 및 테스트 전용인 ClientSecret 경우 직접 설정할 수 있습니다. 배포된 프로덕션 앱에 대한 값을 직접 설정하지 마세요. 보안을 약간 향상하려면 기호를 사용하여 줄을 조건부로 컴파일 합니다
DEBUG
.#if DEBUG oidcOptions.ClientSecret = "{CLIENT SECRET}"; #endif
예시:
클라이언트 암호(
{CLIENT SECRET}
):463471c8c4...f90d674bc9
(표시용으로 단축됨)#if DEBUG oidcOptions.ClientSecret = "463471c8c4...137f90d674bc9"; #endif
ResponseType: 권한 부여 코드 흐름만 수행하도록 OIDC 처리기를 구성합니다. 이 모드에서는 암시적 권한 부여 및 하이브리드 흐름이 필요하지 않습니다.
Entra 또는 Azure Portal의 암시적 권한 부여 및 하이브리드 흐름 앱 등록 구성에서 액세스 토큰 또는 ID 토큰을 반환할 권한 부여 엔드포인트에 대한 확인란을 선택하지 마세요. OIDC 처리기는 권한 부여 엔드포인트에서 반환된 코드를 사용하여 적절한 토큰을 자동으로 요청합니다.
oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
MapInboundClaims및 구성 NameClaimType 및RoleClaimType: 많은 OIDC 서버는 SOAP/WS-Fed 기본값 ClaimTypes대신 "
name
" 및 "role
"를 사용합니다. 설정false
되면 MapInboundClaims 처리기는 클레임 매핑을 수행하지 않으며 JWT의 클레임 이름은 앱에서 직접 사용됩니다. 다음 예제에서는 역할 클레임 유형을 "roles
"로 설정하며 이는 MICROSOFT Entra ID(ME-ID)에 적합합니다. 자세한 내용은 ID 공급자의 설명서를 참조하세요.
참고 항목
MapInboundClaims 는 클레임 이름을 바꾸는 것을 false
방지하는 대부분의 OIDC 공급자에 대해 설정해야 합니다.
oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
경로 구성: 경로는 OIDC 공급자에 애플리케이션을 등록할 때 구성된 리디렉션 URI(로그인 콜백 경로) 및 로그아웃 후 리디렉션(로그아웃 콜백 경로) 경로와 일치해야 합니다. Azure Portal에서 경로는 앱 등록의 인증 블레이드에서 구성됩니다. 로그인 및 로그아웃 경로는 모두 리디렉션 URI로 등록해야 합니다. 기본값은 다음과 같습니다
/signin-oidc
/signout-callback-oidc
.CallbackPath: 사용자 에이전트가 반환되는 앱의 기본 경로 내의 요청 경로입니다.
Entra 또는 Azure Portal에서 웹 플랫폼 구성의 리디렉션 URI에서 경로를 설정합니다.
https://localhost/signin-oidc
참고 항목
주소에는 포트가
localhost
필요하지 않습니다.SignedOutCallbackPath: ID 공급자에서 로그아웃한 후 사용자 에이전트가 반환되는 앱의 기본 경로 내의 요청 경로입니다.
Entra 또는 Azure Portal에서 웹 플랫폼 구성의 리디렉션 URI에서 경로를 설정합니다.
https://localhost/signout-callback-oidc
참고 항목
주소에는 포트가
localhost
필요하지 않습니다.참고 항목
Microsoft Identity Web을 사용하는 경우 공급자는 현재 기관(
https://login.microsoftonline.com/{TENANT ID}/v2.0/
)이 사용되는 경우에만microsoftonline.com
다시 SignedOutCallbackPath 리디렉션됩니다. Microsoft Identity Web에서 "공통" 기관을 사용할 수 있는 경우에는 이 제한이 없습니다. 자세한 내용은 기관 URL에 테넌트 ID(AzureAD/microsoft-authentication-library-for-js
#5783)가 포함된 경우 postLogoutRedirectUri가 작동하지 않음을 참조하세요.RemoteSignOutPath: 이 경로에서 수신된 요청으로 인해 처리기가 로그아웃 체계를 사용하여 로그아웃을 호출합니다.
Entra 또는 Azure Portal에서 프런트 채널 로그아웃 URL을 설정합니다.
https://localhost/signout-oidc
참고 항목
주소에는 포트가
localhost
필요하지 않습니다.
oidcOptions.CallbackPath = new PathString("{PATH}"); oidcOptions.SignedOutCallbackPath = new PathString("{PATH}"); oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
예제(기본값):
oidcOptions.CallbackPath = new PathString("/signin-oidc"); oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
(Microsoft Azure는 "공통" 엔드포인트만 사용) TokenValidationParameters.IssuerValidator: 많은 OIDC 공급자가 기본 발급자 유효성 검사기를 사용하지만, 반환된
https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
테넌트 ID({TENANT ID}
)로 매개 변수가 있는 발급자를 고려해야 합니다. 자세한 내용은 OpenID Connect 및 Azure AD "공통" 엔드포인트를 사용하는 SecurityTokenInvalidIssuerException(AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
#1731)을 참조하세요."공통" 엔드포인트가 있는 Microsoft Entra ID 또는 Azure AD B2C를 사용하는 앱에만 해당합니다.
var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority); oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
샘플 앱 코드
샘플 앱에서 다음 기능을 검사합니다.
- 사용자 지정 새로 고침(
CookieOidcRefresher.cs
)의 도움으로 자동 비대화 cookie 형 토큰 새로 고침 PersistingAuthenticationStateProvider
클래스(PersistingAuthenticationStateProvider.cs
)는 인증 상태를 클라이언트로 이동하는 데 사용하는 PersistentComponentState 서버 쪽 AuthenticationStateProvider 이며 WebAssembly 애플리케이션의 수명 동안 고정됩니다.- 웹앱에 Blazor 대한 요청은 백 엔드 웹 API 프로젝트(
MinimalApiJwt
)에 프록시됩니다.MapForwarder
파일Program
에서 나가는 요청, 사용자 지정된 변환 및 기본 HTTP 클라이언트에 대한 기본 구성을 사용하여 지정된 패턴과 일치하는 HTTP 요청을 특정 대상에 직접 전달합니다.- 서버에서
Weather
구성 요소를 렌더링할 때 구성 요소는 사용자의 액세스 토큰을 사용하여 날씨 데이터에 대한 요청을 프록시하는 데 사용합니다ServerWeatherForecaster
. - 구성 요소가 클라이언트에서 렌더링될 때 구성 요소는 미리 구성된 HttpClient (클라이언트 프로젝트의 파일)를 사용하여 서버 프로젝트에
Program
대한 웹 API 호출을 만드는 서비스 구현을 사용합니다ClientWeatherForecaster
. 서버 프로젝트의Program
파일에 정의된 최소 API 엔드포인트(/weather-forecast
)는 날씨 데이터를 가져오기 위해 사용자의 액세스 토큰으로 요청을 변환합니다.
- 서버에서
Web Apps에서 서비스 추상화를 사용하여 (웹) API 호출에 Blazor 대한 자세한 내용은 ASP.NET Core Blazor 앱에서 웹 API 호출을 참조하세요.
클라이언트 쪽 Blazor 웹앱 프로젝트(BlazorWebAppOidc.Client
)
이 BlazorWebAppOidc.Client
프로젝트는 웹앱의 Blazor 클라이언트 쪽 프로젝트입니다.
PersistentAuthenticationStateProvider
클래스(PersistentAuthenticationStateProvider.cs
)는 서버에서 렌더링될 때 페이지에 유지되는 데이터를 검색하여 사용자의 인증 상태를 결정하는 클라이언트 쪽 AuthenticationStateProvider 입니다. 인증 상태는 WebAssembly 애플리케이션의 수명 동안 고정됩니다.
사용자가 로그인하거나 로그아웃해야 하는 경우 전체 페이지 다시 로드가 필요합니다.
샘플 앱은 표시 목적으로 사용자 이름과 이메일만 제공합니다. 후속 요청을 할 때 서버에 인증하는 토큰은 포함되지 않습니다. 이 토큰은 서버에 대한 HttpClient 요청에 포함된 토큰을 cookie 사용하여 별도로 작동합니다.
백 엔드 웹 API 프로젝트(MinimalApiJwt
)
이 MinimalApiJwt
프로젝트는 여러 프런트 엔드 프로젝트에 대한 백 엔드 웹 API입니다. 이 프로젝트는 날씨 데이터에 대한 최소 API 엔드포인트를 구성합니다. 웹앱 서버 쪽 프로젝트()의 Blazor 요청은 프로젝트에 프록시됩니다MinimalApiJwt
.BlazorWebAppOidc
구성
프로젝트 JwtBearerOptions 파일의 AddJwtBearer 호출에서 프로젝트를 Program
구성합니다.
Audience: 받은 OpenID Connect 토큰의 대상 그룹을 설정합니다.
Azure 또는 Entra 포털에서: API 노출 아래에 범위를 추가할
Weather.Get
때 구성된 애플리케이션 ID URI의 경로에만 값을 일치합니다.jwtOptions.Audience = "{APP ID URI}";
예시:
앱 ID URI(
{APP ID URI}
):https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
:- 디렉터리 이름(
{DIRECTORY NAME}
):contoso
- 애플리케이션(클라이언트) ID(
{CLIENT ID}
):4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
jwtOptions.Audience = "https://contoso.onmicrosoft.com/4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
앞의 예제는 AAD B2C 테넌트 유형을 사용하여 테넌트에 등록된 앱과 관련이 있습니다. 앱이 ME-ID 테넌트에 등록된 경우 앱 ID URI가 다르므로 대상 그룹은 다릅니다.
예시:
앱 ID URI(
{APP ID URI}
):api://{CLIENT ID}
애플리케이션(클라이언트) ID({CLIENT ID}
):4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
jwtOptions.Audience = "api://4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
- 디렉터리 이름(
Authority: OpenID Connect를 호출하기 위한 기관을 설정합니다. 다음에서 OIDC 처리기에 대해 구성된 기관 값과 일치합니다.
BlazorWebAppOidc/Program.cs
jwtOptions.Authority = "{AUTHORITY}";
예시:
기관(
{AUTHORITY}
):https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/
(테넌트 IDa3942615-d115-4eb7-bc84-9974abcf5064
사용)jwtOptions.Authority = "https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/";
앞의 예제는 AAD B2C 테넌트 유형을 사용하여 테넌트에 등록된 앱과 관련이 있습니다. 앱이 ME-ID 테넌트에 등록된 경우 기관은 ID 공급자가 반환한 JWT의 발급자(
iss
)와 일치해야 합니다.jwtOptions.Authority = "https://sts.windows.net/a3942615-d115-4eb7-bc84-9974abcf5064/";
날씨 데이터에 대한 최소 API
프로젝트 파일에서 일기 예보 데이터 엔드포인트를 Program
보호합니다.
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
확장 메서드에는 RequireAuthorization 경로 정의에 대한 권한 부여가 필요합니다. 프로젝트에 추가하는 모든 컨트롤러의 경우 컨트롤러 또는 작업에 특성을 추가 [Authorize]
합니다.
대화형 서버 쪽 렌더링을 채택하는 구성 요소 추가
앱은 구성 요소를 통해 Routes
전역 대화형 자동 렌더링을 사용하므로 구성 요소 정의 파일.razor
()에서 대화형 서버 쪽 렌더링(대화형 SSR, @rendermode InteractiveServer
)을 지정하는 개별 구성 요소가 프로젝트의 Pages
폴더에 .Client
배치됩니다.
이러한 구성 요소는 서버에서 .Client
만 렌더링되므로 프로젝트에 대화형 SSR 구성 요소를 배치하는 것은 직관적이지 않습니다.
대화형 SSR 구성 요소를 서버 프로젝트의 Components/Pages
폴더에 배치하면 구성 요소가 정상적으로 미리 렌더링되고 사용자의 브라우저에 간략하게 표시됩니다. 그러나 클라이언트 쪽 라우터는 구성 요소를 찾을 수 없으므로 궁극적으로 404 - 브라우저에서 찾을 수 없습니다.
따라서 대화형 SSR 구성 요소를 프로젝트의 Pages
폴더에 .Client
배치합니다.
로그아웃 시 홈페이지로 리디렉션
사용자가 앱을 LogInOrOut
탐색할 때 구성 요소()는 반환 URL(Layout/LogInOrOut.razor
ReturnUrl
)의 숨겨진 필드를 현재 URL(currentURL
)의 값으로 설정합니다. 사용자가 앱에서 로그아웃하면 ID 공급자가 로그아웃한 페이지로 반환합니다.
사용자가 보안 페이지에서 로그아웃하는 경우 인증 프로세스를 통해서만 다시 전송되도록 로그아웃한 후 동일한 보안 페이지로 다시 반환됩니다. 이 동작은 사용자가 계정을 자주 전환해야 하는 경우에 유용합니다. 그러나 대체 앱 사양은 사용자가 로그아웃 후 앱의 홈페이지 또는 다른 페이지로 반환되도록 요구할 수 있습니다. 다음 예제에서는 앱의 홈페이지를 로그아웃 작업의 반환 URL로 설정하는 방법을 보여 줍니다.
구성 요소에 대한 LogInOrOut
중요한 변경 내용은 다음 예제에서 설명합니다. value
에 대한 숨겨진 필드의 ReturnUrl
홈페이지/
로 설정됩니다. IDisposable 가 더 이상 구현되지 않습니다. 더 NavigationManager 이상 삽입되지 않습니다. 전체 @code
블록이 제거됩니다.
Layout/LogInOrOut.razor
:
@using Microsoft.AspNetCore.Authorization
<div class="nav-item px-3">
<AuthorizeView>
<Authorized>
<form action="authentication/logout" method="post">
<AntiforgeryToken />
<input type="hidden" name="ReturnUrl" value="/" />
<button type="submit" class="nav-link">
<span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
</span> Logout @context.User.Identity?.Name
</button>
</form>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">
<span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span>
Login
</a>
</NotAuthorized>
</AuthorizeView>
</div>
암호화 nonce
nonce는 재생 공격을 완화하기 위해 클라이언트의 세션을 ID 토큰과 연결하는 문자열 값입니다.
인증 개발 및 테스트 중에 nonce 오류가 표시되는 경우 부실 cookie 데이터가 nonce 오류로 이어질 수 있으므로 앱 또는 테스트 사용자가 얼마나 작게 변경했는지에 관계없이 각 테스트 실행에 대해 새 InPrivate/incognito 브라우저 세션을 사용합니다. 자세한 내용은 s 및 사이트 데이터 섹션을 Cookie참조하세요.
새로 고침 토큰을 새 액세스 토큰으로 교환할 때 nonce가 필요하지 않거나 사용되지 않습니다. 샘플 앱에서 (CookieOidcRefresher.cs
)는 CookieOidcRefresher
의도적으로 .로 false
설정합니다OpenIdConnectProtocolValidator.RequireNonce.
Microsoft Entra에 등록되지 않은 앱의 애플리케이션 역할(ME-ID)
이 섹션은 MICROSOFT Entra ID(ME-ID)를 ID 공급자로 사용하지 않는 앱과 관련이 있습니다. ME-ID로 등록된 앱의 경우 MICROSOFT Entra(ME-ID) 섹션에 등록된 앱의 애플리케이션 역할을 참조하세요.
다음의 역할 클레임 유형(TokenValidationParameters.RoleClaimType)을 구성합니다.OpenIdConnectOptions Program.cs
oidcOptions.TokenValidationParameters.RoleClaimType = "{ROLE CLAIM TYPE}";
많은 OIDC ID 공급자의 경우 역할 클레임 유형은 role
. ID 공급자의 설명서에서 올바른 값을 확인합니다.
UserInfo
프로젝트의 클래스를 BlazorWebAppOidc.Client
다음 클래스로 바꿉다.
UserInfo.cs
:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;
namespace BlazorWebAppOidc.Client;
// Add properties to this class and update the server and client
// AuthenticationStateProviders to expose more information about
// the authenticated user to the client.
public sealed class UserInfo
{
public required string UserId { get; init; }
public required string Name { get; init; }
public required string[] Roles { get; init; }
public const string UserIdClaimType = "sub";
public const string NameClaimType = "name";
private const string RoleClaimType = "role";
public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
new()
{
UserId = GetRequiredClaim(principal, UserIdClaimType),
Name = GetRequiredClaim(principal, NameClaimType),
Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
.ToArray(),
};
public ClaimsPrincipal ToClaimsPrincipal() =>
new(new ClaimsIdentity(
Roles.Select(role => new Claim(RoleClaimType, role))
.Concat([
new Claim(UserIdClaimType, UserId),
new Claim(NameClaimType, Name),
]),
authenticationType: nameof(UserInfo),
nameType: NameClaimType,
roleType: RoleClaimType));
private static string GetRequiredClaim(ClaimsPrincipal principal,
string claimType) =>
principal.FindFirst(claimType)?.Value ??
throw new InvalidOperationException(
$"Could not find required '{claimType}' claim.");
}
이 시점에서 Razor 구성 요소는 역할 기반 및 정책 기반 권한 부여를 채택할 수 있습니다. 애플리케이션 역할은 역할당 하나의 클레임인 클레임에 role
나타납니다.
Microsoft Entra에 등록된 앱의 애플리케이션 역할(ME-ID)
이 섹션의 지침을 사용하여 MICROSOFT Entra ID(ME-ID)를 사용하는 앱에 대한 애플리케이션 역할, ME-ID 보안 그룹 및 ME-ID 기본 제공 관리자 역할을 구현합니다.
에서 역할 클레임 유형(TokenValidationParameters.RoleClaimType) OpenIdConnectOptions 을 구성합니다 Program.cs
. 값을 다음으로 roles
설정합니다.
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
ME-ID Premium 계정이 없는 그룹에 역할을 할당할 수는 없지만 사용자에게 역할을 할당하고 표준 Azure 계정을 사용하는 사용자에 대한 역할 클레임을 받을 수 있습니다. 이 섹션의 지침에는 ME-ID Premium 계정이 필요하지 않습니다.
기본 디렉터리로 작업하는 경우 애플리케이션에 앱 역할 추가의 지침에 따라 토큰(ME-ID 설명서) 에서 이를 받아 역할을 구성하고 할당합니다. 기본 디렉터리로 작업하지 않는 경우 Azure Portal에서 앱의 매니페스트를 편집하여 매니페스트 파일 항목에서 appRoles
수동으로 앱의 역할을 설정합니다. 자세한 내용은 역할 클레임 구성(ME-ID 설명서)을 참조하세요.
사용자의 Azure 보안 그룹은 클레임에 groups
도착하며 사용자의 기본 제공 ME ID 관리자 역할 할당은 잘 알려진 ID(wids
) 클레임에 도착합니다. 두 클레임 형식의 값은 GUID입니다. 앱에서 수신하는 경우 이러한 클레임을 사용하여 구성 요소에서 Razor 역할 및 정책 권한 부여를 설정할 수 있습니다.
Azure Portal의 앱 매니페스트에서 특성을 All
.로 설정합니다groupMembershipClaims
. ME-ID가 All
로그인한 사용자의 모든 보안/배포 그룹(groups
클레임) 및 역할(wids
클레임)을 보내는 결과 값입니다. 특성을 설정하려면 다음을 수행 groupMembershipClaims
합니다.
- Azure Portal에서 앱 등록을 엽니다.
- 사이드바에서 관리>매니페스트를 선택합니다.
groupMembershipClaims
특성을 찾습니다.- 값을
All
("groupMembershipClaims": "All"
)로 설정합니다. - 저장 단추를 선택합니다.
UserInfo
프로젝트의 클래스를 BlazorWebAppOidc.Client
다음 클래스로 바꿉다.
UserInfo.cs
:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;
namespace BlazorWebAppOidc.Client;
// Add properties to this class and update the server and client
// AuthenticationStateProviders to expose more information about
// the authenticated user to the client.
public sealed class UserInfo
{
public required string UserId { get; init; }
public required string Name { get; init; }
public required string[] Roles { get; init; }
public required string[] Groups { get; init; }
public required string[] Wids { get; init; }
public const string UserIdClaimType = "sub";
public const string NameClaimType = "name";
private const string RoleClaimType = "roles";
private const string GroupsClaimType = "groups";
private const string WidsClaimType = "wids";
public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
new()
{
UserId = GetRequiredClaim(principal, UserIdClaimType),
Name = GetRequiredClaim(principal, NameClaimType),
Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
.ToArray(),
Groups = principal.FindAll(GroupsClaimType).Select(c => c.Value)
.ToArray(),
Wids = principal.FindAll(WidsClaimType).Select(c => c.Value)
.ToArray(),
};
public ClaimsPrincipal ToClaimsPrincipal() =>
new(new ClaimsIdentity(
Roles.Select(role => new Claim(RoleClaimType, role))
.Concat(Groups.Select(role => new Claim(GroupsClaimType, role)))
.Concat(Wids.Select(role => new Claim(WidsClaimType, role)))
.Concat([
new Claim(UserIdClaimType, UserId),
new Claim(NameClaimType, Name),
]),
authenticationType: nameof(UserInfo),
nameType: NameClaimType,
roleType: RoleClaimType));
private static string GetRequiredClaim(ClaimsPrincipal principal,
string claimType) =>
principal.FindFirst(claimType)?.Value ??
throw new InvalidOperationException(
$"Could not find required '{claimType}' claim.");
}
이 시점에서 Razor 구성 요소는 역할 기반 및 정책 기반 권한 부여를 채택할 수 있습니다.
- 애플리케이션 역할은 역할당 하나의 클레임인 클레임에
roles
나타납니다. - 보안 그룹은 그룹당 하나의 클레임인 클레임에
groups
표시됩니다. 보안 그룹을 만들 때 보안 그룹 GUID가 Azure Portal에 표시되고 개요>그룹>보기를 선택할 Identity>때 나열됩니다. - 기본 제공 ME-ID 관리자 역할은 역할당 하나의 클레임인 클레임에
wids
표시됩니다. 값b79fbf4d-3ef9-4689-8143-76b194e85509
이 있는 클레임은wids
항상 테넌트의 게스트가 아닌 계정에 대해 ME-ID로 전송되며 관리자 역할을 참조하지 않습니다. 역할 및 관리자를 선택한 다음 줄임표(...)를 선택하면 Azure Portal에 관리자 역할 GUID(역할 템플릿 ID) > 가 표시됩니다.나열된 역할에 대한 설명입니다. 역할 템플릿 ID도 Microsoft Entra 기본 제공 역할(Entra 설명서)에 나열됩니다.
문제 해결
로깅
서버 앱은 표준 ASP.NET Core 앱입니다. 서버 앱에서 낮은 로깅 수준을 사용하도록 설정하려면 ASP.NET Core 로깅 지침을 참조하세요.
인증에 Blazor WebAssembly 디버그 또는 추적 로깅을 사용하도록 설정하려면 문서 버전 선택기가 ASP.NET Core Blazor 7.0 이상으로 설정된 ASP.NET Core 로깅의 클라이언트 쪽 인증 로깅 섹션을 참조하세요.
일반 오류
앱 또는 IP(Identity 공급자)의 잘못된 구성
가장 일반적인 오류는 잘못된 구성으로 인해 발생합니다. 다음은 몇 가지 예입니다.
- 시나리오의 요구 사항에 따라, 누락되거나 잘못된 권한, 인스턴스, 테넌트 ID, 테넌트 도메인, 클라이언트 ID 또는 리디렉션 URI 때문에 앱에서 클라이언트를 인증하지 못합니다.
- 잘못된 요청 범위는 클라이언트가 서버 웹 API 엔드포인트에 액세스하지 못하게 합니다.
- 서버 API 권한이 잘못되거나 누락되어 클라이언트가 서버 웹 API 엔드포인트에 액세스할 수 없습니다.
- IP 앱 등록의 리디렉션 URI에 구성된 것과 다른 포트에서 앱을 실행합니다. Microsoft Entra ID 및 개발 테스트 주소에서
localhost
실행되는 앱에는 포트가 필요하지 않지만 앱의 포트 구성 및 앱이 실행되는 포트는 주소localhost
가 아닌 경우 일치해야 합니다.
이 문서의 구성 검사에서는 올바른 구성의 예를 보여 줍니다. 앱 및 IP 구성을 찾는 구성을 신중하게 확인합니다.
구성이 올바르게 표시되면 다음을 수행합니다.
애플리케이션 로그를 분석합니다.
브라우저의 개발자 도구를 사용하여 클라이언트 앱과 IP 또는 서버 앱 간의 네트워크 트래픽을 검사합니다. 종종 정확한 오류 메시지 또는 문제의 원인에 대한 단서가 있는 메시지가 요청을 수행한 후 IP 또는 서버 앱에 의해 클라이언트로 반환됩니다. 개발자 도구 지침은 다음 문서에서 확인할 수 있습니다.
- Google Chrome(Google 설명서)
- Microsoft Edge
- Mozilla Firefox(Mozilla 설명서)
문서 작업 팀은 설명서 피드백 및 문서의 버그에 응답하지만(이 페이지의 피드백 섹션에서 문제 열기) 제품 지원을 제공할 수 없습니다. 앱 문제 해결을 지원하기 위해 몇 가지 퍼블릭 지원 포럼을 사용할 수 있습니다. 다음을 권장합니다.
이전 포럼은 Microsoft에서 소유하거나 제어하지 않습니다.
중요하지 않고 보안이나 기밀이 아니며 재현 가능한 프레임워크 버그 보고서의 경우 ASP.NET Core 제품 단위에서 문제를 여세요. 문제의 원인을 철저하게 조사했으며 자신의 노력과 퍼블릭 지원 포럼에서 커뮤니티의 도움을 받아도 해결할 수 없는 경우에만 제품 단위에서 문제를 열고 그전에는 열지 마세요. 제품 단위는 단순한 구성 오류 또는 타사 서비스와 관련된 사용 사례로 인해 손상된 개별 앱의 문제를 해결할 수 없습니다. 보고서가 본질적으로 민감하거나 기밀이거나 공격자가 악용할 수 있는 제품의 잠재적인 보안 결함을 설명하는 경우 보안 문제 및 버그 보고(
dotnet/aspnetcore
GitHub 리포지토리)를 참조하세요.ME-ID에 대한 권한 없는 클라이언트
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 권한 부여에 실패했습니다. 이러한 요구 사항이 충족되지 않았습니다. DenyAnonymousAuthorizationRequirement: 인증된 사용자가 필요합니다.
ME-ID의 로그인 콜백 오류:
- 오류:
unauthorized_client
- 설명:
AADB2C90058: The provided application is not configured to allow public clients.
오류를 해결하려면:
- Azure Portal에서 앱의 매니페스트에 액세스합니다.
allowPublicClient
특성을null
또는true
로 설정합니다.
- 오류:
Cookie 및 사이트 데이터
Cookie 및 사이트 데이터가 앱을 업데이트할 때에도 유지되어 테스트 및 문제 해결에 방해가 될 수 있습니다. 앱 코드를 변경하거나 공급자를 사용하여 사용자 계정을 변경하거나 공급자 앱 구성을 변경하는 경우 다음을 지우세요.
- 사용자 로그인 cookie
- 앱 cookie
- 캐시되고 저장된 사이트 데이터
남겨진 cookie 및 사이트 데이터로 인해 테스트 및 문제 해결이 지장을 받지 않도록 하려면 다음을 수행합니다.
- 브라우저 구성
- 브라우저에서 브라우저를 닫을 때마다 모든 cookie 및 사이트 데이터를 삭제하도록 구성할 수 있는지 테스트합니다.
- 앱, 테스트 사용자 또는 공급자 구성을 변경할 때 수동으로 또는 IDE를 통해 브라우저를 닫습니다.
- 사용자 지정 명령을 사용하여 Visual Studio에서 InPrivate 또는 Incognito 모드로 브라우저를 엽니다.
- Visual Studio의 실행 단추를 통해 브라우저 선택 대화 상자를 엽니다.
- 추가 단추를 선택합니다.
- 프로그램 필드에서 브라우저의 경로를 제공합니다. 다음 실행 파일 경로는 Windows 10에서 일반적인 설치 위치입니다. 브라우저가 다른 위치에 설치되어 있거나 Windows 10을 사용하지 않는 경우 브라우저 실행 파일의 경로를 제공합니다.
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
- Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- 인수 필드에서 브라우저가 InPrivate 또는 Incognito 모드에서 여는 데 사용하는 명령줄 옵션을 제공합니다. 일부 브라우저에는 앱의 URL이 필요합니다.
- Microsoft Edge: 사용
-inprivate
. - Google Chrome: 자리 표시자가 열 URL인 경우
{URL}
(예https://localhost:5001
: )를 사용합니다--incognito --new-window {URL}
. - Mozilla Firefox: 자리 표시자가 열 URL인 경우(예
https://localhost:5001
: )를 사용합니다.-private -url {URL}
{URL}
- Microsoft Edge: 사용
- 이름 필드에 이름을 입력합니다. 예들 들어
Firefox Auth Testing
입니다. - 확인 단추를 선택합니다.
- 앱 테스트를 반복할 때마다 브라우저 프로필을 선택할 필요가 없도록 하려면 기본값으로 설정 단추를 사용하여 프로필을 기본값으로 설정합니다.
- 앱, 테스트 사용자 또는 공급자 구성을 변경할 때 IDE를 통해 브라우저를 닫습니다.
앱 업그레이드
개발 컴퓨터의 .NET Core SDK 또는 앱 내의 패키지 버전을 업그레이드하거나 앱 내 패키지 버전을 변경한 후 즉시 작동 중인 앱에서 오류가 발생할 수 있습니다. 경우에 따라 중요한 업그레이드를 수행할 때 일관되지 않은 패키지로 인해 응용 프로그램이 중단될 수 있습니다. 이러한 대부분의 문제는 다음 지침에 따라 수정할 수 있습니다.
- 명령 셸에서
dotnet nuget locals all --clear
를 실행하여 로컬 시스템의 NuGet 패키지 캐시를 지웁니다. - 프로젝트의
bin
및obj
폴더를 삭제합니다. - 프로젝트를 복원하고 다시 빌드합니다.
- 앱을 다시 배포하기 전에 서버의 배포 폴더에 있는 모든 파일을 삭제합니다.
참고 항목
앱의 대상 프레임워크와 호환되지 않는 패키지 버전의 사용은 지원되지 않습니다. 패키지에 대한 자세한 내용은 NuGet 갤러리 또는 FuGet 패키지 탐색기를 사용하세요.
서버 앱 실행
웹앱을 테스트하고 문제를 해결할 Blazor 때 서버 프로젝트에서 앱을 실행하고 있는지 확인합니다.
사용자 검사
다음 UserClaims
구성 요소는 앱에서 직접 사용하거나 추가 사용자 지정의 기준으로 사용할 수 있습니다.
UserClaims.razor
:
@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>User Claims</PageTitle>
<h1>User Claims</h1>
@if (claims.Count() > 0)
{
<ul>
@foreach (var claim in claims)
{
<li><b>@claim.Type:</b> @claim.Value</li>
}
</ul>
}
@code {
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState == null)
{
return;
}
var authState = await AuthState;
claims = authState.User.Claims;
}
}
추가 리소스
AzureAD/microsoft-identity-web
GitHub 리포지토리: 샘플 앱 및 관련 Azure 설명서에 대한 링크를 포함하여 ASP.NET Core 앱용 Microsoft Identity Web for Microsoft Entra ID 및 Azure Active Directory B2C 구현에 대한 유용한 지침입니다. 현재 Blazor Web Apps는 Azure 설명서에서 명시적으로 다루지 않지만 ME-ID 및 Azure 호스팅을 위한 웹앱의 Blazor 설정 및 구성은 ASP.NET Core 웹앱과 동일합니다.AuthenticationStateProvider
서비스- Web Apps에서 Blazor 인증 상태 관리
- OIDC를 사용하여 대화형 서버에서 Blazor http 요청 중에 토큰 새로 고침(
dotnet/aspnetcore
#55213)
ASP.NET Core