.NET 雲原生架構師訓練營(Identity Server)--學習筆記

MingsonZheng發表於2021-07-01

目錄

  • OAuth 2.0
  • OpenID Connect
  • QuickStart

OAuth 2.0

  • 概念
  • 過程
  • 通訊
  • 元件
  • 示例程式碼

概念

OAuth 2.0 是一個授權協議,它允許軟體應用代表(而不是充當)資源擁有者去訪問資源擁有者的資源(如何讓一個系統元件獲取另一個系統元件的訪問許可權)

  • 受保護的資源:是資源擁有者有許可權訪問的元件
  • 資源擁有者:有權訪問 API,並能將 API 訪問許可權委託出去
  • 客戶端:凡是使用了受保護資源上的 API,都是客戶端

過程

通訊

元件

  • 訪問令牌 token
  • 許可權範圍 scope
  • 重新整理令牌 refresh token
  • 授權許可 grant_type
grant_type 授權方式 授權前置條件 使用通訊通道 說明
authorization_code/PKCE 授權碼模式 授權碼 前端/後端 客戶端通過code在後端與授權伺服器進行互動獲取令牌
implict(不建議使用) 簡化模式
password(不建議使用) 密碼模式 使用者名稱/密碼 後端 在客戶端輸入使用者名稱和密碼,由客戶端向授權伺服器獲取令牌
client_credentials 客戶端模式 後端
device_code 裝置碼
refresh_token 重新整理token 用refresh_token來換取新的token

授權碼模式

  1. 第三方應用首先向服務提供商申請 client_id 應用唯一標識、Client_secret 金鑰,用於後續獲取令牌時提供身份校驗

  2. 申請授權碼:此時要提供預分配好的 client_id 標識來源,提供 scope 標識要申請的許可權,提供 redirect_uri 標識授權完畢後要回跳的第三方應用連結

  3. 第一次 302 重定向:認證伺服器展示登入授權頁

  4. 第二次 302 重定向:在使用者提交授權,認證伺服器認證成功後,會分配授權碼 code,並重定向回第三方應用的 redirect_uri

  5. (建議第三方應用要根據當前使用者會話生成隨機且唯一的 state 引數,並且收到授權碼時先進行校驗,避免 CSRF 攻擊)最後,第三方應用會向認證伺服器申請令牌 access_token,此時要提供預分配好的 code、client_id、client_secret 以便認證。這一步是在後端之間完成的,對使用者不可見。access_token 是有有效期的,過期後需要重新整理

  6. 拿到令牌 access_token 後,第三方應用就可以訪問資源方,獲取所需資源 access_token 相當於使用者的 session id

選擇正確的許可型別

示例程式碼

地址:https://github.com/skoruba/IdentityServer4.Admin

OpenID Connect

  • OAuth2.0 的不足之處
  • OIDC 概念

OAuth2.0 的不足之處

OAuth2.0 中的 access_token 就是酒店的房卡,誰都可以擁有房卡,有房卡就可以開啟酒店的門,但是房卡上並沒有當前使用房卡的使用者資訊,如果需要知道當前房卡所有人的資訊需要單獨再向酒店的前臺去詢問

OIDC 概念

Open ID Connect 1.0 是建立在 OAuth 2.0 之上的一個身份層

https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthorizationEndpoint

QuickStart

安裝模板

dotnet new -i IdentityServer4.Templates

檢視模板

dotnet new

使用模板建立

dotnet new is4inmem -n QuickStart

已成功建立模板“IdentityServer4 with In-Memory Stores and Test Users”。

開啟專案,啟動

點選進入登入頁面,使用預設使用者登入

登入結果

根據配置檔案通過ClientCredentials的方式獲取token

// m2m client credentials flow client
new Client
{
    ClientId = "m2m.client",
    ClientName = "Client Credentials Client",

    AllowedGrantTypes = GrantTypes.ClientCredentials,
    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },

    AllowedScopes = { "scope1" }
},

根據配置檔案通過Code的方式獲取token

// interactive client using code flow + pkce
new Client
{
    ClientId = "interactive",
    ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
    
    AllowedGrantTypes = GrantTypes.Code,
    RequirePkce = false,
    AllowPlainTextPkce = true,

    RedirectUris = { "https://localhost:44300/signin-oidc" },
    FrontChannelLogoutUri = "https://localhost:44300/signout-oidc",
    PostLogoutRedirectUris = { "https://localhost:44300/signout-callback-oidc" },

    AllowOfflineAccess = true,
    AllowedScopes = { "openid", "profile", "scope2" }
},

訪問認證介面獲取授權碼

https://localhost:5001/connect/authorize?client_id=interactive&scope=openid&response_type=code&redirect_uri=https://localhost:44300/signin-oidc&nonce=xyz

返回授權碼

https://localhost:44300/signin-oidc?code=BC56FE53D39BD46A5D55D43F485E23D7FF6583FEDD7A2A0B7A2A3DFDF5C52935&scope=openid&session_state=SwfB-jWoQ16C67cm5c_ANqbVE1R50Krj55GuJuArEQ0.BE30A11CD461DC430C5121AEFB4A4E82

知識共享許可協議

本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。

歡迎轉載、使用、重新發布,但務必保留文章署名 鄭子銘 (包含連結: http://www.cnblogs.com/MingsonZheng/ ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。

如有任何疑問,請與我聯絡 (MingsonZheng@outlook.com) 。

相關文章