ASP.NET WebAPI2第007天_實踐Authentication以及Authorization_OAuth概述

 
在.net web api 專案若要去實踐Authentication以及Authorization
預設專案配置會涉及到asp.net identity的使用
而identity又會涉及到Entity Framework的使用
這些在過去的學習部落格篇章都有筆記到

因此不會特別在贅述

稍微介紹到一個詞 Oauth

OAuth是一個開發標準(Open Standard)用來處理有關「授權」(Authorization)相關的行為。
有分為OAuth 1.0跟OAuth 2.0
OAuth 2.0是OAuth協定的下一版本,但不向下相容OAuth 1.0。
OAuth 2.0關注客戶端開發者的簡易性,同時為Web應用、桌面應用、手機和智慧型裝置提供專門的認證流程。


OAuth 允許讓第三方應用存取該使用者在某一網站或平台(Google,Facebook,Twitter,Apple)
上儲存的私密的資源(如相片,影片,聯絡人列表),
無需將使用者名稱和密碼提供給第三方應用


更白話說就是透過第三方登入
Sign in with Google
Sign in with Facebook....




在OAuth 2 
具有四種角色
Resource Owner(資料擁有者) : 你(我們自己)、user ,也可能直接是Client (應用)不是人
Client(應用程式) : User授權給第三方的應用程式,例如:蝦皮、instagram、FB心理測驗遊戲、手機APP。
Authorization Server(總管授權Server) : 可能是一個網頁要讓User本人授權取回的是一個Grant(授權狀)而非Token。
Resource Server(Client從這拿資料也就是API) : 通常一般情況跟Authorization Server同來源

規範了四個核發(Grant)類型流程
  1. Authorization Code(授權碼) Grant Type Flow
  2. Implicit Grant Type Flow
  3. Resource Owner Password Credentials Grant Type Flow
  4. Client Credentials Grant Type Flow

四個核發流程是運用在不同的場合,
Authorization Code 核發流程的安全性最高,然而流程最繁複,實作起來的步驟也多。
Implicit 核發流程是其簡化版本,然而安全性低了一些(曝露了 Acccess Token)。
Password Credentials 核發流程則適用於對於密碼在自己控管中的場合,統一管理授權可採用 。
Client Credentials 核發流程適用於不涉及使用者的內部伺服器間授權管理,或者內部完全可信任的客戶端 。

這四種核發(授予)模式可根據以下幾個指標去判定適用何種場合

1.存取token(Access token)由誰持有
存放在固定機器 or 給User持有


2.客戶的型態為何?
網站應用 or 行動裝置APP


3.客戶與資源伺服器是 第一方 還 第三方 關係
3-1.Instagram想讓使用者能使用Facebook身份登入,
由於Instagram與Facebook是同公司的兩個服務,兩者是第一方關係。

3-2.Spotify想讓使用者能使用Facebook身份登入,
由於Spotify與Facebook是不同公司,兩者是第三方關係。

更多Oauth的細節可能無法一時全介紹
只要知道一個核心概念就是全新一套避免直接提供帳密而用token替代的授權機制

大致上的流程以Sign in with Google為例

Step 1:授權請求
Client User點擊第三方應用程式「 以 Google 登入 」,
此時,該應用程式就會向使用者(即資源擁有者 Resource owner )索取資料使用的授權請求。

Step 2:授權許可
Client User會收到一個授權請求,若他點擊同意授權,該應用程式則會收到一個授權許可,
有點類似確認是否真的是你本人才授權該應用,代表他願意讓應用程式代為向 Google 的授權伺服器 (Authorization server) 進行溝通。

Step 3:Access Token 請求
由於已得到使用者本人的授權許可,因此,該應用程式會憑藉授權許可,主動向 Google 的授權伺服器發送 Access Token 請求,接著 Google 會進行資料比對,如 用戶端 ID、用戶端 密碼,確認應用程式的合法性。

Step 4:Access Token 簽發
Google 的授權伺服器,若資料成功比對後,則會發給該應用程式一個 Access Token,讓它接下來能夠透過這個 Access Token 向 Google 資源伺服器 (Resource Server)索取所需要的資料。

Step 5:資料索取
此時,該應用程式,不僅透過 Access Token 認證身份,同時,也會向 Google 資源伺服器提出資料的請求。

Step 6:資料回傳
最後,Google 資源伺服器會驗證 Access Token,若確認無誤,則會將使用者被保護的資料授權給該應用程式來使用,進而完成透過 Google 完成第三方登入應用程式的功能。





新增一個全新.net web專案(for web api)


驗證改為選擇個別帳戶



預設產出的專案


~\MyWebAPI2_Oauth\Controllers\ValuesController.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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace MyWebAPI2_Oauth.Controllers
{
    [Authorize]
    public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
    }
}




~\MyWebAPI2_Oauth\Controllers\AccountController.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
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using MyWebAPI2_Oauth.Models;
using MyWebAPI2_Oauth.Providers;
using MyWebAPI2_Oauth.Results;

namespace MyWebAPI2_Oauth.Controllers
{
    [Authorize]
    [RoutePrefix("api/Account")]
    public class AccountController : ApiController
    {
        private const string LocalLoginProvider = "Local";
        private ApplicationUserManager _userManager;

        public AccountController()
        {
        }

        public AccountController(ApplicationUserManager userManager,
            ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
        {
            UserManager = userManager;
            AccessTokenFormat = accessTokenFormat;
        }

        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }

        public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }

        // GET api/Account/UserInfo
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("UserInfo")]
        public UserInfoViewModel GetUserInfo()
        {
            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

            return new UserInfoViewModel
            {
                Email = User.Identity.GetUserName(),
                HasRegistered = externalLogin == null,
                LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
            };
        }

        // POST api/Account/Logout
        [Route("Logout")]
        public IHttpActionResult Logout()
        {
            Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
            return Ok();
        }

        // GET api/Account/ManageInfo?returnUrl=%2F&generateState=true
        [Route("ManageInfo")]
        public async Task<ManageInfoViewModel> GetManageInfo(string returnUrl, bool generateState = false)
        {
            IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

            if (user == null)
            {
                return null;
            }

            List<UserLoginInfoViewModel> logins = new List<UserLoginInfoViewModel>();

            foreach (IdentityUserLogin linkedAccount in user.Logins)
            {
                logins.Add(new UserLoginInfoViewModel
                {
                    LoginProvider = linkedAccount.LoginProvider,
                    ProviderKey = linkedAccount.ProviderKey
                });
            }

            if (user.PasswordHash != null)
            {
                logins.Add(new UserLoginInfoViewModel
                {
                    LoginProvider = LocalLoginProvider,
                    ProviderKey = user.UserName,
                });
            }

            return new ManageInfoViewModel
            {
                LocalLoginProvider = LocalLoginProvider,
                Email = user.UserName,
                Logins = logins,
                ExternalLoginProviders = GetExternalLogins(returnUrl, generateState)
            };
        }

        // POST api/Account/ChangePassword
        [Route("ChangePassword")]
        public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
                model.NewPassword);
            
            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST api/Account/SetPassword
        [Route("SetPassword")]
        public async Task<IHttpActionResult> SetPassword(SetPasswordBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST api/Account/AddExternalLogin
        [Route("AddExternalLogin")]
        public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);

            AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);

            if (ticket == null || ticket.Identity == null || (ticket.Properties != null
                && ticket.Properties.ExpiresUtc.HasValue
                && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
            {
                return BadRequest("外部登入失敗。");
            }

            ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);

            if (externalData == null)
            {
                return BadRequest("外部登入已與帳戶相關聯。");
            }

            IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
                new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST api/Account/RemoveLogin
        [Route("RemoveLogin")]
        public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result;

            if (model.LoginProvider == LocalLoginProvider)
            {
                result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
            }
            else
            {
                result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
                    new UserLoginInfo(model.LoginProvider, model.ProviderKey));
            }

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // GET api/Account/ExternalLogin
        [OverrideAuthentication]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
        [AllowAnonymous]
        [Route("ExternalLogin", Name = "ExternalLogin")]
        public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
        {
            if (error != null)
            {
                return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
            }

            if (!User.Identity.IsAuthenticated)
            {
                return new ChallengeResult(provider, this);
            }

            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

            if (externalLogin == null)
            {
                return InternalServerError();
            }

            if (externalLogin.LoginProvider != provider)
            {
                Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
                return new ChallengeResult(provider, this);
            }

            ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
                externalLogin.ProviderKey));

            bool hasRegistered = user != null;

            if (hasRegistered)
            {
                Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
                
                 ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
                    OAuthDefaults.AuthenticationType);
                ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
                    CookieAuthenticationDefaults.AuthenticationType);

                AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
                Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
            }
            else
            {
                IEnumerable<Claim> claims = externalLogin.GetClaims();
                ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
                Authentication.SignIn(identity);
            }

            return Ok();
        }

        // GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true
        [AllowAnonymous]
        [Route("ExternalLogins")]
        public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false)
        {
            IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes();
            List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>();

            string state;

            if (generateState)
            {
                const int strengthInBits = 256;
                state = RandomOAuthStateGenerator.Generate(strengthInBits);
            }
            else
            {
                state = null;
            }

            foreach (AuthenticationDescription description in descriptions)
            {
                ExternalLoginViewModel login = new ExternalLoginViewModel
                {
                    Name = description.Caption,
                    Url = Url.Route("ExternalLogin", new
                    {
                        provider = description.AuthenticationType,
                        response_type = "token",
                        client_id = Startup.PublicClientId,
                        redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
                        state = state
                    }),
                    State = state
                };
                logins.Add(login);
            }

            return logins;
        }

        // POST api/Account/Register
        [AllowAnonymous]
        [Route("Register")]
        public async Task<IHttpActionResult> Register(RegisterBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

            IdentityResult result = await UserManager.CreateAsync(user, model.Password);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST api/Account/RegisterExternal
        [OverrideAuthentication]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("RegisterExternal")]
        public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var info = await Authentication.GetExternalLoginInfoAsync();
            if (info == null)
            {
                return InternalServerError();
            }

            var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

            IdentityResult result = await UserManager.CreateAsync(user);
            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            result = await UserManager.AddLoginAsync(user.Id, info.Login);
            if (!result.Succeeded)
            {
                return GetErrorResult(result); 
            }
            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && _userManager != null)
            {
                _userManager.Dispose();
                _userManager = null;
            }

            base.Dispose(disposing);
        }

        #region Helper

        private IAuthenticationManager Authentication
        {
            get { return Request.GetOwinContext().Authentication; }
        }

        private IHttpActionResult GetErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                return InternalServerError();
            }

            if (!result.Succeeded)
            {
                if (result.Errors != null)
                {
                    foreach (string error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }

                if (ModelState.IsValid)
                {
                    // 沒有要傳送的 ModelState 錯誤,因此僅傳回空的 BadRequest。
                    return BadRequest();
                }

                return BadRequest(ModelState);
            }

            return null;
        }

        private class ExternalLoginData
        {
            public string LoginProvider { get; set; }
            public string ProviderKey { get; set; }
            public string UserName { get; set; }

            public IList<Claim> GetClaims()
            {
                IList<Claim> claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));

                if (UserName != null)
                {
                    claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
                }

                return claims;
            }

            public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
            {
                if (identity == null)
                {
                    return null;
                }

                Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);

                if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
                    || String.IsNullOrEmpty(providerKeyClaim.Value))
                {
                    return null;
                }

                if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
                {
                    return null;
                }

                return new ExternalLoginData
                {
                    LoginProvider = providerKeyClaim.Issuer,
                    ProviderKey = providerKeyClaim.Value,
                    UserName = identity.FindFirstValue(ClaimTypes.Name)
                };
            }
        }

        private static class RandomOAuthStateGenerator
        {
            private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();

            public static string Generate(int strengthInBits)
            {
                const int bitsPerByte = 8;

                if (strengthInBits % bitsPerByte != 0)
                {
                    throw new ArgumentException("strengthInBits 必須平均地被 8 除盡。", "strengthInBits");
                }

                int strengthInBytes = strengthInBits / bitsPerByte;

                byte[] data = new byte[strengthInBytes];
                _random.GetBytes(data);
                return HttpServerUtility.UrlTokenEncode(data);
            }
        }

        #endregion
    }
}


在此嘗試GET方式存取API https://localhost:44354/api/values
當運行起來會發現有出現"已拒絕此要求的授權"的錯誤訊息





這邊我們會需要註冊一個新帳戶才能進行API存取

這裡準備RegisterModel所需欄位的json資料透過post呼叫
/api/Account/Register做註冊







再到檢視->SQL Server物件總管看就能看到新增的一筆註冊用戶資料了





在我們的
~\App_Start\Startup.Auth.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
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Microsoft.Owin.Security.OAuth;
using Owin;
using MyWebAPI2_Oauth.Providers;
using MyWebAPI2_Oauth.Models;

namespace MyWebAPI2_Oauth
{
    public partial class Startup
    {
        public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

        public static string PublicClientId { get; private set; }

        // 如需設定驗證的詳細資訊,請瀏覽 https://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            // 設定資料庫內容和使用者管理員以針對每個要求使用單一執行個體
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            // 讓應用程式使用 Cookie 儲存已登入使用者的資訊
            // 並使用 Cookie 暫時儲存使用者利用協力廠商登入提供者登入的相關資訊;
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            // 設定 OAuth 基礎流程的應用程式
            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                // 在生產模式中設定 AllowInsecureHttp = false
                AllowInsecureHttp = true
            };

            // 讓應用程式使用 Bearer 權杖驗證使用者
            app.UseOAuthBearerTokens(OAuthOptions);

            // 註銷下列各行以啟用利用協力廠商登入提供者登入
            //app.UseMicrosoftAccountAuthentication(
            //    clientId: "",
            //    clientSecret: "");

            //app.UseTwitterAuthentication(
            //    consumerKey: "",
            //    consumerSecret: "");

            //app.UseFacebookAuthentication(
            //    appId: "",
            //    appSecret: "");

            //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
            //{
            //    ClientId = "",
            //    ClientSecret = ""
            //});
        }
    }
}

TokenEndpointPath 預先指定要取得token的存取路徑 /token

在此利用post並設置username , password , grant_type來獲取token

獲得的token與時效資訊


1
2
3
4
5
6
7
8
{
    "access_token": "kpUftta22l_14Yzn8q-WATFRdV2USA2xp5ptuSGvUEOOIqIem-AQiCwAy3aKYOKb2UJNtnLz_Q3L2UHlt68aXF_6SnikK_lqyulQOOgEzTh1uREAC_aC5RaF_oboKrfL5s-stSmRIGguSP1W7Wi_CQJ-_xVxxd79H3vCpHSLGgK1w1RHTxXSTm_3oXjEYLsJWfE7djDPRnsQd5Y_oCqyXUIV8Y1dCQQpqJ2f5T0FvYgCEdx5hVK1DY-YTA3nYr72YJSXbaUuL6FRQWDCmoc9OUYWBvJlyJRsMyj1SmNKrlzk_kzByBiBXPX3SToCbfme4aCCFo8S0Ekm94cfJRC_erVh4WYX6-EevKULRVKCYI-qiEZJlrmyn_Vhk7DLWTRFMvgW_ed1eooC_sPCJ44yRIG_3qSzjrCIoJmTI0Haunafhycl_5CQYgFDUBT7_MvUNDoMf1KIr7480yF92f0-4w_4dyQuIwX4Ene3dxy5ROSPKA27wYohlRg9OBRB0nmN",
    "token_type": "bearer",
    "expires_in": 1209599,
    "userName": "abc321@gmail.com",
    ".issued": "Tue, 28 Dec 2021 07:56:00 GMT",
    ".expires": "Tue, 11 Jan 2022 07:56:00 GMT"
}



再次存取values API時
就需要設置Header 鍵值
Authorization:bearer kpUftta22l_14Yzn8q-WATFRdV2USA2xp5ptuSGvUEOOIqIem-AQiCwAy3aKYOKb2UJNtnLz_Q3L2UHlt68aXF_6SnikK_lqyulQOOgEzTh1uREAC_aC5RaF_oboKrfL5s-stSmRIGguSP1W7Wi_CQJ-_xVxxd79H3vCpHSLGgK1w1RHTxXSTm_3oXjEYLsJWfE7djDPRnsQd5Y_oCqyXUIV8Y1dCQQpqJ2f5T0FvYgCEdx5hVK1DY-YTA3nYr72YJSXbaUuL6FRQWDCmoc9OUYWBvJlyJRsMyj1SmNKrlzk_kzByBiBXPX3SToCbfme4aCCFo8S0Ekm94cfJRC_erVh4WYX6-EevKULRVKCYI-qiEZJlrmyn_Vhk7DLWTRFMvgW_ed1eooC_sPCJ44yRIG_3qSzjrCIoJmTI0Haunafhycl_5CQYgFDUBT7_MvUNDoMf1KIr7480yF92f0-4w_4dyQuIwX4Ene3dxy5ROSPKA27wYohlRg9OBRB0nmN























Ref:















【開放銀行特別報導】金融個資存取如何更安全?開放銀行將引進OAuth 2委任授權架構

OpenID Connect 是什麼?

電影欣賞《OAuth 2.0 and OpenID Connect (in plain English)》

「筆記」- 何謂 OAuth?Google 實例說明 OAuth 處理流程


留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header