Azure App Service 인증에서 사용자 ID 사용

이 문서에서는 App Service의 기본 제공 인증 및 권한 부여를 사용할 때 사용자 ID로 작업하는 방법을 보여 줍니다.

앱 코드에서 사용자 클레임에 액세스

모든 언어 프레임워크를 위해 App Service는 들어오는 토큰의 클레임(인증된 최종 사용자 또는 클라이언트 애플리케이션이든 관계없이)을 요청 헤더에 삽입하여 코드에서 사용할 수 있도록 합니다. 외부 요청은 이러한 헤더를 설정하도록 허용되지 않았으므로 App Service에서 설정한 경우에만 표시됩니다. 다음은 이러한 헤더의 예입니다.

헤더 설명
X-MS-CLIENT-PRINCIPAL 사용 가능한 클레임의 Base64로 인코딩된 JSON 표현입니다. 자세한 내용은 클라이언트 보안 주체 헤더 디코딩을 참조하세요.
X-MS-CLIENT-PRINCIPAL-ID ID 공급자가 설정한 호출자에 대한 식별자입니다.
X-MS-CLIENT-PRINCIPAL-NAME ID 공급자가 설정한 호출자의 이름으로, 사람이 읽을 수 있는 이름(예: 이메일 주소, 사용자 계정 이름)입니다.
X-MS-CLIENT-PRINCIPAL-IDP App Service 인증에서 사용하는 ID 공급자의 이름입니다.

공급자 토큰도 유사한 헤더를 통해 노출됩니다. 예를 들어 Microsoft ID 공급자는 X-MS-TOKEN-AAD-ACCESS-TOKENX-MS-TOKEN-AAD-ID-TOKEN도 적절하게 설정합니다.

참고 항목

다른 언어 프레임워크는 이러한 헤더를 소문자 또는 제목 대/소문자와 같은 다양한 형식으로 앱 코드에 표시할 수 있습니다.

모든 언어로 작성된 코드 또는 프레임워크는 이러한 헤더에서 필요한 정보를 가져올 수 있습니다. 클라이언트 보안 주체 헤더 디코딩에서는 이 프로세스를 다룹니다. 일부 프레임워크의 경우 플랫폼은 더 편리할 수 있는 추가 옵션도 제공합니다.

클라이언트 보안 주체 헤더 디코딩

X-MS-CLIENT-PRINCIPAL에는 Base64로 인코딩된 JSON으로 사용 가능한 클레임의 전체 세트가 포함되어 있습니다. 이 클레임은 기본 클레임 매핑 프로세스를 거치므로 일부 클레임의 이름은 토큰을 직접 처리하는 경우 표시되는 이름과 다를 수 있습니다. 디코딩된 페이로드는 다음과 같이 구성됩니다.

{
    "auth_typ": "",
    "claims": [
        {
            "typ": "",
            "val": ""
        }
    ],
    "name_typ": "",
    "role_typ": ""
}
속성 Type Description
auth_typ string App Service 인증에서 사용하는 ID 공급자의 이름입니다.
claims 개체의 배열 사용 가능한 클레임을 나타내는 개체의 배열입니다. 각 개체에는 typval 속성이 포함됩니다.
typ string 클레임의 이름입니다. 이 이름은 기본 클레임 매핑이 적용되었을 수 있으며 토큰에 포함된 해당 클레임과 다를 수 있습니다.
val string 클레임의 값입니다.
name_typ string 이름 클레임 유형으로, 일반적으로 클레임이 정의된 경우 name 클레임에 대한 체계 정보를 제공하는 URI입니다.
role_typ string 역할 클레임 유형으로, 일반적으로 클레임이 정의된 경우 role 클레임에 대한 체계 정보를 제공하는 URI입니다.

이 헤더를 처리하려면 앱이 페이로드를 디코딩하고 claims 배열을 반복하여 원하는 클레임을 찾아야 합니다. 이를 앱의 언어 프레임워크에서 사용하는 표현으로 변환하는 것이 편리할 수 있습니다. 다음은 앱에서 사용할 ClaimsPrincipal 형식을 생성하는 C#으로 작성된 이 프로세스의 예제입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http;

public static class ClaimsPrincipalParser
{
    private class ClientPrincipalClaim
    {
        [JsonPropertyName("typ")]
        public string Type { get; set; }
        [JsonPropertyName("val")]
        public string Value { get; set; }
    }

    private class ClientPrincipal
    {
        [JsonPropertyName("auth_typ")]
        public string IdentityProvider { get; set; }
        [JsonPropertyName("name_typ")]
        public string NameClaimType { get; set; }
        [JsonPropertyName("role_typ")]
        public string RoleClaimType { get; set; }
        [JsonPropertyName("claims")]
        public IEnumerable<ClientPrincipalClaim> Claims { get; set; }
    }

    public static ClaimsPrincipal Parse(HttpRequest req)
    {
        var principal = new ClientPrincipal();

        if (req.Headers.TryGetValue("x-ms-client-principal", out var header))
        {
            var data = header[0];
            var decoded = Convert.FromBase64String(data);
            var json = Encoding.UTF8.GetString(decoded);
            principal = JsonSerializer.Deserialize<ClientPrincipal>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
        }

        /** 
         *  At this point, the code can iterate through `principal.Claims` to
         *  check claims as part of validation. Alternatively, we can convert
         *  it into a standard object with which to perform those checks later
         *  in the request pipeline. That object can also be leveraged for 
         *  associating user data, etc. The rest of this function performs such
         *  a conversion to create a `ClaimsPrincipal` as might be used in 
         *  other .NET code.
         */

        var identity = new ClaimsIdentity(principal.IdentityProvider, principal.NameClaimType, principal.RoleClaimType);
        identity.AddClaims(principal.Claims.Select(c => new Claim(c.Type, c.Value)));
        
        return new ClaimsPrincipal(identity);
    }
}

프레임워크별 대안

ASP.NET 4.6 응용 프로그램의 경우 App Service는 인증된 사용자의 클레임을 사용하여 ClaimsPrincipal.Current를 채우기 때문에 [Authorize] 특성을 비롯한 표준 .NET 코드 패턴을 따를 수 있습니다. 마찬가지로 PHP 앱의 경우, App Service는 _SERVER['REMOTE_USER'] 변수를 채웁니다. Java 앱의 경우 Tomcat 서블릿에서 클레임에 액세스할 수 있습니다.

Azure Functions의 경우, .NET 코드를 위해 ClaimsPrincipal.Current가 채워지지 않지만, 요청 헤더에서 사용자 클레임을 찾거나 요청 컨텍스트에서 또는 바인딩 매개 변수를 통해 ClaimsPrincipal 개체를 가져올 수 있습니다. 자세한 내용은 Azure Functions에서 클라이언트 ID 사용을 참조하세요.

.NET Core의 경우 Microsoft.Identity.Web은 App Service 인증으로 현재 사용자 채우기를 지원합니다. 자세한 내용은 Microsoft.Identity.Web wiki를 참조하거나 Microsoft Graph에 액세스하는 웹앱에 대해 이 자습서에서 시연된 내용을 참조하세요.

참고 항목

클레임 매핑이 작동하려면 토큰 저장소를 사용하도록 설정해야 합니다.

API를 사용하여 사용자 클레임에 액세스

앱에서 토큰 저장소를 사용하도록 설정한 경우 /.auth/me를 호출하여 인증된 사용자에 관한 다른 세부 정보를 가져올 수도 있습니다.

다음 단계