天天看點

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

授權碼模式定義

通過用戶端的背景伺服器,與“服務提供商”的認證伺服器進行認證。

1、使用者通路用戶端,後者将前者導向認證伺服器。

2、使用者選擇是否給予用戶端授權。

3、假設使用者給予授權,認證伺服器首先生成一個授權碼,并傳回給使用者,認證伺服器将使用者導向用戶端事先指定的"重定向URI"(redirection URI),同時附上一個授權碼。

4、用戶端收到授權碼,附上早先的"重定向URI",向認證伺服器申請令牌。這一步是在用戶端的背景的伺服器上完成的,對使用者不可見。

5、認證伺服器核對了授權碼和重定向URI,确認無誤後,向用戶端發送通路令牌(access token)和更新令牌(refresh token)。

6、Client拿着access token去通路Resource資源

授權碼模式的工作流程圖

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

圖 1 (網上搜到的授權碼工作流程圖說明)

之前看上邊的流程圖,看了不下10遍,還是搞不懂,這個圖真心畫的不好了解!

我們一步步來,AuthorizationServer與ResourceServer還是用之前的項目

建立項目:AuthorizationCodeGrant

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

HomeController.cs也簡單

     public ActionResult Index()             {                 ViewBag.AccessToken = Request.Form["AccessToken"] ?? "";                 ViewBag.RefreshToken = Request.Form["RefreshToken"] ?? "";                 ViewBag.Action = "";                 ViewBag.ResourceResponse = "";                 var authorizationServerUri = new Uri("http://localhost:8270/");                 var authorizationServer = new AuthorizationServerDescription                 {                     AuthorizationEndpoint = new Uri(authorizationServerUri, "OAuth/Authorize"),                     TokenEndpoint = new Uri(authorizationServerUri, "OAuth/Token")                 };                 // 重新整理AccessToken                 var client = new WebServerClient(authorizationServer, "123456", "abcdef");                 if (string.IsNullOrEmpty(ViewBag.AccessToken))                 {                     var authorizationState = client.ProcessUserAuthorization(Request);                     if (authorizationState != null)                     {                         ViewBag.AccessToken = authorizationState.AccessToken;                         ViewBag.RefreshToken = authorizationState.RefreshToken;                         ViewBag.Action = Request.Path;                     }                 }                 // 授權申請                 if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestAuthorize")))                 {                     var grantRequest = client.PrepareRequestUserAuthorization(new[] { "scopes1", "scopes2" });                     grantRequest.Send(HttpContext);                     Response.End();                 }                 // 申請資源                 if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestResource")))                 {                     var resourceServerUri = new Uri("http://localhost:8001/");                     var resourceRequest = new HttpClient(client.CreateAuthorizingHandler(ViewBag.AccessToken));                     ViewBag.ResourceResponse = resourceRequest.GetStringAsync(new Uri(resourceServerUri, "api/Values")).Result;                 }                 return View();             }      

Index.cshtml

<!DOCTYPE html>     <html xmlns="http://www.w3.org/1999/xhtml">     <head>         <title>Authorization Code Grant Client</title>     </head>     <body>         <form id="form1" action="@ViewBag.Action" method="POST">             <div>                 <input id="AccessToken" name="AccessToken" value="@ViewBag.AccessToken" type="hidden" />                 <input id="Authorize" name="btnRequestAuthorize" value="向認證伺服器索要授權" type="submit" />                 <input id="Resource" name="btnRequestResource" value="通路資源(Resource)" type="submit" />             </div>             <div>@ViewBag.ResourceResponse</div>         </form>     </body>     </html>      

運作項目  

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

授權過程

點選“向認證服務索要授權”,根據HomeController.cs檔案的設定,頁面預計會跳轉到"http://localhost:8270/OAuth/Authorize"

是以我們需要在認證服務中新增處理授權碼模式的處理邏輯

在項目AuthorizationServer中新增OAuthController.cs、Authorize.cshtml

   public class OAuthController : Controller         {             public ActionResult Authorize()             {                 if (Response.StatusCode != 200)                 {                     return View("AuthorizeError");                 }                 var authentication = HttpContext.GetOwinContext().Authentication;                 var ticket = authentication.AuthenticateAsync("Application").Result;                 var identity = ticket != null ? ticket.Identity : null;                 if (identity == null)                 {                     authentication.Challenge("Application");                     return new HttpUnauthorizedResult(); //使用者登入憑證失效就報401錯誤,并且跳轉至AccountController中的Login中                 }                 ViewBag.IdentityName = identity.Name;                 ViewBag.Scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');                 if (Request.HttpMethod == "POST")                 {               // 點選btnGrant就确認授權,傳回token等資訊                     if (!string.IsNullOrEmpty(Request.Form.Get("btnGrant")))                     {                         identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);                         foreach (var scope in ViewBag.Scopes)                         {                             identity.AddClaim(new Claim("urn:oauth:scope", scope));                         }                         authentication.SignIn(identity);                     }                     if (!string.IsNullOrEmpty(Request.Form.Get("btnOtherLogin")))                     {                         authentication.SignOut("Application");                         authentication.Challenge("Application");                         return new HttpUnauthorizedResult();                     }                 }                 return View();             }         }      
<!DOCTYPE html>     <html xmlns="http://www.w3.org/1999/xhtml">     <head>         <title>Authorize</title>     </head>     <body>         <h1>認證頁面</h1>         <form method="POST">             <p>登入使用者:@ViewBag.IdentityName</p>             <p>第三方應用需要你給他開放以下權限</p>             <ul>                 @foreach (var scope in ViewBag.Scopes)                 {                     <li>@scope</li>                 }             </ul>             <p>                 <input type="submit" name="btnGrant" value="确認授權" />                 <input type="submit" name="btnOtherLogin" value="以不同使用者登入" />             </p>         </form>     </body>     </html>      
   public class AccountController : Controller         {             public ActionResult Login()             {                 var authentication = HttpContext.GetOwinContext().Authentication;                 if (Request.HttpMethod == "POST")                 {                     // 預設使用者登入成功              // 生産環境需要單獨整合第三方登入資訊                     var username = Request.Form["username"];                     authentication.SignIn(                         new AuthenticationProperties { IsPersistent = true },                         new ClaimsIdentity(                             new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, username) }, "Application"));                 }                 return View();             }             public ActionResult Logout()             {                 return View();             }         }      

運作項目,成功跳轉至認證登入頁面

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

點選登入,此時url位址為:

http://localhost:8270/OAuth/Authorize?client_id=123456&redirect_uri=http%3A%2F%2Flocalhost%3A4825%2F&state=IUKeWFTR1HKi4hlzKOOPgw&scope=scopes1%20scopes2&response_type=code

7.1 client_id為用戶端ID,即之前我們在AuthorizationCodeGrant項目設定的clientID

7.2 redirect_uri、state為之前登入時就确定的值

7.3 scope為使用者确定授權的範圍

7.4 response_type=code,即指定為授權碼模式

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

确認授權

此時url有變化:http://localhost:4825/?code=efab38fc30c741a198b20663ec60869a36c6b25ff21f4c9986bcb9c9ae8d20eb&state=tjB9jXhNiHvIr4Ko9VhEkw

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

注意:這一步會會預設擷取Token

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)
asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

點選通路資源

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

完全能夠對上;

url中的code即認證服務傳回的授權碼,之後Client請求Token會用這個code來交換

這個就是授權碼模式的特色的地方了

asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)

 自此,整個授權碼模式已經完畢了哦

asp.net權限認證系列

  1. asp.net權限認證:Forms認證
  2. asp.net權限認證:HTTP基本認證(http basic)
  3. asp.net權限認證:Windows認證
  4. asp.net權限認證:摘要認證(digest authentication)
  5. asp.net權限認證:OWIN實作OAuth 2.0 之用戶端模式(Client Credential)
  6. asp.net權限認證:OWIN實作OAuth 2.0 之密碼模式(Resource Owner Password Credential)
  7. asp.net權限認證:OWIN實作OAuth 2.0 之授權碼模式(Authorization Code)
  8. asp.net權限認證:OWIN實作OAuth 2.0 之簡化模式(Implicit)

繼續閱讀