ASP.NET Web API 2.2에서 개별 계정 및 로컬 로그인을 사용 하 여 Web API 보안 유지Secure a Web API with Individual Accounts and Local Login in ASP.NET Web API 2.2

Mike Wassonby Mike Wasson

샘플 앱 다운로드Download Sample App

이 항목에서는 OAuth2를 사용 하 여 웹 API를 보호 하 여 멤버 자격 데이터베이스에 대해 인증 하는 방법을 보여 줍니다.This topic shows how to secure a web API using OAuth2 to authenticate against a membership database.

자습서에서 사용 되는 소프트웨어 버전Software versions used in the tutorial

Visual Studio 2013 웹 API 프로젝트 템플릿은 인증을 위한 세 가지 옵션을 제공 합니다.In Visual Studio 2013, the Web API project template gives you three options for authentication:

  • 개별 계정.Individual accounts. 앱은 멤버 자격 데이터베이스를 사용 합니다.The app uses a membership database.
  • 조직 계정.Organizational accounts. 사용자는 Azure Active Directory, Office 365 또는 온-프레미스 Active Directory 자격 증명을 사용 하 여 로그인 합니다.Users sign in with their Azure Active Directory, Office 365, or on-premise Active Directory credentials.
  • Windows 인증.Windows authentication. 이 옵션은 인트라넷 응용 프로그램용 이며 Windows 인증 IIS 모듈을 사용 합니다.This option is intended for Intranet applications, and uses the Windows Authentication IIS module.

이러한 옵션에 대 한 자세한 내용은 Visual Studio 2013에서 ASP.NET 웹 프로젝트 만들기를 참조 하세요.For more details about these options, see Creating ASP.NET Web Projects in Visual Studio 2013.

개별 계정은 사용자가 로그인 할 수 있는 두 가지 방법을 제공 합니다.Individual accounts provide two ways for a user to log in:

  • 로컬 로그인.Local login. 사용자가 사이트에 등록 하 고 사용자 이름과 암호를 입력 합니다.The user registers at the site, entering a username and password. 앱은 멤버 자격 데이터베이스에 암호 해시를 저장 합니다.The app stores the password hash in the membership database. 사용자가 로그인 하면 ASP.NET Identity 시스템에서 암호를 확인 합니다.When the user logs in, the ASP.NET Identity system verifies the password.
  • 소셜 로그인.Social login. 사용자가 Facebook, Microsoft 또는 Google과 같은 외부 서비스를 사용 하 여 로그인 합니다.The user signs in with an external service, such as Facebook, Microsoft, or Google. 앱은 여전히 멤버 자격 데이터베이스에서 사용자에 대 한 항목을 만들지만 자격 증명을 저장 하지는 않습니다.The app still creates an entry for the user in the membership database, but does not store any credentials. 사용자가 외부 서비스에 로그인 하 여 인증 합니다.The user authenticates by signing into the external service.

이 문서에서는 로컬 로그인 시나리오를 살펴봅니다.This article looks at the local login scenario. 웹 API는 로컬 로그인과 소셜 로그인 모두에 대해 OAuth2를 사용 하 여 요청을 인증 합니다.For both local and social login, Web API uses OAuth2 to authenticate requests. 그러나 로컬 및 소셜 로그인에 대 한 자격 증명 흐름은 다릅니다.However, the credential flows are different for local and social login.

이 문서에서는 사용자가 로그인 하 여 웹 API에 인증 된 AJAX 호출을 보낼 수 있는 간단한 앱을 설명 합니다.In this article, I'll demonstrate a simple app that lets the user log in and send authenticated AJAX calls to a web API. 샘플 코드는 여기에서 다운로드할 수 있습니다.You can download the sample code here. 추가 정보는 Visual Studio에서 샘플을 처음부터 만드는 방법을 설명 합니다.The readme describes how to create the sample from scratch in Visual Studio.

샘플 앱은 데이터 바인딩 및 jQuery에 대해 녹아웃을 사용 하 여 AJAX 요청을 보냅니다.The sample app uses Knockout.js for data-binding and jQuery for sending AJAX requests. AJAX 호출에 초점을 맞춘 후이 문서에 대 한 사용자의 녹아웃을 알 필요가 없습니다.I'll be focusing on the AJAX calls, so you don't need to know Knockout.js for this article.

이 과정을 통해 다음과 같이 설명할 수 있습니다.Along the way, I'll describe:

  • 응용 프로그램이 클라이언트 쪽에서 수행 하는 작업입니다.What the app is doing on the client side.
  • 서버에서 무슨 일이 발생 합니다.What's happening on the server.
  • 중간의 HTTP 트래픽입니다.The HTTP traffic in the middle.

먼저 일부 OAuth2 용어를 정의 해야 합니다.First, we need to define some OAuth2 terminology.

  • 리소스.Resource. 보호할 수 있는 데이터의 일부입니다.Some piece of data that can be protected.
  • 리소스 서버.Resource server. 리소스를 호스트 하는 서버입니다.The server that hosts the resource.
  • 리소스 소유자입니다.Resource owner. 리소스에 대 한 액세스 권한을 부여할 수 있는 엔터티입니다.The entity that can grant permission to access a resource. (일반적으로 사용자입니다.)(Typically the user.)
  • 클라이언트: 리소스에 액세스 하려는 앱입니다.Client: The app that wants access to the resource. 이 문서에서 클라이언트는 웹 브라우저입니다.In this article, the client is a web browser.
  • 액세스 토큰입니다.Access token. 리소스에 대 한 액세스 권한을 부여 하는 토큰입니다.A token that grants access to a resource.
  • 전달자 토큰입니다.Bearer token. 사용자가 토큰을 사용할 수 있는 속성을 가진 특정 형식의 액세스 토큰입니다.A particular type of access token, with the property that anyone can use the token. 즉, 클라이언트는 전달자 토큰을 사용 하는 암호화 키 또는 기타 비밀이 필요 하지 않습니다.In other words, a client doesn't need a cryptographic key or other secret to use a bearer token. 이러한 이유로 전달자 토큰은 HTTPS를 통해서만 사용 해야 하며, 짧은 만료 시간을 사용 해야 합니다.For that reason, bearer tokens should only be used over a HTTPS, and should have relatively short expiration times.
  • 권한 부여 서버.Authorization server. 액세스 토큰을 제공 하는 서버입니다.A server that gives out access tokens.

응용 프로그램은 권한 부여 서버 및 리소스 서버 역할을 할 수 있습니다.An application can act as both authorization server and resource server. Web API 프로젝트 템플릿은이 패턴을 따릅니다.The Web API project template follows this pattern.

로컬 로그인 자격 증명 흐름Local Login Credential Flow

로컬 로그인의 경우 Web API는 OAuth2에 정의 된 리소스 소유자 암호 흐름 을 사용 합니다.For local login, Web API uses the resource owner password flow defined in OAuth2.

  1. 사용자가 클라이언트에 이름과 암호를 입력 합니다.The user enters a name and password into the client.
  2. 클라이언트는 권한 부여 서버에 이러한 자격 증명을 보냅니다.The client sends these credentials to the authorization server.
  3. 권한 부여 서버는 자격 증명을 인증 하 고 액세스 토큰을 반환 합니다.The authorization server authenticates the credentials and returns an access token.
  4. 보호 된 리소스에 액세스 하기 위해 클라이언트는 HTTP 요청의 인증 헤더에 액세스 토큰을 포함 합니다.To access a protected resource, the client includes the access token in the Authorization header of the HTTP request.

웹 API 프로젝트 템플릿에서 개별 계정을 선택 하면 프로젝트에 사용자 자격 증명의 유효성을 검사 하 고 토큰을 발급 하는 권한 부여 서버가 포함 됩니다.When you select Individual accounts in the Web API project template, the project includes an authorization server that validates user credentials and issues tokens. 다음 다이어그램에서는 Web API 구성 요소를 기준으로 동일한 자격 증명 흐름을 보여 줍니다.The following diagram shows the same credential flow in terms of Web API components.

이 시나리오에서 Web API 컨트롤러는 리소스 서버 역할을 합니다.In this scenario, Web API controllers act as resource servers. 인증 필터는 액세스 토큰의 유효성을 검사 하 고 [권한 부여] 특성은 리소스를 보호 하는 데 사용 됩니다.An authentication filter validates access tokens, and the [Authorize] attribute is used to protect a resource. 컨트롤러나 작업에 [권한 부여] 특성이 있는 경우 해당 컨트롤러 또는 작업에 대 한 모든 요청을 인증 해야 합니다.When a controller or action has the [Authorize] attribute, all requests to that controller or action must be authenticated. 그렇지 않으면 권한 부여가 거부 되 고 Web API는 401 (권한 없음) 오류를 반환 합니다.Otherwise, authorization is denied, and Web API returns a 401 (Unauthorized) error.

권한 부여 서버와 인증 필터는 모두 OAuth2의 세부 정보를 처리 하는 OWIN 미들웨어 구성 요소를 호출 합니다.The authorization server and the authentication filter both call into an OWIN middleware component that handles the details of OAuth2. 디자인은이 자습서의 뒷부분에서 자세히 설명 합니다.I'll describe the design in more detail later in this tutorial.

권한 없는 요청 보내기Sending an Unauthorized Request

시작 하려면 앱을 실행 하 고 API 호출 단추를 클릭 합니다.To get started, run the app and click the Call API button. 요청이 완료 되 면 결과 상자에 오류 메시지가 표시 됩니다.When the request completes, you should see an error message in the Result box. 요청이 액세스 토큰을 포함 하지 않기 때문에 요청이 권한 없는 것입니다.That's because the request does not contain an access token, so the request is unauthorized.

Api 호출 단추는 웹 API 컨트롤러 작업을 호출 하는 ~/api/values에 AJAX 요청을 보냅니다.The Call API button sends an AJAX request to ~/api/values, which invokes a Web API controller action. 다음은 AJAX 요청을 보내는 JavaScript 코드의 섹션입니다.Here is the section of JavaScript code that sends the AJAX request. 샘플 앱에서 모든 JavaScript 앱 코드는 Scripts\app.js 파일에 있습니다.In the sample app, all of the JavaScript app code is located in the Scripts\app.js file.

// If we already have a bearer token, set the Authorization header.
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
    headers.Authorization = 'Bearer ' + token;
}

$.ajax({
    type: 'GET',
    url: 'api/values/1',
    headers: headers
}).done(function (data) {
    self.result(data);
}).fail(showError);

사용자가 로그인 할 때까지 전달자 토큰이 없으며, 따라서 요청에 권한 부여 헤더가 없습니다.Until the user logs in, there is no bearer token, and therefore no Authorization header in the request. 이로 인해 요청에서 401 오류가 반환 됩니다.This causes the request to return a 401 error.

다음은 HTTP 요청입니다.Here is the HTTP request. ( Fiddler 를 사용 하 여 HTTP 트래픽을 캡처 했습니다.)(I used Fiddler to capture the HTTP traffic.)

GET https://localhost:44305/api/values HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Accept-Language: en-US,en;q=0.5
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/

HTTP 응답:HTTP response:

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
WWW-Authenticate: Bearer
Date: Tue, 30 Sep 2014 21:54:43 GMT
Content-Length: 61

{"Message":"Authorization has been denied for this request."}

응답에는 챌린지가 설정 된 Www 인증 헤더가 포함 되어 있습니다.Notice that the response includes a Www-Authenticate header with the challenge set to Bearer. 서버에 전달자 토큰이 필요 함을 나타냅니다.That indicates the server expects a bearer token.

사용자 등록Register a User

앱의 등록 섹션에서 전자 메일 및 암호를 입력 하 고 등록 단추를 클릭 합니다.In the Register section of the app, enter an email and password, and click the Register button.

이 샘플에 유효한 전자 메일 주소를 사용할 필요는 없지만 실제 앱은 주소를 확인 합니다.You don't need to use a valid email address for this sample, but a real app would confirm the address. ( 로그인, 전자 메일 확인 및 암호 재설정을 사용 하 여 보안 ASP.NET MVC 5 웹 앱 만들기를참조 하세요.) 암호에 대해 대문자, 소문자, 숫자 및 영숫자가 아닌 문자를 포함 하는 "Password1!"와 같은 항목을 사용 합니다.(See Create a secure ASP.NET MVC 5 web app with log in, email confirmation and password reset.) For the password, use something like "Password1!", with an upper case letter, lower case letter, number, and non-alpha-numeric character. 앱을 간단 하 게 유지 하기 위해 클라이언트 쪽 유효성 검사를 수행 하 여 암호 형식에 문제가 있는 경우 400 (잘못 된 요청) 오류가 발생 합니다.To keep the app simple, I left out client-side validation, so if there is a problem with the password format, you'll get a 400 (Bad Request) error.

등록 단추를 클릭 하면 POST 요청을 ~/api/Account/Register/.로 보냅니다.The Register button sends a POST request to ~/api/Account/Register/. 요청 본문은 이름과 암호를 포함 하는 JSON 개체입니다.The request body is a JSON object that holds the name and password. 요청을 보내는 JavaScript 코드는 다음과 같습니다.Here is the JavaScript code that sends the request:

var data = {
    Email: self.registerEmail(),
    Password: self.registerPassword(),
    ConfirmPassword: self.registerPassword2()
};

$.ajax({
    type: 'POST',
    url: '/api/Account/Register',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify(data)
}).done(function (data) {
    self.result("Done!");
}).fail(showError);

HTTP 요청:HTTP request:

POST https://localhost:44305/api/Account/Register HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/
Content-Length: 84

{"Email":"alice@example.com","Password":"Password1!","ConfirmPassword":"Password1!"}

HTTP 응답:HTTP response:

HTTP/1.1 200 OK
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 00:57:58 GMT
Content-Length: 0

이 요청은 AccountController 클래스에 의해 처리 됩니다.This request is handled by the AccountController class. 내부적으로 AccountController는 ASP.NET Identity를 사용 하 여 멤버 자격 데이터베이스를 관리 합니다.Internally, AccountController uses ASP.NET Identity to manage the membership database.

Visual Studio에서 로컬로 응용 프로그램을 실행 하는 경우 사용자 계정은 LocalDB의 AspNetUsers 테이블에 저장 됩니다.If you run the app locally from Visual Studio, user accounts are stored in LocalDB, in the AspNetUsers table. Visual Studio에서 테이블을 보려면 보기 메뉴를 클릭 하 서버 탐색기, 데이터 연결을 차례로 확장 합니다.To view the tables in Visual Studio, click the View menu, select Server Explorer, then expand Data Connections.

액세스 토큰 가져오기Get an Access Token

지금까지 OAuth를 수행 하지 않았지만, 이제 액세스 토큰을 요청할 때 작동 중인 OAuth 권한 부여 서버가 표시 됩니다.So far we have not done any OAuth, but now we'll see the OAuth authorization server in action, when we request an access token. 샘플 앱의 로그인 영역에서 전자 메일 및 암호를 입력 하 고 로그인을 클릭 합니다.In the Log In area of the sample app, enter the email and password and click Log In.

로그인 단추는 토큰 끝점에 요청을 보냅니다.The Log In button sends a request to the token endpoint. 요청 본문에는 다음과 같은 폼 url로 인코딩된 데이터가 포함 되어 있습니다.The body of the request contains the following form-url-encoded data:

  • grant_유형: "password"grant_type: "password"
  • 사용자 이름: 사용자의 전자 메일을 <>username: <the user's email>
  • 암호: 암호 <>password: <password>

AJAX 요청을 보내는 JavaScript 코드는 다음과 같습니다.Here is the JavaScript code that sends the AJAX request:

var loginData = {
    grant_type: 'password',
    username: self.loginEmail(),
    password: self.loginPassword()
};

$.ajax({
    type: 'POST',
    url: '/Token',
    data: loginData
}).done(function (data) {
    self.user(data.userName);
    // Cache the access token in session storage.
    sessionStorage.setItem(tokenKey, data.access_token);
}).fail(showError);

요청이 성공 하면 권한 부여 서버는 응답 본문에 액세스 토큰을 반환 합니다.If the request succeeds, the authorization server returns an access token in the response body. 세션 저장소에 토큰을 저장 하 여 나중에 API로 요청을 보낼 때 사용 합니다.Notice that we store the token in session storage, to use later when sending requests to the API. 일부 인증 형태 (예: 쿠키 기반 인증)와 달리 브라우저는 후속 요청에 액세스 토큰을 자동으로 포함 하지 않습니다.Unlike some forms of authentication (such as cookie-based authentication), the browser will not automatically include the access token in subsequent requests. 응용 프로그램은 명시적으로이 작업을 수행 해야 합니다.The application must do so explicitly. 이것은 Csrf 취약성을 제한 하기 때문입니다.That's a good thing, because it limits CSRF vulnerabilities.

HTTP 요청:HTTP request:

POST https://localhost:44305/Token HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/
Content-Length: 68

grant_type=password&username=alice%40example.com&password=Password1!

요청에 사용자 자격 증명이 포함 되어 있는 것을 볼 수 있습니다.You can see that the request contains the user's credentials. 전송 계층 보안을 제공 하려면 HTTPS를 사용 해야 합니다.You must use HTTPS to provide transport layer security.

HTTP 응답:HTTP response:

HTTP/1.1 200 OK
Content-Length: 669
Content-Type: application/json;charset=UTF-8
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 01:22:36 GMT

{
  "access_token":"imSXTs2OqSrGWzsFQhIXziFCO3rF...",
  "token_type":"bearer",
  "expires_in":1209599,
  "userName":"alice@example.com",
  ".issued":"Wed, 01 Oct 2014 01:22:33 GMT",
  ".expires":"Wed, 15 Oct 2014 01:22:33 GMT"
}

가독성을 위해 JSON을 들여쓴 후 매우 긴 액세스 토큰을 자릅니다.For readability, I indented the JSON and truncated the access token, which is a quite long.

access_token, token_typeexpires_in 속성은 OAuth2 사양으로 정의 됩니다. 다른 속성 (userName, .issued.expires)은 참고용 으로만 사용 됩니다.The access_token, token_type, and expires_in properties are defined by the OAuth2 spec. The other properties (userName, .issued, and .expires) are just for informational purposes. TokenEndpoint 메서드에서/Providers/ApplicationOAuthProvider.cs 파일에 추가 속성을 추가 하는 코드를 찾을 수 있습니다.You can find the code that adds those additional properties in the TokenEndpoint method, in the /Providers/ApplicationOAuthProvider.cs file.

인증 된 요청 보내기Send an Authenticated Request

이제 전달자 토큰이 있으므로 API에 대 한 인증 된 요청을 수행할 수 있습니다.Now that we have a bearer token, we can make an authenticated request to the API. 요청에서 권한 부여 헤더를 설정 하 여이 작업을 수행 합니다.This is done by setting the Authorization header in the request. API 호출 단추를 다시 클릭 하 여이를 확인 합니다.Click the Call API button again to see this.

HTTP 요청:HTTP request:

GET https://localhost:44305/api/values/1 HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Authorization: Bearer imSXTs2OqSrGWzsFQhIXziFCO3rF...
X-Requested-With: XMLHttpRequest

HTTP 응답:HTTP response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 01:41:29 GMT
Content-Length: 27

"Hello, alice@example.com."

로그아웃Log Out

브라우저는 자격 증명이 나 액세스 토큰을 캐시 하지 않으므로 세션 저장소에서 토큰을 제거 하 여 토큰을 "잊어버린" 경우에만 로그 아웃 합니다.Because the browser does not cache the credentials or the access token, logging out is simply a matter of "forgetting" the token, by removing it from session storage:

self.logout = function () {
    sessionStorage.removeItem(tokenKey)
}

개별 계정 프로젝트 템플릿 이해Understanding the Individual Accounts Project Template

ASP.NET 웹 응용 프로그램 프로젝트 템플릿에서 개별 계정을 선택 하면 프로젝트에 다음 항목이 포함 됩니다.When you select Individual Accounts in the ASP.NET Web Application project template, the project includes:

  • OAuth2 권한 부여 서버입니다.An OAuth2 authorization server.
  • 사용자 계정을 관리 하기 위한 Web API 끝점A Web API endpoint for managing user accounts
  • 사용자 계정을 저장 하기 위한 EF 모델입니다.An EF model for storing user accounts.

다음은 이러한 기능을 구현 하는 기본 응용 프로그램 클래스입니다.Here are the main application classes that implement these features:

  • AccountController입니다.AccountController. 사용자 계정을 관리 하기 위한 Web API 끝점을 제공 합니다.Provides a Web API endpoint for managing user accounts. Register 작업은이 자습서에서 사용한 유일한 작업입니다.The Register action is the only one that we used in this tutorial. 클래스의 다른 메서드는 암호 재설정, 소셜 로그인 및 기타 기능을 지원 합니다.Other methods on the class support password reset, social logins, and other functionality.
  • /Models/IdentityModels.cs.에 정의 된 ApplicationUserApplicationUser, defined in /Models/IdentityModels.cs. 이 클래스는 멤버 자격 데이터베이스의 사용자 계정에 대 한 EF 모델입니다.This class is the EF model for user accounts in the membership database.
  • /App_Start/IdentityConfig에 정의 된 ApplicationUserManager이 클래스는 Usermanager 에서 파생 되 고 사용자 계정에 대 한 작업을 수행 합니다 (예: 새 사용자 만들기, 암호 확인 등), 데이터베이스에 대 한 변경 내용을 자동으로 유지 합니다.ApplicationUserManager, defined in /App_Start/IdentityConfig.cs This class derives from UserManager and performs operations on user accounts, such as creating a new user, verifying passwords, and so forth, and automatically persists changes to the database.
  • ApplicationOAuthProvider입니다.ApplicationOAuthProvider. 이 개체는 OWIN 미들웨어에 연결 하 고 미들웨어에 의해 발생 한 이벤트를 처리 합니다.This object plugs into the OWIN middleware, and processes events raised by the middleware. Oauthauthorizationserverprovider에서 파생 됩니다.It derives from OAuthAuthorizationServerProvider.

권한 부여 서버 구성Configuring the Authorization Server

StartupAuth.cs에서 다음 코드는 OAuth2 권한 부여 서버를 구성 합니다.In StartupAuth.cs, the following code configures the OAuth2 authorization server.

PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    // Note: Remove the following line before you deploy to production:
    AllowInsecureHttp = true
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);

TokenEndpointPath 속성은 권한 부여 서버 끝점에 대 한 URL 경로입니다.The TokenEndpointPath property is the URL path to the authorization server endpoint. 앱에서 전달자 토큰을 가져오는 데 사용 하는 URL입니다.That's the URL that app uses to get the bearer tokens.

Provider 속성은 OWIN 미들웨어에 연결 하 고 미들웨어에 의해 발생 한 이벤트를 처리 하는 공급자를 지정 합니다.The Provider property specifies a provider that plugs into the OWIN middleware, and processes events raised by the middleware.

앱에서 토큰을 받으려는 기본 흐름은 다음과 같습니다.Here is the basic flow when the app wants to get a token:

  1. 액세스 토큰을 가져오기 위해 앱은 ~/Token.에 요청을 보냅니다.To get an access token, the app sends a request to ~/Token.
  2. OAuth 미들웨어는 공급자에 대 한 GrantResourceOwnerCredentials를 호출 합니다.The OAuth middleware calls GrantResourceOwnerCredentials on the provider.
  3. 공급자는 ApplicationUserManager를 호출 하 여 자격 증명의 유효성을 검사 하 고 클레임 id를 만듭니다.The provider calls the ApplicationUserManager to validate the credentials and create a claims identity.
  4. 이 작업이 성공 하면 공급자는 토큰을 생성 하는 데 사용 되는 인증 티켓을 만듭니다.If that succeeds, the provider creates an authentication ticket, which is used to generate the token.

OAuth 미들웨어는 사용자 계정에 대 한 어떠한 정보도 알지 못합니다.The OAuth middleware doesn't know anything about the user accounts. 공급자는 미들웨어와 ASP.NET Identity 사이를 통신 합니다.The provider communicates between the middleware and ASP.NET Identity. 권한 부여 서버를 구현 하는 방법에 대 한 자세한 내용은 OWIN OAuth 2.0 Authorization server를 참조 하세요.For more information about implementing the authorization server, see OWIN OAuth 2.0 Authorization Server.

전달자 토큰을 사용 하도록 Web API 구성Configuring Web API to use Bearer Tokens

WebApiConfig.Register 메서드에서 다음 코드는 Web API 파이프라인에 대 한 인증을 설정 합니다.In the WebApiConfig.Register method, the following code sets up authentication for the Web API pipeline:

config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

Hostauthenticationfilter 클래스를 사용 하면 전달자 토큰을 사용 하 여 인증을 수행할 수 있습니다.The HostAuthenticationFilter class enables authentication using bearer tokens.

Config.suppressdefaulthostauthentication 메서드는 요청이 웹 api 파이프라인 (IIS 또는 OWIN 미들웨어)에 도달 하기 전에 발생 하는 모든 인증을 무시 하도록 웹 api에 지시 합니다.The SuppressDefaultHostAuthentication method tells Web API to ignore any authentication that happens before the request reaches the Web API pipeline, either by IIS or by OWIN middleware. 이러한 방식으로 Web API가 전달자 토큰만으로 인증하도록 제한할 수 있습니다.That way, we can restrict Web API to authenticate only using bearer tokens.

Note

특히 응용 프로그램의 MVC 부분은 쿠키에 자격 증명을 저장 하는 폼 인증을 사용할 수 있습니다.In particular, the MVC portion of your app might use forms authentication, which stores credentials in a cookie. 쿠키 기반 인증을 사용 하려면 위조 방지 토큰을 사용 하 여 CSRF 공격을 방지 해야 합니다.Cookie-based authentication requires the use of anti-forgery tokens, to prevent CSRF attacks. 웹 API가 위조 방지 토큰을 클라이언트에 보낼 수 있는 편리한 방법이 없기 때문에 웹 Api의 문제입니다.That's a problem for web APIs, because there is no convenient way for the web API to send the anti-forgery token to the client. (이 문제에 대 한 자세한 배경 정보는 WEB API에서 CSRF 공격 방지를 참조 하세요.) Config.suppressdefaulthostauthentication 를 호출 하면 Web API가 쿠키에 저장 된 자격 증명의 csrf 공격에 취약 하지 않습니다.(For more background on this issue, see Preventing CSRF Attacks in Web API.) Calling SuppressDefaultHostAuthentication ensures that Web API is not vulnerable to CSRF attacks from credentials stored in cookies.

클라이언트에서 보호 된 리소스를 요청할 때 웹 API 파이프라인에서 발생 하는 작업은 다음과 같습니다.When the client requests a protected resource, here is what happens in the Web API pipeline:

  1. Hostauthentication 필터는 OAuth 미들웨어를 호출 하 여 토큰의 유효성을 검사 합니다.The HostAuthentication filter calls the OAuth middleware to validate the token.
  2. 미들웨어는 토큰을 클레임 id로 변환 합니다.The middleware converts the token into a claims identity.
  3. 이 시점에서 요청은 인증 되지만 권한이 부여되지 않습니다.At this point, the request is authenticated but not authorized.
  4. 권한 부여 필터는 클레임 id를 검사 합니다.The authorization filter examines the claims identity. 클레임에서 해당 리소스에 대 한 사용자 권한을 부여 하는 경우 요청에 권한이 부여 됩니다.If the claims authorize the user for that resource, the request is authorized. 기본적으로 [권한 부여] 특성은 인증 된 모든 요청에 대 한 권한을 부여 합니다.By default, the [Authorize] attribute will authorize any request that is authenticated. 그러나 역할 또는 다른 클레임을 통해 권한을 부여할 수 있습니다.However, you can authorize by role or by other claims. 자세한 내용은 WEB API의 인증 및 권한 부여를 참조 하세요.For more information, see Authentication and Authorization in Web API.
  5. 이전 단계가 성공적으로 수행 되 면 컨트롤러는 보호 된 리소스를 반환 합니다.If the previous steps are successful, the controller returns the protected resource. 그렇지 않으면 클라이언트에서 401 (권한 없음) 오류를 수신 합니다.Otherwise, the client receives a 401 (Unauthorized) error.

추가 리소스Additional Resources