Idsr 定義了幾種模式適用於不同的場景:
// // 摘要: // OpenID Connect flows. public enum Flows { // // 摘要: // authorization code flow AuthorizationCode = 0, // // 摘要: // implicit flow Implicit = 1, // // 摘要: // hybrid flow Hybrid = 2, // // 摘要: // client credentials flow ClientCredentials = 3, // // 摘要: // resource owner password credential flow ResourceOwner = 4, // // 摘要: // custom grant Custom = 5, // // 摘要: // authorization code with proof key flow AuthorizationCodeWithProofKey = 6, // // 摘要: // hybrid flow with proof key HybridWithProofKey = 7 }
最近我們把 IdentityServer 部署到了生成環境,為了適用於 cs/bs,app 等不同終端,接入使用了 OAuth2.0 標准規范 AuthorizationCode,ClientCredentials,ResourceOwner,Implicit 的幾種模式和 OpenID Connect 協議,整個過程也遇到了各種各樣的問題。
啟用 HTTPS 后 Endpoint 問題
我們是在 LB 層部署了證書(沒有設置在IIS層),IIS 層還是HTTP ,IdentityServer 默認 RequireSsl 強制設置成 false ,當時生成后的 Endpoints 都是 HTTP ,因為默認 IdentityServer 是根據 RequireSsl 的設置來生成URL;最后找到的解決方案是強制設置 PublicOrigin 為 HTTPS 的域名。
Terminating SSL
If you want to terminate SSL on the load balancer, there are two relevant settings on the options:
RequireSsl
Set this to false to allow non-SSL connections between the load balancer and IdentityServer.
PublicOrigin
Since your internal farm nodes have different names than the public reachable address, IdentityServer can’t use it for link generation. Set this property to the public name.
跨域與跳過權限確認頁
CORS 是 Cross-Origin Resource Sharing 的縮寫,這本質上來自於瀏覽器的保護機制。當web頁面的host與Ajax訪問的host不同時,瀏覽器會使用Http的 OPTIONS 方法,去探測被訪問的host是否允許跨域訪問。一般就是添加Access-Control-Allow-Origin的頭 ,Idsrv 添加如下配置即可 。
RequireConsent = true, AllowRememberConsent = true, RedirectUris = new List<string> { "http://localhost:5000/index.html", }, AllowedCorsOrigins = new List<string> { "http://localhost:5000" }
第三方資源問題
如果項目中引用了第三方的資源,需要設置
CspOptions = new CspOptions { Enabled = false, }
負載環境切換緩存到 redis
//Redis var redis = ConnectionMultiplexer.Connect(CacheSetting.Redis); //客戶端信息緩存 var clientStoreCache = new ClientStoreCache(redis); //作用域信息緩存 var scopeStoreCache = new ScopeStoreCache(redis); //用戶信息緩存 var userServiceCache = new UserServiceCache(redis); //注冊客戶端緩存- factory.ConfigureClientStoreCache(new Registration<ICache<Client>>(clientStoreCache)); //注冊作用域緩存 factory.ConfigureScopeStoreCache(new Registration<ICache<IEnumerable<Scope>>>(scopeStoreCache));
定期清理過期的票據(使用EF持久化票據)
var cleanToken = new TokenCleanup(ef, 20); cleanToken.Start();
Token handle not found
2017-04-13 14:40:18.9149 ERROR Token handle not found { "ValidateLifetime": true, "AccessTokenType": "Reference", "TokenHandle": "1d6f4eb15ca3079ac25978be95d7e2f5" }
偶爾抽風,還沒有找到解決方案
https://github.com/IdentityServer/IdentityServer3/issues/2985
https://github.com/IdentityModel/IdentityModel2
負載 XSRF 問題
做負載時需要配置 machineKey
the antiforgery token cookie is protected with the default Owin data protector. If, for some reason, the server does not manage to unprotect the cookie, it'll also treat the scenario as an antiforgery validation failed. In a load balanced environment, unless you take control of configuring the servers to use the same protectors (eg. common machine key), mismatch may happen.
https://github.com/IdentityServer/IdentityServer3/issues/450
https://github.com/IdentityServer/IdentityServer3/issues/1672
IDX10311: RequireNonce is 'true'
IDX10311: RequireNonce is 'true' (default) but validationContext.Nonce is null. A nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'.
調試源碼,這個錯誤是由於獲取不到 cookie 的的原因,檢查 idsrv 的站點 cookie 是否存在,是否使用 IE 並且 iframe 跨域(使用P3P協議自動更改IE瀏覽器安全級別:http://blog.csdn.net/fdipzone/article/details/43205961)
IDX10316: The 'nonce' has expired
Microsoft.IdentityModel.Protocols.OpenIdConnectProtocolInvalidNonceException
IDX10316: The 'nonce' has expired: '...'. Time from 'nonce': '19/01/2017 13:09:13', Current Time: '19/01/2017 15:48:05'. NonceLifetime is: '01:00:00'
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { // Set expiration time to 8 hours ProtocolValidator = new OpenIdConnectProtocolValidator() { NonceLifetime = new TimeSpan(0, 8, 0, 0) }, ... , AuthenticationFailed = (context) => { if (context.Exception is OpenIdConnectProtocolInvalidNonceException && context.Exception.Message.ContainsAny(new string[] { "IDX10316", "IDX10311" })) { logger.Warn("OpenIdConnectProtocolInvalidNonce expired, reauthenticating..."); context.HandleResponse(); //context.Response.Redirect("/Error.aspx?message=" + context.Exception.Message); context.Response.Redirect(context.Request.Uri.PathAndQuery); } return Task.FromResult(0); },
https://teknovenus.com/nonce-expriation-idx10316-workaround-asp-net-mvc/
使用 OpenID Connect 登錄成功回調白板
這個問題是上線后發現的,因為本地調試都是OK ,在公司網絡訪問也是OK(機房在公司,公司環境域名是做了內部 DNS 解析),就是外網不可以,各種日志看,排查了好幾天;后面是發現,因為回調會 POST 相關的參數到客戶端上,id_token 過長被防火牆截斷,因為防火牆緩沖區設置太小的原因,參數如下:
id_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJpc3MiOiJodHRwczovL3Nzby5jbG91ZGhvdGVscy5jbiIsImF1ZCI6IjEwMDAwMDA1IiwiZXhwIjoxNDk2NTYwMjA1LCJuYmYiOjE0OTY1NjAyMDQsIm5vbmNlIjoiNjM2MzIxNTY5OTYxOTU2NjM4Lk9EZGxaVEJrT1dJdFltVTRNaTAwT1RsaUxUazVaamt0TmpZMFlUa3dOams0TVRFME9EY3pNMk00WldVdE56SXlaaTAwWWpnd0xUbGhaREF0TTJOa05tRTNOelkyTXpKbCIsImlhdCI6MTQ5NjU2MDIwNCwiYXRfaGFzaCI6InJEYVhQcXRaSFZEcUxVSzhscmotUFEiLCJzaWQiOiJhNjBlMDA4NjUyMWU5OWMwOTkxMjJlOWQ1NGU2YTg3MCIsInN1YiI6ImlydmluZyIsImF1dGhfdGltZSI6MTQ5NjU2MDIwNCwiaWRwIjoiaWRzcnYiLCJ1c2VyIjoie1wiVXNlcklEXCI6XCJpcnZpbmdcIixcIlVzZXJOYW1lXCI6XCLlkajmtptcIixcIlVzZXJQd2RcIjpcIioqKioqKlwiLFwiU2FsdFwiOlwiKioqKioqXCIsXCJDaXR5QXJlYUlEXCI6XCIxMDAwMDAwOFwiLFwiQ2l0eUFyZWFOTVwiOlwi5Y2X5Y2O6KW_XCIsXCJDaXR5R3JvdXBJRFwiOlwiXCIsXCJDaXR5R3JvdXBOYW1lXCI6XCJcIixcIkpvYklEXCI6XCJBMDAwM1wiLFwiSm9iVGl0bGVcIjpcIuWfjuWMuumUgOWUruWJr-aAu-ebkVwiLFwiRW1haWxcIjpcInl4ZGVuZ0Bob21laW5ucy5jb21cIixcIkJ1c2luZXNzRGVwXCI6XCJcIixcIlVzZXJTb3VyY2VcIjozLFwiWFR5cGVcIjoyLFwiTW9iaWxlXCI6XCIxMzgxNzk2MzY2MlwiLFwiSG90ZWxDZFwiOlwiMDIxMDY0XCIsXCJIb3RlbE5hbWVcIjpcIuS4iua1t-WcuuS4rei3r-WcsOmTgeermeW6l--8iOWGheWuvu-8iVwiLFwiSG90ZWxKb2JJRFwiOlwiUkpDV0pMXCIsXCJIb3RlbEpvYlRpdGxlXCI6XCLotKLliqHnu4_nkIZcIixcIkJyYW5kQ2RcIjpcIlJKXCIsXCJCcmFuZERlc2NcIjpcIuWmguWutlwiLFwiVXBkYXRlVGltZVwiOlwiMjAxNy0wNS0xOFQwOTo0MDoyMS4wNFwifSIsImFtciI6WyJwYXNzd29yZCJdfQ.c_Dn0xxmLRGsp9_iZ7T2UOhwGf2uVjKwWYeGrKr70HtWDXcoafurb6_JxgEwdcWJzlhv3t9a-Y-LcupLbRBfBO-mP7CcbWM5Jr5zn55-z7RH2QnMlViK17AOOiXrKdCr8kTaGAK2bnkMpYIzk4oUAgWkwS3z0_RQ4G1aAIwIDxRvrKo4DuLwCXGPTYXp7YwAemnpvgywNvDM6yjKEL8KltdKyYWaHg8zxQVEPUOeteLFlsBA6rHJ873YTv-s6XNH3Rx944Sh75qGmPCkv3N3mEIDvHd8emMKyGJ53_Rbr6Jjr6eH_h8XNdwvtSIlH3GRfCgsJXppGxEl-KtRDGaR0w access_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJpc3MiOiJodHRwczovL3Nzby5jbG91ZGhvdGVscy5jbiIsImF1ZCI6Imh0dHBzOi8vc3NvLmNsb3VkaG90ZWxzLmNuL3Jlc291cmNlcyIsImV4cCI6MTQ5NjU2MDIwNSwibmJmIjoxNDk2NTYwMjA0LCJjbGllbnRfaWQiOiIxMDAwMDAwNSIsInNjb3BlIjpbIm9wZW5pZCIsInByb2ZpbGUiXSwic3ViIjoiaXJ2aW5nIiwiYXV0aF90aW1lIjoxNDk2NTYwMjA0LCJpZHAiOiJpZHNydiIsImFtciI6WyJwYXNzd29yZCJdfQ.e4DeFyh2Jt6dnsry0ALSbEJpj34lbN0u_iW9YAsc_XlSgWm044LeI19xRzgZvzF4lN_4jjwjvMaQPzOO4MOokSmSAjwnMdVg1j2b9U3c7YyqIUQMueHn1hTr06f2kd2OLYLz38RnNilvFf1xAAF8tXs2TOyrHl9L39i6Nb3I7pQenooIoIbP8yRGpGAztRVBBEHf-b1-7b1wmhaDYEKe_dFOXzlNPRjFzrDhvCcoke2SHJ3Zo60c9JQVUKopFPYUF0EN_TDsS4dHeZCE55tLb--1KJpz7e2WVNGMbts7HGUrlpa4O4mwESxN_c1F3V8YVstdEB7i8xYZCSqQHUdE4Q token_type:Bearer expires_in:1 scope:openid profile state:OpenIdConnect.AuthenticationProperties=Tl--AjNJpswyb_R1ytC6SqEKnWP5FWe969jAIK-tPHj7l5bCYieg5fffC111-Bjur08jIafy5-DNg2ESrenp71it4OBCLnUsLXPbFGxlsT6jWwsTmRgJf5HxG-HtsTZm2iIwDkFl2P4GmlUt7GAl8gMuTNlaLqB3M-RuJ2prt603WzMQ session_state:UDOKlCOQmRPUjrKy2bRKz-erQ9Ze4jkre7FwspSAZBA.d02260a76d5c74285e125e59531cea07
REFER: https://identityserver.github.io/Documentation/docsv2/advanced/deployment.html
