다음을 통해 공유


인증 및 권한 부여

참고 항목

이 전자책은 2017년 봄에 게시되었으며 그 이후로 업데이트되지 않았습니다. 이 책에는 귀중한 기본 많이 있지만 일부 자료는 구식입니다.

인증은 사용자로부터 이름 및 암호와 같은 식별 자격 증명을 가져오고 해당 자격 증명의 유효성을 검사하는 프로세스입니다. 자격 증명이 유효한 경우 자격 증명을 제출한 엔터티는 인증된 ID로 간주됩니다. ID가 인증되면 권한 부여 프로세스는 해당 ID가 지정된 리소스에 액세스할 수 있는지 여부를 결정합니다.

ASP.NET MVC 웹 애플리케이션과 통신하는 앱에 Xamarin.Forms 인증 및 권한 부여를 통합하는 방법에는 ASP.NET 핵심 ID, Microsoft, Google, Facebook 또는 Twitter와 같은 외부 인증 공급자 및 인증 미들웨어를 사용하는 방법이 많이 있습니다. eShopOnContainers 모바일 앱은 IdentityServer 4를 사용하는 컨테이너화된 ID 마이크로 서비스를 사용하여 인증 및 권한 부여를 수행합니다. 모바일 앱은 사용자를 인증하거나 리소스에 액세스하기 위해 IdentityServer에서 보안 토큰을 요청합니다. IdentityServer가 사용자를 대신하여 토큰을 발급하려면 사용자가 IdentityServer에 로그인해야 합니다. 그러나 IdentityServer는 인증을 위해 사용자 인터페이스 또는 데이터베이스를 제공하지 않습니다. 따라서 eShopOnContainers 참조 애플리케이션에서 ASP.NET Core ID가 이러한 목적으로 사용됩니다.

인증

애플리케이션이 현재 사용자의 ID를 알아야 하는 경우 인증이 필요합니다. 사용자를 식별하는 ASP.NET Core의 기본 메커니즘은 개발자가 구성한 데이터 저장소에 사용자 정보를 저장하는 ASP.NET Core ID 멤버 자격 시스템입니다. 일반적으로 이 데이터 저장소는 EntityFramework 저장소이지만 사용자 지정 저장소 또는 타사 패키지를 사용하여 Azure Storage, Azure Cosmos DB 또는 기타 위치에 ID 정보를 저장할 수 있습니다.

로컬 사용자 데이터 저장소를 사용하고 쿠키를 통해 요청 간에 ID 정보를 유지하는 인증 시나리오의 경우(ASP.NET MVC 웹 애플리케이션에서 일반적인 것처럼) ASP.NET Core Identity는 적합한 솔루션입니다. 그러나 쿠키는 데이터를 유지하고 전송하는 자연스러운 방법이 아닐 때도 있습니다. 예를 들어 모바일 앱에서 액세스하는 RESTful 엔드포인트를 노출하는 ASP.NET Core 웹 애플리케이션은 일반적으로 이 시나리오에서 쿠키를 사용할 수 없으므로 전달자 토큰 인증을 사용해야 합니다. 그러나 전달자 토큰을 쉽게 검색하고 모바일 앱에서 만든 웹 요청의 권한 부여 헤더에 포함할 수 있습니다.

IdentityServer 4를 사용하여 전달자 토큰 발급

IdentityServer 4는 ASP.NET Core용 오픈 소스 OpenID 커넥트 및 OAuth 2.0 프레임워크로, 로컬 ASP.NET Core ID 사용자에 대한 보안 토큰 발급을 비롯한 많은 인증 및 권한 부여 시나리오에 사용할 수 있습니다.

참고 항목

OpenID Connect와 OAuth 2.0은 매우 비슷하지만 책임이 다릅니다.

OpenID Connect는 OAuth 2.0 프로토콜을 기반으로 하는 인증 계층입니다. OAuth 2는 애플리케이션이 보안 토큰 서비스에서 액세스 토큰을 요청하고 이를 사용하여 API와 통신할 수 있도록 하는 프로토콜입니다. 이 위임은 인증 및 권한 부여를 중앙 집중화할 수 있으므로 클라이언트 애플리케이션과 API의 복잡성을 줄입니다.

OpenID 커넥트 OAuth 2.0의 조합은 인증 및 API 액세스의 두 가지 기본적인 보안 문제를 결합하며 IdentityServer 4는 이러한 프로토콜의 구현입니다.

eShopOnContainers 참조 애플리케이션과 같은 직접 클라이언트-마이크로 서비스 통신을 사용하는 애플리케이션에서는 그림 9-1과 같이 STS(보안 토큰 서비스)로 작동하는 전용 인증 마이크로 서비스를 사용하여 사용자를 인증할 수 있습니다. 직접 클라이언트-마이크로 서비스 통신에 대한 자세한 내용은 클라이언트와 마이크로 서비스 간의 통신을 참조 하세요.

Authentication by a dedicated authentication microservice

그림 9-1: 전용 인증 마이크로 서비스에 의한 인증

eShopOnContainers 모바일 앱은 IDENTITyServer 4를 사용하여 인증을 수행하고 API에 대한 액세스 제어를 수행하는 ID 마이크로 서비스와 통신합니다. 따라서 모바일 앱은 사용자를 인증하거나 리소스에 액세스하기 위해 IdentityServer에서 토큰을 요청합니다.

  • IdentityServer를 사용하여 사용자를 인증하는 작업은 인증 프로세스의 결과를 나타내는 ID 토큰을 요청하는 모바일 앱에 의해 수행됩니다. 최소한 사용자에 대한 식별자 및 사용자가 인증하는 방법과 시기에 대한 정보가 포함됩니다. 추가 ID 데이터를 포함할 수도 있습니다.
  • IdentityServer를 사용하여 리소스에 액세스하는 작업은 API 리소스에 대한 액세스를 허용하는 액세스 토큰을 요청하는 모바일 앱에 의해 수행됩니다. 클라이언트는 액세스 토큰을 요청하여 이를 API에 전달합니다. 액세스 토큰에는 클라이언트 및 사용자(있는 경우)에 대한 정보가 포함됩니다. 그런 다음, API는 해당 정보를 사용하여 데이터에 대한 액세스 권한을 부여합니다.

참고 항목

토큰을 요청하려면 먼저 클라이언트를 IdentityServer에 등록해야 합니다.

웹 애플리케이션에 IdentityServer 추가

ASP.NET Core 웹 애플리케이션이 IdentityServer 4를 사용하려면 웹 애플리케이션의 Visual Studio 솔루션에 추가해야 합니다. 자세한 내용은 IdentityServer 설명서의 개요를 참조하세요.

IdentityServer가 웹 애플리케이션의 Visual Studio 솔루션에 포함되면 OpenID 커넥트 및 OAuth 2.0 엔드포인트에 대한 요청을 처리할 수 있도록 웹 애플리케이션의 HTTP 요청 처리 파이프라인에 추가되어야 합니다. 이는 다음 코드 예제에서 설명한 것처럼 웹 애플리케이션의 Startup 클래스에 있는 Configure 메서드에서 수행됩니다.

public void Configure(  
    IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)  
{  
    ...  
    app.UseIdentity();  
    ...  
}

순서는 웹 애플리케이션의 HTTP 요청 처리 파이프라인에서 중요합니다. 따라서 로그인 화면을 구현하는 UI 프레임워크에 앞서 IdentityServer를 파이프라인에 추가해야 합니다.

IdentityServer 구성

eShopOnContainers 참조 애플리케이션의 다음 코드 예제에 설명된 대로 메서드를 호출 services.AddIdentityServer 하여 웹 애플리케이션 클래스의 Startup 메서드에서 IdentityServer를 구성 ConfigureServices 해야 합니다.

public void ConfigureServices(IServiceCollection services)  
{  
    ...  
    services.AddIdentityServer(x => x.IssuerUri = "null")  
        .AddSigningCredential(Certificate.Get())                 
        .AddAspNetIdentity<ApplicationUser>()  
        .AddConfigurationStore(builder =>  
            builder.UseSqlServer(connectionString, options =>  
                options.MigrationsAssembly(migrationsAssembly)))  
        .AddOperationalStore(builder =>  
            builder.UseSqlServer(connectionString, options =>  
                options.MigrationsAssembly(migrationsAssembly)))  
        .Services.AddTransient<IProfileService, ProfileService>();  
}

services.AddIdentityServer 메서드를 호출한 후 다음을 구성하기 위해 추가 흐름 API가 호출됩니다.

  • 서명에 사용되는 자격 증명
  • 사용자의 요청에 따라 액세스할 수 있는 API 및 ID 리소스
  • 토큰을 요청하기 위해 연결되는 클라이언트
  • ASP.NET Core ID

IdentityServer 4 구성을 동적으로 로드합니다. IdentityServer 4의 API를 사용하면 구성 개체의 메모리 내 목록에서 IdentityServer를 구성할 수 있습니다. eShopOnContainers 참조 애플리케이션에서 이러한 메모리 내 컬렉션은 애플리케이션에 하드 코딩됩니다. 그러나 프로덕션 시나리오에서 이러한 컬렉션은 구성 파일 또는 데이터베이스에서 동적으로 로드할 수 있습니다.

ASP.NET Core ID를 사용하도록 IdentityServer를 구성하는 방법에 관한 자세한 내용은 IdentityServer 설명서에서 ASP.NET Core ID 사용을 참조하세요.

API 리소스 구성

API 리소스를 구성할 때 AddInMemoryApiResources 메서드는 IEnumerable<ApiResource> 컬렉션을 예상합니다. 다음 코드 예제에서는 eShopOnContainers 참조 애플리케이션에서 이 컬렉션을 제공하는 GetApis 메서드를 보여줍니다.

public static IEnumerable<ApiResource> GetApis()  
{  
    return new List<ApiResource>  
    {  
        new ApiResource("orders", "Orders Service"),  
        new ApiResource("basket", "Basket Service")  
    };  
}

이 메서드는 IdentityServer가 순서와 basket API를 보호하도록 지정합니다. 따라서 이러한 API를 호출할 때 IdentityServer 관리형 액세스 토큰이 필요합니다. ApiResource 형식에 관한 자세한 내용은 IdentityServer 4 설명서의 API 리소스를 참조하세요.

ID 리소스 구성

ID 리소스를 구성할 때 AddInMemoryIdentityResources 메서드는 IEnumerable<IdentityResource> 컬렉션을 예상합니다. ID 리소스는 사용자 ID, 이름 또는 이메일 주소와 같은 데이터입니다. 각 ID 리소스에는 고유한 이름이 있으며, 임의 클레임 형식을 할당할 수 있습니다. 그러면 사용자의 ID 토큰에 포함됩니다. 다음 코드 예제에서는 eShopOnContainers 참조 애플리케이션에서 이 컬렉션을 제공하는 GetResources 메서드를 보여줍니다.

public static IEnumerable<IdentityResource> GetResources()  
{  
    return new List<IdentityResource>  
    {  
        new IdentityResources.OpenId(),  
        new IdentityResources.Profile()  
    };  
}

OpenID Connect 사양은 일부 표준 ID 리소스를 지정합니다. 최소 요구 사항은 사용자에 대한 고유 ID를 내보내기 위한 지원이 제공된다는 것입니다. IdentityResources.OpenId ID 리소스를 노출하여 이 작업을 수행합니다.

참고 항목

클래스는 IdentityResources OpenID 커넥트 사양(openid, 이메일, 프로필, 전화 및 주소)에 정의된 모든 범위를 지원합니다.

IdentityServer는 사용자 지정 ID 리소스 정의도 지원합니다. 형식에 대한 IdentityResource 자세한 내용은 IdentityServer 4 설명서의 ID 리소스를 참조하세요.

클라이언트 구성

클라이언트는 IdentityServer에서 토큰을 요청할 수 있는 애플리케이션입니다. 일반적으로 각 클라이언트에 대해 최소한 다음과 같은 설정을 정의해야 합니다.

  • 고유한 클라이언트 ID
  • 토큰 서비스와 허용되는 상호 작용(‘권한 부여 유형’이라고 함)
  • ID 및 액세스 토큰이 전송되는 위치(‘리디렉션 URI’라고 함)
  • 클라이언트가 액세스할 수 있는 리소스 목록(‘범위’라고 함)

클라이언트를 구성할 때 AddInMemoryClients 메서드는 IEnumerable<Client> 컬렉션을 예상합니다. 다음 코드 예제에서는 eShopOnContainers 참조 애플리케이션에서 이 컬렉션을 제공하는 메서드의 GetClients eShopOnContainers 모바일 앱에 대한 구성을 보여줍니다.

public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
    return new List<Client>
    {
        ...
        new Client
        {
            ClientId = "xamarin",
            ClientName = "eShop Xamarin OpenId Client",
            AllowedGrantTypes = GrantTypes.Hybrid,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            RedirectUris = { clientsUrl["Xamarin"] },
            RequireConsent = false,
            RequirePkce = true,
            PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" },
            AllowedCorsOrigins = { "http://eshopxamarin" },
            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "orders",
                "basket"
            },
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true
        },
        ...
    };
}

이 구성은 다음 속성에 대한 데이터를 지정합니다.

  • ClientId: 클라이언트의 고유 ID입니다.
  • ClientName: 로깅 및 동의 화면에 사용되는 클라이언트 표시 이름입니다.
  • AllowedGrantTypes: 클라이언트가 IdentityServer와 상호 작용하는 방법을 지정합니다. 자세한 내용은 인증 흐름 구성을 참조 하세요.
  • ClientSecrets: 토큰 엔드포인트에서 토큰을 요청할 때 사용되는 클라이언트 비밀 자격 증명을 지정합니다.
  • RedirectUris: 토큰 또는 권한 부여 코드를 반환할 수 있는 URI를 지정합니다.
  • RequireConsent: 동의 화면이 필요한지 여부를 지정합니다.
  • RequirePkce: 권한 부여 코드를 사용하는 클라이언트가 증명 키를 보내야 하는지 여부를 지정합니다.
  • PostLogoutRedirectUris: 로그아웃 후 리디렉션할 수 있는 URI를 지정합니다.
  • AllowedCorsOrigins: IdentityServer에서 원본 간 호출을 허용할 수 있도록 클라이언트의 원본을 지정합니다.
  • AllowedScopes: 클라이언트가 액세스할 수 있는 리소스를 지정합니다. 기본적으로 클라이언트는 리소스에 액세스할 수 없습니다.
  • AllowOfflineAccess: 클라이언트가 새로 고침 토큰을 요청할 수 있는지 여부를 지정합니다.

인증 흐름 구성

클라이언트와 IdentityServer 간의 인증 흐름은 Client.AllowedGrantTypes 속성에 권한 부여 유형을 지정하여 구성할 수 있습니다. OpenID 커넥트 및 OAuth 2.0 사양은 다음을 비롯한 다양한 인증 흐름을 정의합니다.

  • 암시적. 이 흐름은 브라우저 기반 애플리케이션에 최적화되어 있으며 사용자 인증 전용 또는 인증 및 액세스 토큰 요청에 사용해야 합니다. 모든 토큰은 브라우저를 통해 전송되므로 새로 고침 토큰과 같은 고급 기능은 허용되지 않습니다.
  • 권한 부여 코드입니다. 이 흐름은 클라이언트 인증을 지원하면서 브라우저 전면 채널이 아닌 백 채널에서 토큰을 검색하는 기능을 제공합니다.
  • 혼합. 이 흐름은 암시적 코드 부여 형식과 인증 코드 부여 형식의 조합입니다. ID 토큰은 브라우저 채널을 통해 전송되며 권한 부여 코드와 같은 다른 아티팩트와 함께 서명된 프로토콜 응답을 포함합니다. 응답의 유효성을 성공적으로 검사한 후 백 채널을 사용하여 액세스 및 새로 고침 토큰을 검색해야 합니다.

하이브리드 인증 흐름을 사용합니다. 하이브리드 인증 흐름은 브라우저 채널에 가해지는 여러 공격을 완화하며 액세스 토큰(및 가능하다면 새로 고침 토큰)을 검색하려는 네이티브 애플리케이션에 권장되는 흐름입니다.

인증 흐름에 관한 자세한 내용은 IdentityServer 4 설명서의 권한 부여 유형을 참조하세요.

인증 수행

IdentityServer가 사용자를 대신하여 토큰을 발급하려면 사용자가 IdentityServer에 로그인해야 합니다. 그러나 IdentityServer는 인증을 위해 사용자 인터페이스 또는 데이터베이스를 제공하지 않습니다. 따라서 eShopOnContainers 참조 애플리케이션에서 ASP.NET Core ID가 이러한 목적으로 사용됩니다.

eShopOnContainers 모바일 앱은 그림 9-2에 설명된 하이브리드 인증 흐름을 사용하여 IdentityServer로 인증합니다.

High-level overview of the sign-in process

그림 9-2: 로그인 프로세스의 개략적인 개요

에 대한 로그인 요청이 이루어집니다 <base endpoint>:5105/connect/authorize. 인증에 성공한 후 IdentityServer는 인증 코드와 ID 토큰이 포함된 인증 응답을 반환합니다. 그런 다음 권한 부여 코드가 액세스, ID 및 새로 고침 토큰으로 응답하는 데 전송 <base endpoint>:5105/connect/token됩니다.

eShopOnContainers 모바일 앱은 추가 매개 변수를 사용하여 요청을 <base endpoint>:5105/connect/endsession전송하여 IdentityServer에서 로그아웃합니다. 로그아웃이 발생하면 IdentityServer는 로그아웃 후 리디렉션 URI를 모바일 앱으로 다시 전송하여 응답합니다. 그림 9-3에서는 이 프로세스를 보여 줍니다.

High-level overview of the sign-out process

그림 9-3: 로그아웃 프로세스의 개략적인 개요

eShopOnContainers 모바일 앱에서 IdentityServer와의 통신은 인터페이스를 IdentityService 구현하는 클래스에 IIdentityService 의해 수행됩니다. 이 인터페이스는 구현 클래스가 CreateAuthorizationRequest, CreateLogoutRequestGetTokenAsync 메서드를 제공해야 한다고 지정합니다.

로그인

사용자가 로그인 단추를 LoginViewSignInCommand 하면 클래스에서 LoginViewModel 실행되어 메서드가 SignInAsync 실행됩니다. 다음 코드 예제에서는 이 메서드를 보여줍니다.

private async Task SignInAsync()  
{  
    ...  
    LoginUrl = _identityService.CreateAuthorizationRequest();  
    IsLogin = true;  
    ...  
}

이 메서드는 CreateAuthorizationRequest 다음 코드 예제에 IdentityService 표시된 클래스의 메서드를 호출합니다.

public string CreateAuthorizationRequest()
{
    // Create URI to authorization endpoint
    var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);

    // Dictionary with values for the authorize request
    var dic = new Dictionary<string, string>();
    dic.Add("client_id", GlobalSetting.Instance.ClientId);
    dic.Add("client_secret", GlobalSetting.Instance.ClientSecret); 
    dic.Add("response_type", "code id_token");
    dic.Add("scope", "openid profile basket orders locations marketing offline_access");
    dic.Add("redirect_uri", GlobalSetting.Instance.Callback);
    dic.Add("nonce", Guid.NewGuid().ToString("N"));
    dic.Add("code_challenge", CreateCodeChallenge());
    dic.Add("code_challenge_method", "S256");

    // Add CSRF token to protect against cross-site request forgery attacks.
    var currentCSRFToken = Guid.NewGuid().ToString("N");
    dic.Add("state", currentCSRFToken);

    var authorizeUri = authorizeRequest.Create(dic); 
    return authorizeUri;
}

이 메서드는 필수 매개 변수를 사용하여 IdentityServer의 권한 부여 엔드포인트에 대한 URI를 만듭니다. 권한 부여 엔드포인트는 사용자 설정으로 노출되는 기본 엔드포인트의 포트 5105에서 /connect/authorize에 위치합니다. 사용자 설정에 관한 자세한 내용은 구성 관리를 참조하세요.

참고 항목

EShopOnContainers 모바일 앱의 공격 표면은 OAuth에 대한 PKCE(코드 교환용 증명 키) 확장을 구현하여 감소합니다. PKCE는 차단된 경우 권한 부여 코드가 사용되지 않도록 보호합니다. 이러한 보호는 클라이언트가 비밀 검증 도구 즉, 권한 부여 요청에 전달되는 해시를 생성하여 이루어지며, 이 해시는 인증 코드를 사용할 때 해시되지 않은 상태로 표시됩니다. PKCE에 관한 자세한 내용은 인터넷 엔지니어링 태스크 포스 웹 사이트에서 OAuth 공용 클라이언트의 코드 교환에 대한 증명 키를 참조하세요.

반환된 URI는 LoginViewModel 클래스의 LoginUrl 속성에 저장됩니다. 속성이 IsLogin 되면 truein이 WebViewLoginView 표시됩니다. 데이터는 WebView 해당 Source 속성을 클래스의 속성에 LoginUrl 바인딩하므로 속성이 IdentityServer의 LoginViewModel 권한 부여 엔드포인트로 설정되면 IdentityServer LoginUrl 에 대한 로그인 요청을 수행합니다. IdentityServer가 이 요청을 수신하고 사용자가 인증 WebView 되지 않으면 구성된 로그인 페이지로 리디렉션됩니다(그림 9-4).

Login page displayed by the WebView

그림 9-4: WebView에서 표시하는 로그인 페이지

로그인이 완료되면 WebView는 반환 URI로 리디렉션됩니다. 이 WebView 탐색을 수행하면 다음 코드 예제와 같이 LoginViewModel 클래스의 NavigateAsync 메서드가 실행됩니다.

private async Task NavigateAsync(string url)  
{  
    ...  
    var authResponse = new AuthorizeResponse(url);  
    if (!string.IsNullOrWhiteSpace(authResponse.Code))  
    {  
        var userToken = await _identityService.GetTokenAsync(authResponse.Code);  
        string accessToken = userToken.AccessToken;  

        if (!string.IsNullOrWhiteSpace(accessToken))  
        {  
            Settings.AuthAccessToken = accessToken;  
            Settings.AuthIdToken = authResponse.IdentityToken;  

            await NavigationService.NavigateToAsync<MainViewModel>();  
            await NavigationService.RemoveLastFromBackStackAsync();  
        }  
    }  
    ...  
}

이 메서드는 반환 URI에 포함된 인증 응답을 구문 분석하고 유효한 권한 부여 코드가 있는 경우 IdentityServer의 토큰 엔드포인트에 요청하여 인증 코드, PKCE 비밀 검증 도구 및 기타 필수 매개 변수를 전달합니다. 토큰 엔드포인트는 사용자 설정으로 노출되는 기본 엔드포인트의 포트 5105에서 /connect/token에 위치합니다. 사용자 설정에 관한 자세한 내용은 구성 관리를 참조하세요.

반환 URI의 유효성을 검사합니다. eShopOnContainers 모바일 앱은 반환 URI의 유효성을 검사하지 않지만 반환 URI가 알려진 위치를 참조하는지 확인하는 것이 가장 좋습니다.

토큰 엔드포인트는 유효한 인증 코드 및 PKCE 비밀 검증 도구를 수신하면 액세스 토큰, ID 토큰 및 새로 고침 토큰으로 응답합니다. 액세스 토큰(API 리소스에 대한 액세스를 허용)과 ID 토큰은 애플리케이션 설정으로 저장되고 페이지 탐색이 수행됩니다. 따라서 eShopOnContainers 모바일 앱의 전반적인 효과는 다음과 같습니다. 사용자가 IdentityServer를 사용하여 성공적으로 인증할 수 있는 경우 선택한 탭으로 표시되는 CatalogView 페이지 TabbedPage 로 이동합니다MainView.

탐색에 관한 자세한 내용은 탐색을 참조하세요. 탐색으로 인해 뷰 모델 메서드가 실행되는 방법에 WebView 대한 자세한 내용은 동작을 사용하여 탐색 호출을 참조 하세요. 애플리케이션 설정에 대한 자세한 내용은 구성 관리를 참조하세요.

참고 항목

또한 eShopOnContainers는 앱이 모의 서비스를 사용하도록 구성된 경우 모의 로그인을 허용합니다 SettingsView. 이 모드에서는 앱이 IdentityServer와 통신하지 않고 사용자가 자격 증명을 사용하여 로그인할 수 있도록 합니다.

로그아웃

사용자가 로그아웃 단추를 LogoutCommand 탭하면 클래스에서 ProfileViewModel 실행되어 메서드가 LogoutAsync 실행됩니다.ProfileView 이 메서드는 LoginView 페이지로 탐색을 수행하여 true로 설정된 LogoutParameter 인스턴스를 매개 변수로 전달합니다. 페이지 탐색 중에 매개 변수를 전달하는 방법에 대한 자세한 내용은 탐색 중에 매개 변수 전달을 참조하세요.

하나의 뷰가 생성되어 이를 탐색하면 해당 뷰의 연결된 뷰 모델의 InitializeAsync 메서드가 실행되며, 다음 코드 예제에서 보는 것과 같은 LoginViewModel 클래스의 Logout 메서드를 실행합니다.

private void Logout()  
{  
    var authIdToken = Settings.AuthIdToken;  
    var logoutRequest = _identityService.CreateLogoutRequest(authIdToken);  

    if (!string.IsNullOrEmpty(logoutRequest))  
    {  
        // Logout  
        LoginUrl = logoutRequest;  
    }  
    ...  
}

이 메서드는 IdentityService 클래스에서 CreateLogoutRequest 메서드를 호출하여 애플리케이션 설정에서 검색된 ID 토큰을 매개 변수로 전달합니다. 애플리케이션 설정에 대한 자세한 내용은 구성 관리를 참조하세요. 다음 코드 예제는 CreateLogoutRequest 메서드를 보여줍니다.

public string CreateLogoutRequest(string token)  
{  
    ...  
    return string.Format("{0}?id_token_hint={1}&post_logout_redirect_uri={2}",   
        GlobalSetting.Instance.LogoutEndpoint,  
        token,  
        GlobalSetting.Instance.LogoutCallback);  
}

이 메서드는 필수 매개 변수를 사용하여 IdentityServer의 끝 세션 엔드포인트에 대한 URI를 만듭니다. 최종 세션 엔드포인트는 사용자 설정으로 노출되는 기본 엔드포인트의 포트 5105에서 /connect/endsession에 위치합니다. 사용자 설정에 관한 자세한 내용은 구성 관리를 참조하세요.

반환된 URI는 LoginViewModel 클래스의 LoginUrl 속성에 저장됩니다. 속성이 IsLogintrue있는 동안 해당 WebView 속성이 LoginView 표시됩니다. 데이터는 WebView 해당 Source 속성을 클래스의 LoginViewModel 속성에 LoginUrl 바인딩하므로 속성이 IdentityServer의 끝 세션 엔드포인트로 설정되면 IdentityServer LoginUrl 에 대한 로그아웃 요청을 수행합니다. 사용자가 로그인한 경우 IdentityServer가 이 요청을 받으면 로그아웃이 발생합니다. 인증은 ASP.NET Core의 쿠키 인증 미들웨어에서 관리하는 쿠키로 추적됩니다. 따라서 IdentityServer에서 로그아웃하면 인증 쿠키가 제거되고 로그아웃 후 리디렉션 URI가 클라이언트로 다시 전송됩니다.

모바일 앱 WebView 에서 로그아웃 후 리디렉션 URI로 리디렉션됩니다. 이 WebView 탐색을 수행하면 다음 코드 예제와 같이 LoginViewModel 클래스의 NavigateAsync 메서드가 실행됩니다.

private async Task NavigateAsync(string url)  
{  
    ...  
    Settings.AuthAccessToken = string.Empty;  
    Settings.AuthIdToken = string.Empty;  
    IsLogin = false;  
    LoginUrl = _identityService.CreateAuthorizationRequest();  
    ...  
}

이 메서드는 애플리케이션 설정에서 ID 토큰과 액세스 토큰을 모두 지우고 속성을 설정 IsLogin 하여 falseWebViewLoginView 페이지에서 보이지 않게 합니다. 마지막으로, LoginUrl 속성은 사용자가 다음에 로그인을 시작할 때를 준비하기 위해 필요한 매개 변수를 사용하여 IdentityServer의 권한 부여 엔드포인트의 URI로 설정됩니다.

탐색에 관한 자세한 내용은 탐색을 참조하세요. 탐색으로 인해 뷰 모델 메서드가 실행되는 방법에 WebView 대한 자세한 내용은 동작을 사용하여 탐색 호출을 참조 하세요. 애플리케이션 설정에 대한 자세한 내용은 구성 관리를 참조하세요.

참고 항목

또한 eShopOnContainers는 앱이 설정View에서 모의 서비스를 사용하도록 구성된 경우에도 모의 로그아웃을 허용합니다. 이 모드에서는 앱이 IdentityServer와 통신하지 않고 그 대신 애플리케이션 설정에서 저장된 토큰을 지웁니다.

권한 부여

인증 후 ASP.NET Core 웹 API는 액세스 권한을 부여해야 하는 경우가 많으며, 이를 통해 서비스는 일부 인증된 사용자가 API를 사용할 수 있지만 모든 사용자가 사용할 수는 없습니다.

다음 코드 예제와 같이 컨트롤러 또는 작업에 권한 부여 특성을 적용하여 인증된 사용자에게 컨트롤러 또는 작업에 대한 액세스를 제한하여 ASP.NET Core MVC 경로에 대한 액세스를 제한할 수 있습니다.

[Authorize]  
public class BasketController : Controller  
{  
    ...  
}

권한이 없는 사용자가 특성으로 Authorize 표시된 컨트롤러 또는 작업에 액세스하려고 하면 MVC 프레임워크는 401(권한 없는) HTTP 상태 코드를 반환합니다.

참고 항목

특성에 매개 변수를 Authorize 지정하여 API를 특정 사용자로 제한할 수 있습니다. 자세한 내용은 권한 부여를 참조 하세요.

IdentityServer를 권한 부여 워크플로에 통합하면 그것이 제공하는 액세스 토큰이 권한 부여를 제어합니다. 이 방법은 그림 9-5에 나와 있습니다.

Authorization by access token

그림 9-5: 액세스 토큰별 권한 부여

eShopOnContainers 모바일 앱은 ID 마이크로 서비스와 통신하고 인증 프로세스의 일부로 액세스 토큰을 요청합니다. 그런 다음 액세스 토큰은 액세스 요청의 일부로서 주문 및 basket 마이크로 서비스에 의해 노출되는 API에 전달됩니다. 액세스 토큰에는 클라이언트 및 사용자에 대한 정보가 포함됩니다. 그런 다음, API는 해당 정보를 사용하여 데이터에 대한 액세스 권한을 부여합니다. API를 보호하도록 IdentityServer를 구성하는 방법에 대한 자세한 내용은 API 리소스 구성을 참조 하세요.

권한 부여를 수행하도록 IdentityServer 구성

IdentityServer를 사용하여 권한 부여를 수행하려면 해당 권한 부여 미들웨어를 웹 애플리케이션의 HTTP 요청 파이프라인에 추가해야 합니다. 미들웨어는 메서드에서 ConfigureAuth 호출되는 웹 애플리케이션 클래스의 Startup 메서드에 Configure 추가되며 eShopOnContainers 참조 애플리케이션의 다음 코드 예제에 설명되어 있습니다.

protected virtual void ConfigureAuth(IApplicationBuilder app)  
{  
    var identityUrl = Configuration.GetValue<string>("IdentityUrl");  
    app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions  
    {  
        Authority = identityUrl.ToString(),  
        ScopeName = "basket",  
        RequireHttpsMetadata = false  
    });  
} 

이 메서드는 유효한 액세스 토큰으로만 API에 액세스할 수 있도록 합니다. 미들웨어는 들어오는 토큰의 유효성을 검사하여 신뢰할 수 있는 발급자에서 전송되었는지 확인하고 토큰을 수신하는 API와 함께 사용할 수 있는 토큰이 유효한지 확인합니다. 따라서 주문 또는 장바구니 컨트롤러로 검색하면 액세스 토큰이 필요함을 나타내는 401(권한 없는) HTTP 상태 코드가 반환됩니다.

참고 항목

IdentityServer의 권한 부여 미들웨어는 MVC를 추가하기 전에 app.UseMvc() 또는 app.UseMvcWithDefaultRoute()를 사용하여 웹 애플리케이션의 HTTP 요청 파이프라인에 추가해야 합니다.

API에 대한 액세스 요청 만들기

주문 및 장바구니 마이크로 서비스에 대한 요청을 수행할 때 다음 코드 예제와 같이 인증 프로세스 중에 IdentityServer에서 가져온 액세스 토큰이 요청에 포함되어야 합니다.

var authToken = Settings.AuthAccessToken;  
Order = await _ordersService.GetOrderAsync(Convert.ToInt32(order.OrderNumber), authToken);

액세스 토큰은 애플리케이션 설정으로 저장되며 플랫폼별 스토리지에서 검색되고 클래스의 메서드 호출 GetOrderAsyncOrderService 포함됩니다.

마찬가지로 다음 코드 예제와 같이 IdentityServer로 보호된 API로 데이터를 보낼 때 액세스 토큰을 포함해야 합니다.

var authToken = Settings.AuthAccessToken;  
await _basketService.UpdateBasketAsync(new CustomerBasket  
{  
    BuyerId = userInfo.UserId,   
    Items = BasketItems.ToList()  
}, authToken);

액세스 토큰은 플랫폼별 스토리지에서 검색되고 클래스의 메서드 호출 UpdateBasketAsyncBasketService 포함됩니다.

eShopOnContainers 모바일 앱의 클래스는 RequestProvider 이 클래스를 사용하여 HttpClient eShopOnContainers 참조 애플리케이션에서 노출하는 RESTful API를 요청합니다. 권한 부여가 필요한 주문 및 basket API를 요청할 때 유효한 액세스 토큰을 요청에 포함해야 합니다. 이 작업은 다음 코드 예제에 설명된 대로 인스턴스의 헤더에 HttpClient 액세스 토큰을 추가하여 수행됩니다.

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

HttpClient 클래스의 DefaultRequestHeaders 속성은 각 요청과 함께 전송되는 헤더를 노출하며, 액세스 토큰은 Bearer를 문자열의 접두사로 하는 Authorization 헤더에 추가됩니다. 요청이 RESTful API로 전송되면 헤더 값 Authorization 이 추출되고 유효성이 검사되어 신뢰할 수 있는 발급자에서 전송되는지 확인하고 사용자가 수신하는 API를 호출할 수 있는 권한이 있는지 여부를 확인하는 데 사용됩니다.

eShopOnContainers 모바일 앱이 웹 요청을 만드는 방법에 대한 자세한 내용은 원격 데이터 액세스를 참조 하세요.

요약

ASP.NET MVC 웹 애플리케이션과 통신하는 앱에 Xamarin.Forms 인증 및 권한 부여를 통합하는 방법에는 여러 가지가 있습니다. eShopOnContainers 모바일 앱은 IdentityServer 4를 사용하는 컨테이너화된 ID 마이크로 서비스를 사용하여 인증 및 권한 부여를 수행합니다. IdentityServer는 전달자 토큰 인증을 수행하기 위해 ASP.NET Core ID와 통합되는 ASP.NET Core에 대한 오픈 소스 OpenID Connect 및 OAuth 2.0 프레임워크입니다.

모바일 앱은 사용자를 인증하거나 리소스에 액세스하기 위해 IdentityServer에서 보안 토큰을 요청합니다. 리소스에 액세스할 때 권한 부여가 필요한 API에 대한 요청에 액세스 토큰을 포함해야 합니다. IdentityServer의 미들웨어는 들어오는 액세스 토큰의 유효성을 검사하여 신뢰할 수 있는 발급자에서 전송되고 이를 수신하는 API와 함께 사용할 수 있는지 확인합니다.