IdentityServer4之Client Credentials(客戶端憑據許可)
參考
項目創建:0_overview,1_client_credentials
概念:客戶端憑據許可
認證服務端配置
認證服務ApiResource配置
new ApiResource("api1", "api項目 一") { ApiSecrets = { new Secret("api1pwd".Sha256()) } },
認證服務Client配置
//client credentials client new Client { ClientId = "client", // no interactive user, use the clientid/secret for authentication AllowedGrantTypes = GrantTypes.ClientCredentials,
//Jwt = 0;Reference = 1支持撤銷; AccessTokenType = AccessTokenType.Reference, // secret for authentication ClientSecrets = { new Secret("secret".Sha256()), new Secret("abc".Sha256()) }, // scopes that client has access to AllowedScopes = { "api1" } },
認證服務Startup配置
// configure identity server with in-memory stores, keys, clients and scopes services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients());
配置完成啟動訪問http://localhost:5000/.well-known/openid-configuration

資源服務Api配置
資源服務器Startup配置
services.AddMvcCore() .AddAuthorization() .AddJsonFormatters(); services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(options => { options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.ApiName = "api1"; options.ApiSecret = "api1pwd"; //對應ApiResources中的密鑰 });
添加接口
[Route("[controller]")] [Authorize] public class IdentityController : ControllerBase { [HttpGet] public IActionResult Get() { var info = from c in User.Claims select new { c.Type, c.Value }; var list = info.ToList(); list.Add(new { Type = "api1返回", Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); return new JsonResult(list); } }
Client客戶端
客戶端與授權服務器進行身份驗證並向令牌端點請求訪問令牌。
授權服務器對客戶端進行身份驗證,如果有效,頒發訪問令牌。
//credentials client private void btnAuth_Click(object sender, EventArgs e) { // discover endpoints from metadata Task<DiscoveryResponse> discoTask = DiscoveryClient.GetAsync(txtCCAuthSer.Text); discoTask.Wait(); var disco = discoTask.Result; if (disco.IsError) { MessageBox.Show(disco.Error, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information); txtCCResult.Text = string.Empty; txtAccessToken.Text = string.Empty; return; } // request token var tokenClient = new TokenClient(disco.TokenEndpoint, txtCCClient.Text, txtCCSecret.Text); Task<TokenResponse> tokenTask = tokenClient.RequestClientCredentialsAsync(txtCCScopes.Text); tokenTask.Wait(); var tokenResponse = tokenTask.Result; if (tokenResponse.IsError) { MessageBox.Show(tokenResponse.Error, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information); txtCCResult.Text = string.Empty; txtAccessToken.Text = string.Empty; return; } txtCCResult.Text = tokenResponse.Json.ToString(); txtAccessToken.Text = tokenResponse.AccessToken; }
調用Api
private void btnCallApi_Click(object sender, EventArgs e) { // call api var client = new HttpClient(); client.SetBearerToken(txtAccessToken.Text); var responseTask = client.GetAsync(txtCCApiUrl.Text); responseTask.Wait(); var response = responseTask.Result; if (!response.IsSuccessStatusCode) { MessageBox.Show(response.StatusCode.ToString(), "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information); txtApiResult.Text = string.Empty; } else { var contentTask = response.Content.ReadAsStringAsync(); contentTask.Wait(); var content = contentTask.Result; txtApiResult.Text = JArray.Parse(content).ToString(); } }
獲取token過程解析
Jwt形式獲取access_token
通過IdentityModel發送請求

監聽請求數據

客戶端身份驗證兩種方式
1、Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3。
POST /connect/token HTTP/1.1 Connection: Keep-Alive Content-Type: application/x-www-form-urlencoded Accept: application/json Authorization: Basic Y2xpZW50OnNlY3JldA== Expect: 100-continue Host: localhost:5000 MS-ASPNETCORE-TOKEN: 08de58f6-58ee-4f05-8d95-3829dde6ae09 X-Forwarded-For: [::1]:12112 X-Forwarded-Proto: http Content-Length: 40 grant_type=client_credentials&scope=api1
2、client_id(客戶端標識),client_secret(客戶端秘鑰)。

Reference形式獲取access_token
將client的AccessTokenType設置為1

再次獲取的access_token不包含Claim信息。

此時獲取的access_token(加密后)對應PersistedGrants表中的key

調用Api資源服務過程解析
Jwt形式獲取access_token調用Api
監聽請求數據

api資源服務驗證Jwt形式token會去認證服務器獲取一次配置信息。



Reference形式獲取access_token調用Api
監聽請求數據

api資源服務驗證Reference形式token每次(可配置緩存)會去認證服務器獲取信息。參考



