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

적용 대상: 이 내용은 워크포스 테넌트에 적용됩니다. 흰색 체크 표시가 있는 녹색 원으로 표시됩니다.이 내용은 외부 테넌트에 적용됩니다. 흰색 체크 표시가 있는 녹색 원으로 표시됩니다. 외부 테넌트(자세한 정보)

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

조건부 액세스 인증 컨텍스트(인증 컨텍스트)를 사용하면 앱 수준뿐만 아니라 중요한 데이터 및 작업에 세분화된 정책을 적용할 수 있습니다. 사용자 불편을 최소화하고 사용자의 생산성을 높이고 리소스를 더욱 안전하게 유지하면서 최소 권한 액세스를 위한 제로 트러스트 정책을 구체화할 수 있습니다. 오늘날 OpenId Connect를 인증에 사용하는 회사에서 개발한 애플리케이션은 고가치 거래나 직원 개인 데이터 보기와 같은 민감한 리소스를 보호하는 데 사용됩니다.

애플리케이션 및 서비스 내에서 추가 인증을 트리거하려면 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 가격 책정 페이지에서 확인할 수 있습니다.

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

통합 단계

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

참고

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

먼저 테넌트에서 인증 컨텍스트를 선언하고 사용할 수 있게 합니다. 자세한 내용은 인증 컨텍스트 구성을 참조하세요.

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

  • C1 - 강력한 인증 요구
  • C2 – 규정을 준수하는 장치 필요
  • C3 – 신뢰할 수 있는 위치 요구

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

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

참고

조건부 액세스 인증 컨텍스트 값은 애플리케이션과 별도로 선언 및 유지 관리됩니다. 애플리케이션이 인증 컨텍스트 ID에 하드 종속성을 갖는 것은 바람직하지 않습니다. IT 관리자는 일반적으로 사용 가능한 리소스를 더 잘 이해하므로 조건부 액세스 정책을 만듭니다. 마찬가지로 애플리케이션이 여러 테넌트에서 사용되는 경우 사용 중인 인증 컨텍스트 ID가 다를 수 있으며 경우에 따라 전혀 제공되지 않을 수 있습니다.

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

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

다음은 코드 베이스에 필요한 변경 사항을 적용하기 위해 수행해야 하는 단계입니다. 단계는 대체로 다음과 같습니다.

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

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

세 번째로: 이 예제에서는 웹 API라고 가정하는 애플리케이션이 저장된 매핑에 따라 호출을 평가하고, 그에 따라 해당 클라이언트 앱에 클레임 챌린지를 제기해야 합니다. 이 작업을 준비하려면 다음 단계를 수행해야 합니다.

  1. 민감하고 인증 컨텍스트로 보호되는 작업에서, 이전에 저장된 인증 컨텍스트 ID 매핑과 비교하여 acrs 클레임의 값을 평가하고 다음 코드 조각에 제공된 대로 클레임 챌린지를 발생시킵니다.

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

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

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

    • 호출 중인 애플리케이션의 작업에 추가 인증이 필요한지 확인합니다. 해당 데이터베이스에서 이 메서드에 대한 저장된 매핑을 확인하여 수행합니다.
    • 이 작업에 실제로 상승된 인증 컨텍스트가 필요한 경우 기존의 일치하는 인증 컨텍스트 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. (선택 사항) 클라이언트 지원 여부를 선언합니다. 클라이언트 기능은 Web API와 같은 RP(리소스 공급자)가 클라이언트 애플리케이션이 클레임 챌린지를 이해하고 그에 따라 응답을 사용자 지정할 수 있는지 감지하는 데 도움이 됩니다. 이 기능은 일부 API 클라이언트가 클레임 챌린지를 처리할 수 없고 일부 오래된 API 클라이언트가 여전히 다른 응답을 기대하는 경우에 유용할 수 있습니다. 자세한 내용은 클라이언트 기능 섹션을 참조하세요.

제한 사항 및 권장 사항

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

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

샘플 코드

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

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

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

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

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

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

ACRS가 요청됨 정책이 적용됨 제어 조건 충족 ACRS가 클레임에 추가됨
예 아니요 예 예
예 예 아니요 아니요
예 예 예 예
예 구성된 ACRS 정책이 없음 예 예

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

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

참고

각 토큰 유형은 개별적으로 선택하여 활성화해야 합니다 (ID 토큰, 액세스 토큰).

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

암시적 ACRS 기회 평가를 위한 인증 컨텍스트 및 세션 제어에서의 예상 동작

간격별 로그인 빈도

조건부 액세스는 현재의 모든 인증 요소 인증 시점이 로그인 빈도 간격 내에 있는 경우 기회적 ACRS 평가에 대해 "간격별 로그인 빈도"를 충족하는 것으로 간주합니다. 인증 요소 중 하나가 부실한 경우 간격별로 로그인 빈도가 충족되지 않으며 토큰에서 ACRS가 기회적으로 발급되지 않습니다.

CAS(Cloud App Security)

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

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

아래 표에서는 기회적 평가를 통해 ACRS가 토큰의 클레임에 추가되는 모든 예외 경우를 보여 줍니다.

정책 A: “c1” acrs를 요청할 때 사용자 “Ariel”을 제외한 모든 사용자에게 MFA를 요구합니다. 정책 B: 사용자가 “c2” 또는 “c3” acrs를 요청하면 사용자 “Jay”를 제외한 모든 사용자를 차단합니다.

흐름 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” 모두 기회가 되는 대로 추가됨

다음 단계