关于 OpenIdConnect 认证启用 HTTPS 回调 RedirectUri 不生效问题
在搭建 IdentityServer 服务端后,我们尝试使用了 OIDC(OpenID Connect) 的中间件来代替了原先的 Session 系统认证方式,起初采用的是 HTTP 协议,一切都没有什么问题,最近启用全站 HTTPS 后,发现登陆会跳转到 HTTP的页面,
OpenID Connect 认证流程
第一步:
请求构造授权页
Request URL:https://sso.xxx.cn/connect/authorize?client_id=10000005&redirect_uri=https%3A%2F%2Fp2.cloudhotels.cn&response_mode=form_post&response_type=id_token%20token&scope=openid%20profile&state=OpenIdConnect.AuthenticationProperties%3DTl--AjNJpswyb_R1ytC6SqEKnWP5FWe969jAIK-tPHj7l5bCYieg5fffC111-Bjur08jIafy5-DNg2ESrenp71it4OBCLnUsLXPbFGxlsT6jWwsTmRgJf5HxG-HtsTZm2iIwDkFl2P4GmlUt7GAl8gMuTNlaLqB3M-RuJ2prt603WzMQ&nonce=636321569961956638.ODdlZTBkOWItYmU4Mi00OTliLTk5ZjktNjY0YTkwNjk4MTE0ODczM2M4ZWUtNzIyZi00YjgwLTlhZDAtM2NkNmE3NzY2MzJl&x-client-SKU=ID_NET&x-client-ver=1.0.40306.1554 Request Method:GET Status Code:200 Remote Address:222.186.49.226:443 Referrer Policy:no-referrer-when-downgrade
:authority:sso.xxx.cn :method:GET :path:/connect/authorize?client_id=10000005&redirect_uri=https%3A%2F%2Fp2.xxx.cn&response_mode=form_post&response_type=id_token%20token&scope=openid%20profile&state=OpenIdConnect.AuthenticationProperties%3DTl--AjNJpswyb_R1ytC6SqEKnWP5FWe969jAIK-tPHj7l5bCYieg5fffC111-Bjur08jIafy5-DNg2ESrenp71it4OBCLnUsLXPbFGxlsT6jWwsTmRgJf5HxG-HtsTZm2iIwDkFl2P4GmlUt7GAl8gMuTNlaLqB3M-RuJ2prt603WzMQ&nonce=636321569961956638.ODdlZTBkOWItYmU4Mi00OTliLTk5ZjktNjY0YTkwNjk4MTE0ODczM2M4ZWUtNzIyZi00YjgwLTlhZDAtM2NkNmE3NzY2MzJl&x-client-SKU=ID_NET&x-client-ver=1.0.40306.1554 :scheme:https accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 accept-encoding:gzip, deflate, sdch, br accept-language:zh-CN,zh;q=0.8 cookie:acw_tc=AQAAACVlAyxojQIAFpTodHdoRw2DIBLj; idsrv.xsrf=lL0mbSQCJwUEqyWAufNmPsKzR6s4rlmo9TnH5RgESnOUtVXBzRBfF1bumRiySNSdyI8LDA; SignInMessage.410d3116e4685a1ff945b72ec5b7bdee=owpop5ySCBwDREEoMovtaEIsnr5k6JVvD8kbdp2dJlSJvAUWX6xXvR1qP_G-C-Hf6QOOV8M5wZ_HBJ8L-101uznPFSmw1lqkmnPHTj0xJeR3gJ4QeaP9IEm4sQvEyZWzdnNGwW-F_y_9ooSGDqpNEr-PFoI_nrK7az0PWvgHsqv-hKSBQVonq_AIPaGumS7p5ORNHkHwB1LdJXWXnVwFq6NMM1DLD1zXJgpXp4EkzjCExIA89Nd9wUYZlJDb1TuNGLpucraql9RZ6kpKJpnr4z2bGtW1JENWdPb3YH4thqBlP6JMz4s9rKCJWhrOtojpuqfzGUanE-Sw8he4My0GQQ3FcNPqT8GFaVUmwPpy8qIZriLyCRO6IUlXoqo_uwAHS2N5f3AYtaoIo88TEJZl8sZCIeM1QD2ZADB1L96JHuTzMAR7TLEWxtFrFmlIX4Ue0XyXclzQnKbNPnhFlwK11joxFxpVczMuUp4bpEvfdhmuFaqTkTqO9qOmxh3fiVQxqpv9LXNg-JFrAWzlXfSJmrFaRUJ6-RFbHi31cYkLQ0v4Gal7KASMsVTvp9Iswj1lgvRtHoMEAXmwyMWThZg6RGJbFrQQSjG2uFB7-LFCOI_V_d3EYQMHxkvFeFJHUQ4O9DbXq0v-nSXCzcyNYEXBUS273X6OensJ4nilWZVtnssyXh1SppSICXGnX1MHfNvWMp2AlmdQQo76myLL0l2yCRVpyP6fLGWcMUmn9MmQi5-NoIALlCNyOslwAOGsgCkpcpLEeeI0BD7SKwXzQZQnTgCtJJayMZVdPB3aEKojZFe1BsBUV8nwsdEAhY8dc6HZPY3wpGhrVK1tYH1KzCFt1yw2LI3qgKgQyGnqETk7GUD-gunrvMYym-CMjteLu7lSyOiaaRTjMWb8o35psxK8RvHRNqc; _pms_session=gyyabpm4wizgtp0drl02nuuf; SignInMessage.9d3ece88ead86da0d24435c1a430c34e=NGNDv77kQPUAKKXDc9uVuokKTz1CIJG0t1G81CCrtHgPxx2wEb1TwxRdCT7UV61lmQxF-kYGSXH2-irds7PfoQSdp4Wm4Aot-zOjtpjtR8aH5VEndu78hbGIv6n2JEOAUQBtfh2GTrmQYBgHpEHIulCrHJWovGVmFIsgjDHmpnzAz_Kf6ZmcL0sC2tFDZYKP2PTYkaF83cG3PYbqVIeM7HTuucORtaybnuzv15UxGKU4T28cZwI28d_u-Og8gXkAoYNNFnT054S-q_Coxhz1nR5rYAZe_WmLZCvqM_3D0M7IK_1nHN8NexBKyuRIZ9V25D4afl7rNROCb2A0m3Y3ayUgu3FySHZwcjjhsia_l16IJMVu6KjFJCVZHh6JGu06O6lTza8QUnvYA6vh-PWVFiLFoszUy16RxuDWJl_fnoaWFBxP97zhFZ7gCHj9zdr5BjEgko6fkoEIcmHosehqsrTYJUGPKkaKR2GUfKzCEBeoNFvUveCOXrrjayeCSw5hk6dEjdehQvjrBy7ezffBRgViimpBr0YLqH00WSRdsZzfBA_KlUBkE3zJDBIrmGkyB7xiTOSHFXT-CoC4g7rEF4usM44CCntWTO48UGd_eq6qIxSLjVhXGrsuauqXZTKs82mPmARsd85opyA69kHfDkHT2vCKT3GLVmvBxk4Sdi1zoCobyHohFpj0o-u0J9fko6W8uxhilcKovPeWh8yDp5CQrpquXKc6yAN-4x1Lyh-lnKKHm2m1uPSV0v04P4PZfBYqASkYtgSKTRcmwErF8l8H7XpqlWFRT2DdXWYwetTv2I5MhC6HqwIlVoYzBk3JRIGheYTazNaO8Mz3pm1Ayp0VIWPH36mvdXynMV5iJmqgccVkWpdHmwJbHzdYajWPtqYocartaA2pAU9zog4nneNs9KI; SignInMessage.2e3550a6f27dbe37def555603163623e=dQUu6i3OyRhbsoYaK7wbtzSK5xGjVNSmenWCdZ0wbSvAnMAK7KNmBLBCOcV9rKRxAA-9jehtXT7bkFA0NRptXfgrWrU_my-cVvC2ok72b7qwk4LGTHonPqklVl-L_xCCBkUe0svpP1C4B3etBAj5MotsOVNFHuyhkNDAfMt_HpA6fCUJnEZtfQ0i3qycFmwL67O4JQx1EEbvhuugnlbyDiahppUlc-_TeVoySc_SNpnJc8HC9fCkYm7p2vQaLZoWVUsROU-JCPeIJ8NRDISTMqYlSWL0QY1UNa8vXF7zLSGO8jfMQ5YdmpYJIwG7VZrqf4yqHKi9E14G0IhYi1Y99wddOyaPYIKIQGIhWHkWVkRX0E1Mq-gsvzXJzLlN0-0_Ywyt4VRtpE1tQz9iS4xAtNPZBp3xyBzPJ0KsM6sHOuxuZT3X0NQV7hIZRA1eIV4xKhrGJtlh59FC7BaCmVIDDV7dytO9AGMlO5iYSjgKI4bTGC8cGYXHs2k7BsFTEh_RWKg0ygyu3hjvjIgN4X67yQ4BGHv92iFwLUxEn4nBXb7oZEx7BawzYAFcTlCK-l81VPmwr2Is0FjnhYlcr7MS-tvUx3HmG758-QPpoth5T0oZrOKVwv8Pop1503VjS1hFF1MCEzp0zzXaJcjZ_XeDLWmzElZ9jl8pw4AB2I64W-33IWtxBBXgjc9iX1L4t8imT9EMKXKK6wDxTZNQ8uxL2rnoV6NmYRoVcFjR0CFnAhntZDvhNGPWcFtH-eaGeFgDxa8HlbBV4vk1yNDlxN4-4upJxO7fbWmXx3OGPo8IVydyeQI0pUF61UKXYzVekyjc2rMS7wEpVsd8LdOy147tXLeZwqHBVbgU8GA6uITahJdjatOB2RLgTKgJvb_IPfgQQhRNv4ur5q2cfqerTIzSmH1lOJI; SignInMessage.249b0aeaa528d65e2fabdac9f695167d=PoHjxvv3eyxmJKkLNVuho_DAgPaIEjTg0XfzznyM_sKpPQ5vATFKZRIO7h2b9Zf-OtjqdTQN4gvEewnlEOVOvNED-WVT_hTcmBrj22ghMEKXJhYzjjVNOJxc5nYjcI0BHCiNgFsBZyTqsVqGG-QINfID8iG2NpnROU3sLygzIObydw56IJj63N6kJTBemCompDHcm0V8yOuqr8DIu_jR02JCPYotz2nRuHTsN-SRLCJzm1Q5ggfiy5HMMdV0jkdMj2CirxQV3sri32VNVNCvZ0XZJxFd5Ut-xoVfyPU9gGx1FI7iIEDhXyjSNGHgTGo2DFmgTVRn7kVIHnJ5kRiMvM9fYl8PHz2e_pB8VEGuUCisrXrQjdCiaTHdxjFudlmS-IcRksQV9fx4K0Ug0uy9Luf9RrfnUQo8i8JyARtPdrjmguJ79LVOjL-8eblBQlgUB6ih6uwXLBvRziyDTaB4B2FBT--Ke4guwrYBvxJdIgMh7Up5eJne8UW6Qeoc30L6q3TqiFLQLiFS39lehwx7EqoG_xLnp2y133ClQqfbFSBlBnPZD0OvNSuiWnOE724NeqioVkACPWUFgF7X1fbPDQXLc9mfRt0aNwlipNnCKtKwAoXtFJby1skdLx_I18uALo3KAwptivFweCvtKLELv0dBcQxzRzzOcIPi_gNUdrXnS7z23DvhCbsu8q842J-wZeqwXMrwakUzhh1-FvQW4Agt7FrTOCmOS1KzmarC2Xm5srIH3hWGc3gsvT3NYZxM0k-5WAhHw_d16zLAIWW4K_euxz5GnX-qKwvT3Rcpui4DsKQvZQGfCg4Ua3KKQT1iN-YOuixKMQ7nSiIHaP_0qZYI5H16mj3eiW4w0D2mDUSWCCRmJ7BR5qak0_mH0uLodDVvd8oejbfivWt-SGAd0MnZsoU; SignInMessage.8773da773d34dd5079a297ef19316ac0=4KfGGFxV7E7AiKGysQXQS9Dszsj3xHqg2RaVgdc-0uSz8c6ZLf_4ZB2FA1HLFXxoTnFbU-EN86eB1ZjPdYZO1BRPWw4dt_pk-ojgj88HcdDFlshoQBwAoN6MeTlnEriewC78lYz7UZVDJnCFZki4J7dMGPwu7XM93sLif3cR-d0pIFPdLBsjBZ2XaEDi6B9kKN8IAt5afWT8St-1LgnHSJPWl6iiCj2T71NaNnE0XU1ij_JdQRzLIQy4Z0eG8HA-jH3J_0oaqqoR-X3aJAiNlvb_GMPvXWF6CXaWFPiSxpu8_ApjKeI3Sq5bPghCZdApTdV1BH5UWDPciyZmX1knQd3B8DkmSsrAdSYXq5XVSDB4VYRFbZti-Msd5vZlCTo6w9tcGdNRlAnv9aEZjopkkf8IQqgiW0xZFlQjS9oGEVyNv80BkuhMMmoeNaEotHOaoK3qkNswqJRUNWxT9-6lLKB8pUaDxZZE4dJVC2VnW-CK6nbdDqCACcA-Ayf2wCTy2iVknv_zUUyXW5AkUO0CPI1BrBJkc_GqCbymXJphKO44vNLVUBoaMNjdAkqktpHBYx_rXImhCHNdXh0hvsVST4EWlTb2Y6IHx4G4sWNqE7irBPqhFJ4GcSUCfZlM0MD_72JdNCo9sYRDXqBUKO4gx1yRg2pyO00R0ch604AJ5EsF2fotrUm7Ie3br2erdI3dKkuKmy2jpyPQG3NmsZVFXFqIzguX7v4YvQTXXbvlVNHRpj3ulgGL7EQwnaikOD1Zc6mntSyesZ19nrkIQqjeFNFYA22-myhhFDo9ukjm0JIqvLoBLCN5br0JnyTXfHj0Bai_OsR1JMqoBSC9ZYHcSpEkNGDgi_gGiN1rQWUQikxhV3I5T1thx0A4_otw3MV2BMOWKxNMBdI4-jO4AAoWPK4BtFI; idsvr.session=a60e0086521e99c099122e9d54e6a870; idsrv=FXCKHsF7lWgZ6xBWmn5VU8KmB3Uo_DPkYFTsRNvEH3CKFOW4is94zus3LN9lPVj6yOqoV2o36dl5FS3tBTOWphg1fzIShAbW522-_AKnL0I3kKQldeccu7Wusb1moa2iAjq9q3y7mxlGFGBP7itBigCY1cfHeAZGbBfx1R1O5RUBO2Zjwf0PZuH1_-0EexZUNn-8qwOaMrpVTVTUOjZqc1Lr0cFFc6_PyLsyhHWbuiZLRcIHSsf_tSiw1YorIWFgoEv8kRlHOc4squfvAQQsraxBRrIKqWieqqhCA1y7kGUvlBJV8I0eLmP6lu9S08kehlM4sw referer:https://sso.xxx.cn/login?signin=249b0aeaa528d65e2fabdac9f695167d upgrade-insecure-requests:1 user-agent:Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Mobile Safari/537.36
第二步:
请求构造授权页会返回一个OAuth2回传信息 POST 到客户端 ,OAuth 2.0 Form Post Response Mode ,是一个对 OAuth2 的扩展,构造回传信息提交到客户端是通过URL的querystring和fragment这两种方式,这个扩展标准提供了一基于form表单的形式把数据post给客户端的机制。
Request URL:https://p2.xxx.cn/ Request Method:POST Status Code:302 Remote Address:58.220.27.80:443 Referrer Policy:no-referrer-when-downgrade 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
注意这一步会返回一个 302 的 Location 头,并且是 HTTP ?
cache-control:no-cache content-length:0 date:Sun, 04 Jun 2017 07:10:05 GMT eagleid:3adc014214965602048883069e expires:-1 location:http://p2.xxx.cn pragma:no-cache server:Tengine set-cookie:OpenIdConnect.nonce.nC4ZwLkiOvWjmFbe4uMezWn3Ot8OR5Q%2FEKWIPNawETw%3D=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT set-cookie:_pms_cookies=GKjrW_Lmfe3Iek_fsJ0zN9CeIQWNuawbZSAi_tl1yl3q8CT2BCqNzk7rDYrsoJGmfE_tRYN7eccbe34g4TKJjBTSOeMXbdj-JYa249ypqj_zO6spFIoCbchvtMlFUct5ygIbs9a5QVD1FdfZh6oUMFBE283N6EENqX6SxAqv1KfIrrkEyAq2vvwtrnH6uRDcva4vfvgj5777VaXHl-DGQWRy5ET1xusxwT6rx8sA_39QPKxmLeqvoEaz1JRl_pXkBwndcmAmem1g12x1J8m5oW1jBB0sF-fcVCEw737SshYAgOLs42Gb6f-KfOZToqtvf-jkjgHKDM_FgoJjigYOGG3Jbcg158wnbPhBLCukDx1-V3gHLpaKVuiv4kPVzNsQouI27AplfJUbCYQK9KAgzpAIiQXpeGW4AGCfHgHiL_txBNCRoWLRM02xvetHlvmW3vxqBu-qTa_fnYeCFd8DcSJLHcyyOwVGkI8eQEIDzAAmRvy9qYetFRhJo75_SnxK73sHw0OCzM9jX-cFt1_5X1AwXK52QBKwgtfg8Ehxtn5aKwoyEQ3SgJQOMjO1W-AK1pzPN9fbNG-zMhXxN22V7srHxOS5J8s9_w0kZKU_vTjqr8-UaGtj-ed09ik-CpfCZvYOH3sKFIa3Yb_HeOt6GnSviaML1pULaXYR0qKxsOwL2yXyfRxsZb95TGUZ9e8wVvb5AGlxVAZD6_NWlU5qxTqss7fR3vAVbFJyWDcnZ_qEP4iu2yhXuZfplsnDSB8ZO_7JEUJKEKG3AEjsaX0c0eJAc0gJEQ5bx7uujGIUe1mpGhz6AwaLXHnbY_mzgA2HFXFLaqL_l6vwbLJzg8khzqOUT8sF0d91yGco6xxxb_tcLWFURT4z3e6i2Nz0KOpQkt5R8U4TiM41khXbpfiRxsWetc-TunteIv0iVtw3K1My7-qJOeSJn_JvDtnTxaesEiMbaMcGGkyGF_Ew33kSVrO3Ooiiv3qpb2oLLCz5CQ3gxStFCxpf4_ga69rCVQZwnY3-OX4r1pUq-1ObvQBuM055c2jCyhK5EGcd0aN7tu5yCCVLcIsjVLYBmCt-fa2Hkw_qgy6e6-0T07gLPB56k7_O4dm7qI7DbtmBEVR5LYPIA3LxK0Rpsfza0Uj9ELgubA6LP7GhMD313_mIC9DMAjZ3S2jpiuENqm8FsYsLPBKjSWBDCPbI9hHwEl1fBhSoaMxhNSaLdIj88Y5tBADrV0jMgFk9n2Xnzxr8WIMlczvWcFYLoDV6W1shGdxxsDpLK6XLYtzu2hxtm26z1Zhn41LNPuOTUpOK8iC_9J68lUW61mHJbYtWBTmKgXe6IssWegbfdtRLFBRccsWSqIBYtWQtEccTFtzmX4IgBqwCHpOCIVAg7F1m3zV-cI2AfpLccceSGbONTmdOl9dmye0EgW45Mqkz4gAqBfHwkGw8EyiBV9oIUY5dwB3RcrJx9MQlF7iLRMpnbKeVxBePtiEmkc4cn81CPkxjS1PvhH1EljWtHi9OKXKeWzoExnWtVbdHJxe2mcgvNcmqfrPj-R3DWfN83pqNdymqVpqsjZFbZv2UmQlZ8RJxMAqIPqihdA5iYxWzjhtINcrvSRY6qw8fN392t83_1in0XJCHkIO5MJnNYbHhaX7RbnifvXn1Lkg2NwvjAMrl1b8EEq-AO2pqt_XvgAThvv8Khrcwon-RQxmLKVrZPpOv7O-vaHoLsTr2inclMRvwZ_b_w3WMI5G9CAU8mD8eGco1BnkSK8EL78-j57NTH3kXnro6DsA4vgv57a_QuTxXi_DsMLcK5xFDJzohSYzI4DPDjgyuWItztGgk6pAn_ScOkGJ8iMiMaAKH0kxe0g4hjoUSfsS5-SSfAe7RnhZo-WNMn3x6Iz6S7vi9mKttfBRLiKyyPe1tS3ULngJEMukZfR90tUVD1V-yRf1Td1oX08-8iIf1H_qQgLvy37_glhrQRnJOVnufbTGmBTrfJdf482TGhn5HxEOKcaXYKHSU259IegMjT0ikzrxXkCVoI-M1kBuEYtBKCvG1gPH8vO1H710GNzPGq2ZCXBFtNFPsegmx-WXviJd_-B3nFrv_N0w_op0EBZH0Zxel_ZJzkPWzs7zDMRA_qVKjjeVDFDawOK2jKfchsQn4jWCXEYRjn0OpdWb2Hq0PmLvhFPcSgGxPOs6StdcHUGIkwoERzPr20mGj4ZBM9R7krYjjbo6Lddg-Pkvu503E07J9GZMnJ97lvbSVZeckrdFXd2btmh1aJI_qg_DCWwovhKIImN-l-IShEFkQjEBwei9nIiik05qjnU3twlVVIqRaPwV9UUXPODV-xz-oXh0CeN1QKNVAHV8-uoyfzF6F1tQ1Fkv2du_AvEFYySTqqAZVcmXGY6g0ESntPJ4bSYZ-CD3Sk7PxUvJpnQoXgtVzDlqRQeTr2ltqo5QFMyIuTEOCk1alYy-crWQi6Y7-iDHdNtDkYfaVWlYy4mHavmZ9mE5VhIR69UEvRGw2c1D0sNdkBd15EzRS2jA5KGI56bTjNElT9aJOwnPyHQUTJ5I; path=/; HttpOnly status:302 timing-allow-origin:* via:cache5.l2cm10-1[157,0], cache2.cn242[166,0] x-powered-by:ASP.NET
第三步:
根据 Location 的地址跳转 ,这个时候发现 并不是 HTTPS
问题分析
本能的认为是 Idsrv 的 Client 配置回调地址问题 ,后面查阅 Idsrv 源码发现跟授权的 RedirectUri 并没有什么关系(OIDC 是兼容 OAuth 2.0 的),后面查看了客户端的源码(https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Security.OpenIdConnect/OpenidConnectAuthenticationHandler.cs)
/// <summary> /// Handles SignIn /// </summary> /// <returns></returns> protected override async Task ApplyResponseChallengeAsync() { if (Response.StatusCode == 401) { AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode); if (challenge == null) { return; } // order for redirect_uri // 1. challenge.Properties.RedirectUri // 2. CurrentUri AuthenticationProperties properties = challenge.Properties; if (string.IsNullOrEmpty(properties.RedirectUri)) { properties.RedirectUri = CurrentUri; } // this value will be passed to the AuthorizationCodeReceivedNotification if (!string.IsNullOrWhiteSpace(Options.RedirectUri)) { properties.Dictionary.Add(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey, Options.RedirectUri); } if (_configuration == null) { _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.Request.CallCancelled); } OpenIdConnectMessage openIdConnectMessage = new OpenIdConnectMessage { ClientId = Options.ClientId, IssuerAddress = _configuration.AuthorizationEndpoint ?? string.Empty, RedirectUri = Options.RedirectUri, RequestType = OpenIdConnectRequestType.AuthenticationRequest, Resource = Options.Resource, ResponseMode = OpenIdConnectResponseModes.FormPost, ResponseType = Options.ResponseType, Scope = Options.Scope, State = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + Uri.EscapeDataString(Options.StateDataFormat.Protect(properties)), }; if (Options.ProtocolValidator.RequireNonce) { AddNonceToMessage(openIdConnectMessage); } var notification = new RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage }; await Options.Notifications.RedirectToIdentityProvider(notification); if (!notification.HandledResponse) { string redirectUri = notification.ProtocolMessage.CreateAuthenticationRequestUrl(); if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute)) { _logger.WriteWarning("The authenticate redirect URI is malformed: " + redirectUri); } Response.Redirect(redirectUri); } } return; }
默认是取 Properties.RedirectUri 的地址否则自动获得当前请求的 CurrentUri
private string CurrentUri { get { return Request.Scheme + Uri.SchemeDelimiter + Request.Host + Request.PathBase + Request.Path + Request.QueryString; } }
由于我们使用的负载时在LB层做的,所以默认获得的地址是 HTTP的,那么为什么 Properties.RedirectUri 获取是哪里的数据呢 ?
private readonly IOwinContext _context; ... /// <summary> /// Find response challenge details for a specific authentication middleware /// </summary> /// <param name="authenticationType">The authentication type to look for</param> /// <param name="authenticationMode">The authentication mode the middleware is running under</param> /// <returns>The information instructing the middleware how it should behave</returns> public AuthenticationResponseChallenge LookupChallenge(string authenticationType, AuthenticationMode authenticationMode) { if (authenticationType == null) { throw new ArgumentNullException("authenticationType"); } AuthenticationResponseChallenge challenge = _context.Authentication.AuthenticationResponseChallenge; bool challengeHasAuthenticationTypes = challenge != null && challenge.AuthenticationTypes != null && challenge.AuthenticationTypes.Length != 0; if (challengeHasAuthenticationTypes == false) { return authenticationMode == AuthenticationMode.Active ? (challenge ?? new AuthenticationResponseChallenge(null, null)) : null; } foreach (var challengeType in challenge.AuthenticationTypes) { if (string.Equals(challengeType, authenticationType, StringComparison.Ordinal)) { return challenge; } } return null; }
也就是说在 401 状态码的情况下,会获取 _context.Authentication.AuthenticationResponseChallenge 对象时候为 null ,并不是客户端配置项,最后突然想到可能是 Idsrv 的拦截器里配置的(https://github.com/IdentityServer/IdentityServer3.Extensions.Mvc/blob/master/source/IdentityServer3.Extensions.Mvc/IdentityServer3.Extensions.Mvc/Filters/IdentityServerFullLoginAttribute.cs)
public class IdentityServerFullLoginAttribute : OwinAuthenticationAttribute { public IdentityServerFullLoginAttribute() : base(Constants.PrimaryAuthenticationType) { this.Order = 1; } public override void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) { var statusCodeResult = filterContext.Result as HttpStatusCodeResult; if (statusCodeResult != null && statusCodeResult.StatusCode == 401) { var ctx = filterContext.HttpContext.Request.GetOwinContext(); var url = ctx.Environment.CreateSignInRequest(new SignInMessage { ReturnUrl = filterContext.HttpContext.Request.Url.AbsoluteUri }); filterContext.Result = new RedirectResult(url); } } }
解决方案
1.) 客户单强制设置返回 302 与 URL 或 强制给 Properties.RedirectUri 赋值
public class Startup { private static readonly Logger logger = LogManager.GetCurrentClassLogger(); /// <summary> /// 启动类配置 /// </summary> /// <param name="app"></param> public void Configuration(IAppBuilder app) { //忽略SSL证书,安全验证 //ServicePointManager.ServerCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) //{ // return true; //}; // configuring Redis GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(CacheSetting.Redis, "SignalR") { Database = 3 }); //configuring the OpenID Connect authentication middleware app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "Cookies", }); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { // Set expiration time to 8 hours ProtocolValidator = new OpenIdConnectProtocolValidator() { NonceLifetime = new TimeSpan(0, 8, 0, 0) }, Authority = IdsvSetting.Authority, ClientId = IdsvSetting.ClientId, Scope = "openid profile", ResponseType = "id_token token", RedirectUri = IdsvSetting.RedirectUri, SignInAsAuthenticationType = "Cookies", UseTokenLifetime = false, Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = async n => { try { var id = n.AuthenticationTicket.Identity; var nid = new ClaimsIdentity(id.AuthenticationType); // keep the id_token for logout nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); // add access token for sample API nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken)); // keep track of access token expiration nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString())); //获得用户信息 // var client = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken); //var userInfo = await client.GetAsync(); //var user = userInfo.JsonObject.Last.First.ToString().DeserializeJson<XHotelOAuth2UserInfoResponse>(System.Text.Encoding.UTF8); var userInfoClient = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken); var userInfo = await userInfoClient.GetAsync(); var user = userInfo.JsonObject.Last.First.ToString().DeserializeJson<XHotelOAuth2UserInfoResponse>(System.Text.Encoding.UTF8); ... n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties); ////清空 OpenIdConnect 开头的 Cookies foreach (var item in HttpContext.Current.Request.Cookies.AllKeys) { if (item.Contains("OpenIdConnect", StringComparison.OrdinalIgnoreCase)) { HttpCookie cookie = HttpContext.Current.Request.Cookies[item]; cookie.Expires = DateTime.Now.AddDays(-1); HttpContext.Current.Response.Cookies.Add(cookie); } } HttpContext.Current.Response.AddHeader("Location", IdsvSetting.RedirectUri); } catch (Exception ex) { ex.ToExceptionless().MarkAsCritical().Submit(); logger.Error(ex, "UseOpenIdConnectAuthentication: " + ex.Message); } }, RedirectToIdentityProvider = n => { if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) { var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token"); if (idTokenHint != null) { n.ProtocolMessage.IdTokenHint = idTokenHint.Value; } } return Task.FromResult(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); }, } }); } }
2.) MVC 拦截器里设置 Properties.RedirectUri
public class TokenAuthorizeFilter : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext context) { if (!context.HttpContext.User.Identity.IsAuthenticated) { #if !DEBUG HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = context.HttpContext.Request.Url.ToString().Replace("http", "https") }); #endif // 401 who are you? go login and then try again context.Result = new HttpUnauthorizedResult(); } //如果 session 不存在,清除 openid // context.RequestContext.HttpContext.GetOwinContext().Authentication.SignOut(); // context.Result = new RedirectResult("/home?returnUrl=" + HttpUtility.UrlEncode(HttpContext.Current.Request.Url.AbsoluteUri)); } }
REFER:
https://github.com/IdentityServer/IdentityServer3.Extensions.Mvc
https://github.com/aspnet/AspNetKatana
干掉状态:从session到token
https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513566&idx=1&sn=a2688cadbe9c8042ff1abbdf04a8bd5e&chksm=80d67a1db7a1f30b28b93ed2ab29edfbf982b780433e4bfd178e3cc52cb1f9100cc8f923db4f#rd