asp.net core IdentityServer4 實現 resource owner password credentials(密碼憑證)
前言
OAuth 2.0預設四種授權模式(GrantType)
- 授權碼模式(authorization_code)
- 簡化模式(implicit)
- 密碼模式(resource owner password credentials)
- 客戶端模式(client_credentials)
本章主要介紹密碼模式(resource owner password credentials),OAuth2.0資源所有者密碼授權功能允許客戶端將使用者名稱和密碼傳送到令牌服務,並獲得該使用者的訪問令牌.
認證步驟:
- 使用者將使用者名稱密碼提供給客戶端
- 客戶端再將使用者名稱密碼傳送給授權伺服器,請求令牌
- 授權伺服器確定判斷資訊是否有誤,返回給客戶端令牌
建立授權伺服器
建立一個API專案工程,我這邊以埠5000的形式進行後面的講解.
Package
PM> Install-package IdentityServer4 -version 2.5.3
建立一個類Config(配置要保護的資源,和可以訪問的API的客戶端伺服器)
public class Config { /// <summary> /// 定義要保護的資源 /// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetApiResources() { return new List<ApiResource> { new ApiResource("api1","MyApi") }; } /// <summary> /// 定義授權客戶端 /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients() { return new List<Client> { new Client(){ ClientId="client", AllowedGrantTypes=GrantTypes.ResourceOwnerPassword, ClientSecrets= { new Secret("secret".Sha256()) }, AllowedScopes={ "api1",IdentityServerConstants.StandardScopes.OfflineAccess //如果要獲取refresh_tokens ,必須在scopes中加上OfflineAccess }, AllowOfflineAccess=true// 主要重新整理refresh_token, } }; } }
此處AllowedGrantTypes需要設定為ResourceOwnerPassword(密碼憑證).
配置Startup
再走到ConfigureServices方法注入IdentityServer4服務
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()) .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();//注入自定義登入驗證 }
IdentityServer4預設提供了兩種證書加密配置
AddDeveloperSigningCredential AddTemporarySigningCredential
新增記憶體ApiResourceAddInMemoryApiResources
新增記憶體Client AddInMemoryClients
新增自定義登入驗證AddResourceOwnerValidator
自定義使用者驗證
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
if (context.UserName == "test" && context.Password == "test")
{
context.Result = new GrantValidationResult(
subject: context.UserName,
authenticationMethod: OidcConstants.AuthenticationMethods.Password);
}
else
{
//驗證失敗
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
"invalid custom credential"
);
}
return Task.FromResult(0);
}
}
在Configure方法中新增IdentityServer4服務中介軟體
app.UseIdentityServer();
建立ApiResource
建立一個客戶端專案,這邊我將埠設定為5001
Package
PM> Install-package IdentityServer4 -version 2.5.3
配置Startup
在ConfigureServices新增認證伺服器地址
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";//授權伺服器地址
options.RequireHttpsMetadata = false;//不需要https
options.ApiName = "api1";
});
}
在Configure方法中新增認證服務中介軟體
app.UseAuthentication();
Run
在客戶端程式values控制器上面增加[Authorize]
直接訪問資源伺服器http://localhost:5001/api/values
code 401
啟動授權伺服器
http://localhost:5000/.well-known/openid-configuration
發現端點可通過/.well-known/openid-configuration
獲取token
這邊我用postman進行測試
code 200
access_token我們獲取到了,再拿著token通過postman請求資源程式,
code 200
成功了
refresh_token
獲取請求授權介面後會返回access_token expires
_in 等內容,expires_in是有效期(s),當然我們可以自定義有效期,access_token失效後用戶需要重新授權,client才能拿到新的access_token.但是有了refresh_token後,client檢測到token失效後可以直接通過refresh_token向授權伺服器申請新的token,當然refresh_token也是有有效期的。
AbsoluteRefreshTokenLifetime的預設有效期為2592000秒/30天。SlidingRefreshTokenLifetime的預設有效期為1296000秒/15天。
在認證伺服器中我再scopes加上了OfflineAccess
IdentityServerConstants.StandardScopes.OfflineAccess //如果要獲取refresh_tokens ,必須在scopes中加上OfflineAccess
獲取refresh_token
通過refresh_token再去獲取access_token
通過postman請求獲取資源
概要
示例地址https://github.com/fhcodegit/IdentityServer4.Samples