조건부 액세스 인증 컨텍스트에 대한 개발자 가이드

조건부 액세스는 모든 앱(이전 또는 신규, 프라이빗 또는 퍼블릭, 온-프레미스 또는 다중 클라우드)에 대한 액세스 정책을 대상으로 지정할 수 있는 제로 트러스트 컨트롤 플레인입니다. 조건부 액세스 인증 컨텍스트를 사용하여 해당 앱 내에 다른 정책을 적용할 수 있습니다.

조건부 액세스 인증 컨텍스트(인증 컨텍스트)를 사용하면 앱 수준뿐만 아니라 중요한 데이터 및 작업에 세분화된 정책을 적용할 수 있습니다. 사용자 마찰을 최소화하고 사용자의 생산성과 리소스를 더욱 안전하게 유지하면서 최소 권한의 액세스에 대해 제로 트러스트 정책을 구체화할 수 있습니다. 현재는 회사에서 개발한 인증에 OpenId 커넥트 사용하는 애플리케이션에서 고부가가치 트랜잭션 또는 직원 개인 데이터 보기와 같은 중요한 리소스를 보호하는 데 사용됩니다.

애플리케이션 및 서비스 내에서 단계별 인증을 트리거하려면 Microsoft Entra 조건부 액세스 엔진의 인증 컨텍스트 기능을 사용합니다. 개발자는 애플리케이션 내에서 최종 사용자의 MFA와 같이 선택적으로 더 강력한 고급 인증을 요구하는 기능을 사용할 수 있습니다. 이 기능은 개발자가 애플리케이션의 대부분에 대해 더 원활한 사용자 환경을 빌드하는 동시에 더 강력한 인증 제어를 바탕으로 더 안전한 운영 및 데이터에 액세스할 수 있도록 지원합니다.

문제 설명

IT 관리자와 규제 기관은 종종 사용자에게 인증의 추가 요인을 너무 자주 묻는 것과 중요한 데이터 및 작업이 포함된 애플리케이션 및 서비스에 대한 적절한 보안 및 정책 준수를 달성하는 것 사이에서 균형을 맞추는 데 어려움을 겪습니다. 대부분의 데이터 및 작업에 액세스할 때 사용자의 생산성에 영향을 미치는 강력한 정책을 선택하거나, 아니면 중요한 리소스에 충분히 강력하지 않은 정책을 선택할 수 있습니다.

그런데 대부분의 사용자 및 운영에 대해서는 상대적으로 보안 수준이 낮고 프롬프트 횟수가 적으면서도, 사용자가 더 민감한 부분에 액세스할 때는 조건부로 보안 요구 사항을 강화할 수 있도록 앱이 두 가지를 모두 결합할 수 있다면 어떨까요?

일반적인 시나리오

예를 들어 사용자가 다단계 인증을 사용하여 SharePoint에 로그인할 수 있지만 중요한 문서가 포함된 SharePoint의 사이트 모음에 액세스하려면 규격 디바이스가 필요하고 신뢰할 수 있는 IP 범위에서만 액세스할 수 있습니다.

필수 조건

먼저 인증 및 권한 부여를 위해 OpenID Connect/ OAuth 2.0 프로토콜을 사용하여 앱을 Microsoft ID 플랫폼과 통합해야 합니다. Microsoft ID 플랫폼 인증 라이브러리를 사용하여 Microsoft Entra ID로 애플리케이션을 통합하고 보호하는 것이 좋습니다. Microsoft ID 플랫폼 설명서는 앱을 Microsoft ID 플랫폼과 통합하는 방법에 대한 학습을 시작하는 데 적합합니다. 조건부 액세스 인증 컨텍스트 기능 지원은 업계 표준 OpenID Connect 프로토콜에서 제공하는 프로토콜 확장을 기반으로 합니다. 개발자는 클레임 요청 매개 변수와 함께 조건부 액세스 인증 컨텍스트 참조을 사용하여 앱에 정책을 트리거하고 충족하는 방법을 제공합니다.

두 번째, 조건부 액세스에는 Microsoft Entra ID P1 라이선스가 필요합니다. 라이선스에 대한 자세한 내용은 Microsoft Entra 가격 책정 페이지에서 확인할 수 있습니다.

세 번째로, 현재 사용자가 로그인하는 애플리케이션에서만 사용할 수 있습니다. 자체로 인증하는 애플리케이션은 지원되지 않습니다. 인증 흐름 및 애플리케이션 시나리오 가이드를 사용하여 Microsoft ID 플랫폼에서 지원되는 인증 앱 유형 및 흐름에 대해 알아보세요.

통합 단계

지원되는 인증 프로토콜을 사용하여 애플리케이션을 통합하고 조건부 액세스 기능을 사용할 수 있는 Microsoft Entra 테넌트에 등록한 후에는 사용자가 로그인하는 애플리케이션에서 이 기능을 통합하는 프로세스를 시작할 수 있습니다.

참고 항목

이 기능에 대한 자세한 연습은 앱에서 단계별 인증을 위한 조건부 액세스 인증 컨텍스트 사용의 녹화 세션에서 확인할 수 있습니다.

먼저 테넌트에서 사용 가능한 인증 컨텍스트를 선언하고 만듭니다. 자세한 내용은 인증 컨텍스트 구성을 참조하세요.

C1-C99는 테넌트에서 인증 컨텍스트 ID사용할 수 있습니다. 인증 컨텍스트의 예는 다음과 같습니다.

  • C1 - 강력한 인증 필요
  • C2 - 정책 준수 디바이스 필요
  • C3 – 신뢰할 수 있는 위치 필요

조건부 액세스 인증 컨텍스트를 사용하도록 조건부 액세스 정책을 만들거나 수정합니다. 정책 예제는 다음과 같습니다.

  • 이 웹 애플리케이션에 로그인하는 모든 사용자는 인증 컨텍스트 ID C1에 대해 2FA를 성공적으로 완료해야 합니다.
  • 이 웹 애플리케이션에 로그인하는 모든 사용자는 인증 컨텍스트 ID C3에 대해 2FA를 성공적으로 완료하고 특정 IP 주소 범위에서 웹앱에 액세스해야 합니다.

참고 항목

조건부 액세스 인증 컨텍스트 값은 애플리케이션에서 별도로 선언 및 유지 관리됩니다. 애플리케이션이 인증 컨텍스트 ID에 대해 하드 종속성을 사용하지 않는 것이 좋습니다. 조건부 액세스 정책은 정책 적용에 사용할 수 있는 리소스를 더 잘 이해할 수 있도록 일반적으로 IT 관리자가 작성합니다. 예를 들어, Microsoft Entra 테넌트의 경우 IT 관리자는 MFA에 대해 2FA를 사용하는 테넌트의 사용자 수에 대한 정보를 보유하고 있으므로 2FA가 요구되는 조건부 액세스 정책의 범위를 이러한 장착된 사용자로 제한할 수 있습니다. 마찬가지로 애플리케이션이 여러 테넌트에서 사용되는 경우 사용 중인 인증 컨텍스트 ID가 다를 수 있으며 경우에 따라 전혀 사용할 수 없습니다.

두 번째로 조건부 액세스 인증 컨텍스트를 사용하려는 애플리케이션 개발자는 먼저 애플리케이션 관리자 또는 IT 관리자에게 잠재적으로 중요한 작업을 인증 컨텍스트 ID에 매핑할 수 있는 수단을 제공하는 것이 좋습니다. 대략적인 단계는 다음과 같습니다.

  1. 인증 컨텍스트 ID에 대해 매핑할 수 있는 코드의 작업을 파악합니다.
  2. IT 관리자가 사용 가능한 인증 컨텍스트 ID에 중요한 작업을 매핑하는 데 사용할 수 있는 앱(또는 이와 동등한 기능)의 관리 포털에 화면을 빌드합니다.
  3. 작업을 수행하는 방법에 대한 예제를 보려면 코드 샘플에서 조건부 액세스 인증 컨텍스트를 사용한 단계별 인증 수행을 참조하세요.

이러한 단계는 코드 베이스에서 수행해야 하는 변경 내용입니다. 단계는 대체로 다음과 같습니다.

  • 사용 가능한 모든 인증 컨텍스트를 나열하는 MS Graph를 쿼리합니다.
  • IT 관리자가 중요한/높은 권한을 가진 작업을 선택하고 조건부 정책 정책을 사용하여 사용 가능한 인증 컨텍스트에 할당할 수 있도록 허용합니다.
  • 이 매핑 정보를 데이터베이스/로컬 저장소에 저장합니다.

인증 컨텍스트를 만들기 위한 설정 흐름

세 번째로 이 예제에서는 웹 API라고 가정하는 사용자의 애플리케이션은 저장된 매핑에 대한 호출을 평가하고, 그에 따라 해당 클라이언트 앱에 대한 클레임 문제를 발생시켜야 합니다. 이 작업을 준비하려면 다음 단계를 수행합니다.

  1. 중요하고 인증 컨텍스트 작업으로 보호되는 경우 앞에서 저장한 인증 컨텍스트 ID 매핑에 대해 acrs 클레임의 값을 평가하고 다음 코드 조각에 제공된 대로 클레임 챌린지를 발생합니다.

  2. 다음 다이어그램은 사용자, 클라이언트 앱 및 웹 API 간의 상호 작용을 보여 줍니다.

    사용자, 웹앱, API 및 Microsoft Entra ID의 상호 작용을 보여 주는 다이어그램

    다음 코드 조각은 코드 샘플 조건부 액세스 인증 컨텍스트를 사용한 단계별 인증 수행에서 가져온 것입니다. API의 첫 번째 메서드 CheckForRequiredAuthContext()

    • 호출 중인 애플리케이션의 작업에 단계별 인증이 필요한지 확인합니다. 해당 데이터베이스에서 이 메서드에 대한 저장된 매핑을 확인하여 수행합니다.
    • 이 작업에 실제로 상승된 인증 컨텍스트가 필요한 경우 일치하는 기존 인증 컨텍스트 ID에 대한 acrs 클레임을 확인합니다.
    • 일치하는 인증 컨텍스트 ID가 없다면 클레임 문제를 발생시킵니다.
    public void CheckForRequiredAuthContext(string method)
    {
        string authType = _commonDBContext.AuthContext.FirstOrDefault(x => x.Operation == method
                    && x.TenantId == _configuration["AzureAD:TenantId"])?.AuthContextId;
    
        if (!string.IsNullOrEmpty(authType))
        {
            HttpContext context = this.HttpContext;
            string authenticationContextClassReferencesClaim = "acrs";
    
            if (context == null || context.User == null || context.User.Claims == null
                || !context.User.Claims.Any())
            {
                throw new ArgumentNullException("No Usercontext is available to pick claims from");
            }
    
            Claim acrsClaim = context.User.FindAll(authenticationContextClassReferencesClaim).FirstOrDefault(x
                => x.Value == authType);
    
            if (acrsClaim == null || acrsClaim.Value != authType)
            {
                if (IsClientCapableofClaimsChallenge(context))
                {
                    string clientId = _configuration.GetSection("AzureAd").GetSection("ClientId").Value;
                    var base64str = Convert.ToBase64String(Encoding.UTF8.GetBytes("{\"access_token\":{\"acrs\":{\"essential\":true,\"value\":\"" + authType + "\"}}}"));
    
                    context.Response.Headers.Append("WWW-Authenticate", $"Bearer realm=\"\", authorization_uri=\"https://login.microsoftonline.com/common/oauth2/authorize\", client_id=\"" + clientId + "\", error=\"insufficient_claims\", claims=\"" + base64str + "\", cc_type=\"authcontext\"");
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    string message = string.Format(CultureInfo.InvariantCulture, "The presented access tokens had insufficient claims. Please request for claims requested in the WWW-Authentication header and try again.");
                    context.Response.WriteAsync(message);
                    context.Response.CompleteAsync();
                    throw new UnauthorizedAccessException(message);
                }
                else
                {
                    throw new UnauthorizedAccessException("The caller does not meet the authentication  bar to carry our this operation. The service cannot allow this operation");
                }
            }
        }
    }
    

    참고 항목

    클레임 문제의 형식은 Microsoft ID 플랫폼의 클레임 문제 문서에 설명되어 있습니다.

  3. 클라이언트 애플리케이션에서 클레임 문제를 가로채고 추가 정책 평가를 위해 사용자를 다시 Microsoft Entra ID로 리디렉션합니다. 다음 코드 조각은 코드 샘플 조건부 액세스 인증 컨텍스트를 사용한 단계별 인증 수행에서 가져온 것입니다.

    internal static string ExtractHeaderValues(WebApiMsalUiRequiredException response)
    {
        if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized && response.Headers.WwwAuthenticate.Any())
        {
            AuthenticationHeaderValue bearer = response.Headers.WwwAuthenticate.First(v => v.Scheme == "Bearer");
            IEnumerable<string> parameters = bearer.Parameter.Split(',').Select(v => v.Trim()).ToList();
            var errorValue = GetParameterValue(parameters, "error");
    
            try
            {
                // read the header and checks if it contains error with insufficient_claims value.
                if (null != errorValue && "insufficient_claims" == errorValue)
                {
                    var claimChallengeParameter = GetParameterValue(parameters, "claims");
                    if (null != claimChallengeParameter)
                    {
                        var claimChallenge = ConvertBase64String(claimChallengeParameter);
    
                        return claimChallenge;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        return null;
    }
    

    웹 API에 대한 호출에서 예외를 처리합니다. 클레임 문제가 표시되는 경우 추가 처리를 위해 사용자를 Microsoft Entra ID로 다시 리디렉션합니다.

    try
    {
        // Call the API
        await _todoListService.AddAsync(todo);
    }
    catch (WebApiMsalUiRequiredException hex)
    {
        // Challenges the user if exception is thrown from Web API.
        try
        {
            var claimChallenge =ExtractHeaderValues(hex);
            _consentHandler.ChallengeUser(new string[] { "user.read" }, claimChallenge);
    
            return new EmptyResult();
        }
        catch (Exception ex)
        {
            _consentHandler.HandleException(ex);
        }
    
        Console.WriteLine(hex.Message);
    }
    return RedirectToAction("Index");
    
  4. (선택 사항) 클라이언트 기능을 선언합니다. 클라이언트 기능을 통해 웹 API와 같은 RP(리소스 공급자)는 호출하는 클라이언트 애플리케이션이 클레임 문제를 이해하고 그에 따라 응답을 사용자 지정할 수 있는지 여부를 감지합니다. 이 기능은 일부 API 클라이언트가 클레임 문제를 처리할 수 없고 일부 오래된 API가 여전히 다른 응답을 기대하는 경우에 유용할 수 있습니다. 자세한 내용은 클라이언트 기능 섹션을 참조하세요.

제한 사항 및 권장 사항

앱에서 인증 컨텍스트 값을 하드 코딩하지 마세요. 앱은 MS Graph 호출을 사용하여 인증 컨텍스트를 읽고 적용해야 합니다. 이 방법은 다중 테넌트 애플리케이션에 매우 중요합니다. 인증 컨텍스트 값은 Microsoft Entra 테넌트마다 다르며 Microsoft Entra ID Free 버전에서는 사용할 수 없습니다. 앱이 코드에서 인증 컨텍스트를 쿼리, 설정 및 사용하는 방법에 대한 자세한 내용은 코드 샘플 조건부 액세스 인증 컨텍스트를 사용한 단계별 인증 수행에서 앱이 코드에서 인증 컨텍스트를 쿼리, 설정 및 사용하는 방법을 참조하세요.

앱 자체가 조건부 액세스 정책의 대상이 되는 인증 컨텍스트를 사용하지 마세요. 이 기능은 애플리케이션의 일부에서 사용자가 더 높은 수준의 인증을 충족해야 하는 경우에 가장 잘 작동합니다.

샘플 코드

조건부 액세스 예상 동작의 인증 컨텍스트[ACR]

요청의 명시적 인증 컨텍스트 만족도

클라이언트는 요청 본문의 클레임을 통해 ACRS(인증 컨텍스트)를 사용하여 토큰을 명시적으로 요청할 수 있습니다. ACRS가 요청된 경우 조건부 액세스는 모든 챌린지가 완료된 경우 요청된 ACRS를 사용하여 토큰을 발급할 수 있도록 허용합니다.

테넌트의 조건부 액세스로 인증 컨텍스트가 보호되지 않는 경우 예상되는 동작

조건부 액세스는 ACRS 값에 할당된 모든 조건부 액세스 정책이 충족된 경우 토큰의 클레임에서 ACRS를 발급할 수 있습니다. ACRS 값에 조건부 액세스 정책이 할당되지 않은 경우 모든 정책 요구 사항이 충족되었기 때문에 클레임이 계속 발급될 수 있습니다.

ACRS가 명시적으로 요청될 때 예상되는 동작에 대한 요약 테이블

ACRS가 요청됨 정책이 적용됨 컨트롤이 충족됨 ACRS가 클레임에 추가됨
없음
없음 없음
ACRS로 구성된 정책이 없음

기회 평가에 의한 암시적 인증 컨텍스트 만족도

리소스 공급자는 선택적 ‘acrs’ 클레임에 옵트인할 수 있습니다. 조건부 액세스는 Microsoft Entra ID에 대한 새 토큰을 획득하기 위한 왕복을 방지하기 위해 토큰 클레임에 ACRS를 기회적으로 추가하려고 시도합니다. 이 평가에서 조건부 액세스는 인증 컨텍스트 챌린지를 보호하는 정책이 이미 충족된 경우 검사 토큰 클레임에 ACRS를 추가합니다.

참고 항목

각 토큰 유형(ID 토큰, 액세스 토큰)은 개별적으로 옵트인해야 합니다.

리소스 공급자가 선택적 ‘acrs’ 클레임을 옵트인하지 않는 경우 토큰에서 ACRS를 가져오는 유일한 방법은 토큰 요청에서 명시적으로 요청하는 것입니다. 이 방법은 기회 평가의 이점을 얻지 못하므로 필요한 ACRS가 토큰 클레임에서 누락될 때마다 리소스 공급자는 클라이언트에 클레임에 포함된 새 토큰을 획득하도록 요청합니다.

암시적 ACRS 기회 평가를 위한 인증 컨텍스트 및 세션 컨트롤이 있는 예상 동작

간격별 로그인 빈도

조건부 액세스는 모든 현재 인증 요소 인증 인스턴트가 로그인 빈도 간격 내에 있는 경우 기회 ACRS 평가에 대해 "간격별 로그인 빈도"를 충족하는 것으로 간주합니다. 첫 번째 요소 인증 인스턴트가 부실하거나 두 번째 요소(MFA)가 있고 인증 인스턴트가 부실한 경우 간격별 로그인 빈도가 충족되지 않으며 토큰에서 ACRS가 선택적으로 발급되지 않습니다.

CAS(Cloud App Security)

조건부 액세스는 해당 요청 중에 CAS 세션이 설정된 경우 CAS 세션 컨트롤이 기회 ACRS 평가를 만족하는 것으로 간주합니다. 예를 들어 요청이 들어오고 조건부 액세스 정책이 CAS 세션을 적용하는 경우 그리고 CAS 세션도 필요한 조건부 액세스 정책이 있는 경우, CAS 세션이 적용되므로 이는 기회 평가에 대한 CAS 세션 컨트롤을 충족합니다.

테넌트가 인증 컨텍스트를 보호하는 조건부 액세스 정책을 포함하는 경우 예상되는 동작

아래 표에서는 기회 평가를 통해 ACRS가 토큰의 클레임에 추가되는 모든 코너 사례를 보여 줍니다.

정책 A: “c1” acrs를 요청할 경우 사용자 “Ariel”을 제외한 모든 사용자의 MFA가 필요합니다. 정책 B: “c2” 또는 “c3” acrs를 요청할 경우 사용자 “Jay”를 제외한 모든 사용자를 차단합니다.

Flow ACRS가 요청됨 정책이 적용됨 컨트롤이 충족됨 ACRS가 클레임에 추가됨
Ariel이 액세스 토큰 요청 “c1” 없음 “c1”의 경우 예입니다. “c2” 및 “c3”의 경우 아니요 “c1”(요청됨)
Ariel이 액세스 토큰 요청 “c2” 정책 B 정책 B에 의해 차단됨 없음
Ariel이 액세스 토큰 요청 없음 없음 “c1”의 경우 예입니다. “c2” 및 “c3”의 경우 아니요 “c1”(정책 A에서 기회적으로 추가됨)
Jay가 액세스 토큰 요청(MFA 제외) “c1” 정책 A 아니요 없음
Jay가 액세스 토큰 요청(MFA 포함) “c1” 정책 A “c1”(요청됨), “c2”(정책 B에서 선택적으로 추가됨), “c3”(정책 B에서 선택적으로 추가됨)
Jay가 액세스 토큰 요청(MFA 제외) “c2” 없음 “c2” 및 “c3”의 경우 예입니다. “c1”의 경우 아니요 “c2”(요청됨), “c3”(정책 B에서 기회적으로 추가됨)
Jay가 액세스 토큰 요청(MFA 포함) “c2” 없음 “c1”, “c2” 및 “c3”의 경우 예 “c1”(A에서 최선의 노력), “c2”(요청됨), “c3”(정책 B에서 기회적으로 추가됨)
Jay가 액세스 토큰 요청(MFA 포함) 없음 없음 “c1”, “c2” 및 “c3”의 경우 예 “c1”, “c2”, “c3” 모두 선택적으로 추가됨
Jay가 액세스 토큰 요청(MFA 제외) 없음 없음 “c2” 및 “c3”의 경우 예입니다. “c1”의 경우 아니요 “c2”, “c3” 모두 선택적으로 추가됨

다음 단계