2019. 11. 18. 15:30

이 시리즈의 종합편???

이라고 하기에는 좀 그렇고 합본 정도입니다.


지금까지 샘플은 인증서버와 API 서버가 따로 있는 것을 가정하여 만들어져 있었습니다.

이것은 인증서버를 하나만 두고 여러 API서버를 연동해서 사용할 수 있기 때문입니다.


하지만!

인증서버 하나에 API서버가 하나라면 굳이 따로 만들 필요가 없죠.

이번에는 인증서버와 API서버를 합치도록 하겠습니다.




이전 포스팅에서 여러 번 다뤘던 내용이므로 이번 포스팅은 대부분 링크로 대체합니다.


1. 프로젝트 세팅
새 프로젝트를 만듭니다.

프로젝트는 생성 옵션은

닷넷 코어 2.2

웹 응용프로그램

빈 프로젝트

입니다.


1-1. 'IdentityServer4' 설치

누겟에서 'IdentityServer4'를 찾아 설치합니다.

우리는 Core 2.2 가 기준이라 2.x 버전을 설치해야 합니다.


누겟에서 'IdentityServer4.AccessTokenValidation' 찾아 설치합니다.

우리는 Core 2.2 가 기준이라 2.x 버전을 설치해야 합니다.



1-2. html 세팅
빈 프로젝트는 아무것도 없기 때문에 html을 읽을 수 있도록 세팅합니다.
참고 : [ASP.NET Core] 빈 프로젝트 세팅 (1) - 'index.html'을 시작페이지로 설정하기


여기에 'JQuery'의 CDN 주소를 추가합니다.

1) 토큰을 요청하는 함수

2) 토큰 갱신을 요청하는 함수

3) API를 요청하는 함수


이렇게 3개의 함수를 추가합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
 
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"
            integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
            crossorigin="anonymous"></script>
 
    <script>
        var sUrl = "https://localhost:44350";
        var access_token = "";
        var refresh_token = "";
 
        /** 토큰 요청 */
        function CallToken()
        {
            $.ajax({
                type: "POST"
                , url: sUrl + "/connect/token"
                , data: {
                    "grant_type""password"
                    , "client_id""resourceownerclient"
                    , "client_secret""dataEventRecordsSecret"
                    , "scope""dataEventRecords offline_access"
                    , "username""raphael"
                    , "password""raphael"
                }
                , dataType: "json"
                , success: function (result) {
                    console.log(result);
                    access_token = result.access_token;
                    refresh_token = result.refresh_token;
                }
            });
        }
 
        /** 액세스 토큰 갱신 */
        function RefreshToAccess()
        {
            $.ajax({
                type: "POST"
                , url: sUrl + "/connect/token"
                , data: {
                    "grant_type""refresh_token"
                    , "client_id""resourceownerclient"
                    , "client_secret""dataEventRecordsSecret"
                    , "scope""dataEventRecords offline_access"
                    , "refresh_token" : refresh_token
                }
                , dataType: "json"
                , success: function (result) {
                    console.log(result);
                    access_token = result.access_token;
                    refresh_token = result.refresh_token;
                }
            });
        }
 
        /** API 호출 */
        function CallValues()
        {
            $.ajax({
                type: "GET"
                
                , url: sUrl + "/api/values"
                , headers: {
                    "authorization""Bearer " + access_token
                }
                , dataType: "json"
                , data: {
                }
                
                , success: function (result) {
                    console.log(result);
                }
            });
        }
    </script>
</head>
<body>
    이 서버는 인증만 가능합니다.
</body>
</html>
cs



1-3. 'WebAPI' 설정
'WebAPI'도 설정해 줍니다

참고 : [ASP.NET Core 2] 빈 프로젝트 세팅 (2) - 'WebAPI' 설정



'Controllers'폴더를 만들고 'ValuesController'를 추가합니다.

아래와 같이 작성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[Route("api/[controller]")]
[ApiController]
//OAuth2 인증 설정 [Authorize]
public class ValuesController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1""value2" };
    }
 
    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        return "value";
    }
 
    // POST api/values
    [HttpPost]
    public void Post([FromBody] string value)
    {
    }
 
    // PUT api/values/5
    [HttpPut("{id}")]
    public void Put(int id, [FromBody] string value)
    {
    }
 
    // DELETE api/values/5
    [HttpDelete("{id}")]
    public void Delete(int id)
    {
    }
}
cs



2. 서버 설정
'IdentityServer4'폴더를 만들고 'Config.cs'를 만들어 줍니다.


이전 글을 참고하여 'Config.cs'와 'UserServices'폴더의 클래스를 만듭니다.

참고 : [ASP.NET Core 2] OAuth2 인증에서 사용까지 (3) - 'IdentityServer'의 리플레시 토큰(Refresh Token) 사용하기


이전에 만들어놓은 코드가 있다면 'Config.cs'와 'UserServices'는 통으로 복사해서 사용해도 됩니다.


'IdentityServer' 미들웨어 기능 활성화

'Startup.cs'에 이전 글을 참고하여 'ConfigureServices'와 'Configure'를 수정합니다.

참고 : [ASP.NET Core 2] OAuth2 인증에서 사용까지 (3) - 'IdentityServer'의 리플레시 토큰(Refresh Token) 사용하기



3. 'WebAPI' 세팅
'Startup.cs'에 이전 글을 참고하여 'ConfigureServices'와 'Configure'를 수정합니다.

참고 : [ASP.NET Core 2] OAuth2 인증에서 사용까지 (2) - 'IdentityServer'를 이용하여 'OAuth2' 인증 받기



4. 완성된 'Startup.cs'

이 두 가지를 합친 'Startup.cs'입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
 
    public IConfiguration Configuration { get; }
 
    /// <summary>
    /// This method gets called by the runtime.
    /// Use this method to add services to the container.
    /// </summary>
    /// <param name="services"></param>
    public void ConfigureServices(IServiceCollection services)
    {
        //7. OAuth2 미들웨어(IdentityServer) 설정
        //AddCustomUserStore : 앞에서 만든 확장메소드를 추가
        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            //.AddSigningCredential()
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())
            .AddCustomUserStore();
 
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
 
        //인증 요청 정보
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(o =>
        {
            o.Audience = "apiApp";
 
            //인증서버의 주소
            o.Authority = "https://localhost:44350";
            o.RequireHttpsMetadata = false;
            //인증서버에서 선언한 권한
            o.Audience = "dataEventRecords";
        });
    }
 
    /// <summary>
    /// This method gets called by the runtime.
    /// Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            //HSTS 사용
            //The default HSTS value is 30 days.
            //You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
 
        //09. OAuth2 미들웨어(IdentityServer) CROS 접근 권한 문제
        //app.UseCors(options =>
        //{
        //    //전체 허용
        //    options.AllowAnyOrigin();
        //});
        //OAuth2 미들웨어(IdentityServer) 설정
        app.UseIdentityServer();
 
 
        //8. 프로젝트 미들웨어 기능 설정
        //웹사이트 기본파일 읽기 설정
        app.UseDefaultFiles();
        //wwwroot 파일읽기
        app.UseStaticFiles();
        //http요청을 https로 리디렉션합니다.
        //https를 허용하지 않았다면 제거 합니다.
        //https://docs.microsoft.com/ko-kr/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.0&tabs=visual-studio
        app.UseHttpsRedirection();
 
        //인증 요청
        app.UseAuthentication();
        //에러가 났을때 Http 상태코드를 전달하기위한 설정
        app.UseStatusCodePages();
 
        app.UseMvc();
    }
}
cs



5. 테스트하기

html을 만들어놨으므로 함수만 호출해주면 됩니다.


1) 'CallToken()'를 호출해 봅시다.

2) 넘어온 엑세스 토큰과 리플레시 토큰을 저장합니다.

3) 'CallValues()'를 호출하여 API를 호출합니다.

4) 'RefreshToAccess()'를 호출하여 액세스 토큰을 갱신 할 수 있습니다.



마무리

완성된 샘플 : Github - OAuth2Sample/OAuth2Sample/Auth_WebAPI/


이제 인증서버의 기본적인 사용 방법은 모두 끝났습니다.

'IdentityServer'에 대한 심화학습은 계획되어 있지 않습니다만......

필요하면 다시 오겠습니다. ㅎㅎㅎㅎㅎ

댓글 작성

이름
패스워드
홈페이지
비밀글