上一篇我们讨论了客户端为SPA在IdentityServer4中的授权码流程,本篇继续讨论MVC应用中的IdentityServer4授权码流程。

1.查看授权码流程

与上篇类似,只是这次的客户端换成MVC应用,其余步骤与方法都一样,不赘述,参考【One by One系列】IdentityServer4(六)授权码流程原理之SPA

抓包截图如下

image-20200714003552535

2.详解IdentityServer4授权码流程(MVC)

2.1 请求IdentityServer4的配置端点-获取各项配置

请求

GET /.well-known/openid-configuration HTTP/1.1
Host: localhost:5001
User-Agent: Microsoft ASP.NET Core OpenIdConnect handler
Request-Id: |d8ea1673-480ea8a77b20fcf1.

响应

HTTP/1.1 200 OK
Server: Kestrel
{"issuer":"http://localhost:5001","jwks_uri":"http://localhost:5001/.well-known/openid-configuration/jwks","authorization_endpoint":"http://localhost:5001/connect/authorize","token_endpoint":"http://localhost:5001/connect/token","userinfo_endpoint":"http://localhost:5001/connect/userinfo","end_session_endpoint":"http://localhost:5001/connect/endsession","check_session_iframe":"http://localhost:5001/connect/checksession","revocation_endpoint":"http://localhost:5001/connect/revocation","introspection_endpoint":"http://localhost:5001/connect/introspect","device_authorization_endpoint":"http://localhost:5001/connect/deviceauthorization","frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"scopes_supported":["openid","profile","api1","offline_access"],"claims_supported":["sub","name","family_name","given_name","middle_name","nickname","preferred_username","profile","picture","website","gender","birthdate","zoneinfo","locale","updated_at"],"grant_types_supported":["authorization_code","client_credentials","refresh_token","implicit","password","urn:ietf:params:oauth:grant-type:device_code"],"response_types_supported":["code","token","id_token","id_token token","code id_token","code token","code id_token token"],"response_modes_supported":["form_post","query","fragment"],"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],"id_token_signing_alg_values_supported":["RS256"],"subject_types_supported":["public"],"code_challenge_methods_supported":["plain","S256"],"request_parameter_supported":true}

2.2 请求IdentityServer4-密钥端点

请求

GET /.well-known/openid-configuration/jwks HTTP/1.1
Host: localhost:5001
User-Agent: Microsoft ASP.NET Core OpenIdConnect handler
Request-Id: |d8ea1673-480ea8a77b20fcf1.

响应

HTTP/1.1 200 OK
Server: Kestrel
{"keys":[{"kty":"RSA","use":"sig","kid":"768AC10B4A3728E20644058B6EDF5051","e":"AQAB","n":"p8rr99FmiZSoeCzEdThzdfX-XTPCRTXW43PftBuHEPS3CcUM2aRnVpthzyXoaxLb9tKCqOplnCRmIlVorRe1UG_MqrhOgRhD-jCftOyBtAgLg992Oh2i2_E-F62fsmcrvkwd6e31DS2QYAIKADYamkAlWjaBKVpqHYHEe40kHMTzgwg7-pqmQQUUViBlCOm19NC4szHfEJkIAa4MeO2S3Vmvc6vVniwggYshkWCIZDNHq3A5KaE0_z8-5RiM_ci37YqoVvfInx9hxnCzRHHsNoQJQldomQVe9kVXepHJPXfpNWa04RJr72ySAJIQSwNw9ZIjKyENjSLnH_RxYQ6fXQ","alg":"RS256"}]}

这两步由Microsoft.AspNetCore.Authentication.OpenIdConnect内部请求

2.3 请求authorize端点

请求

GET /connect/authorize?client_id=mvc&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&response_type=code&scope=openid%20profile%20api1&code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&code_challenge_method=S256&response_mode=form_post&nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36

响应

HTTP/1.1 302 Found
Server: Kestrel
Location: http://localhost:5001/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0

请求授权端点,除client_id,response_type,scope外的标准参数,还会携带code_challenge,code_challenge_method.响应302重定向登录页

2.4 重定向登录页

请求

GET /Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36

响应

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Server: Kestrel
Set-Cookie: .AspNetCore.Antiforgery.-IwGtD3QVi8=CfDJ8EvLzXx95NhOpTKk_JopLRC52AxoSRHn9ciblh7wwEnyoJI4hEVfPW8ZrSerXc81TOVLPDoIpIS4w4idShomXf2jiiUcgqYsCP6XaeH2i681CSh6xBc-uP1PI9cYvHuUdiMFC25Ig67pxU3pnNo4j0s; path=/; samesite=strict; httponly
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" />

    <title>IdentityServer4</title>
    
    <link rel="icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
    
    <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="/css/site.css" />
</head>
<body>
    

<div class="nav-page">
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">

        <a href="/" class="navbar-brand">
            <img src="/icon.png" class="icon-banner">
            IdentityServer4
        </a>

    
    </nav>
</div>

   
    <div class="container body-container">
        
<div class="login-page">
    <div class="lead">
        <h1>Login</h1>
        <p>Choose how to login</p>
    </div>

    

    <div class="row">

            <div class="col-sm-6">
                <div class="card">
                    <div class="card-header">
                        <h2>Local Account</h2>
                    </div>

                    <div class="card-body">
                        <form action="" method="post">
                            <input type="hidden" id="ReturnUrl" name="ReturnUrl" value="/connect/authorize/callback?client_id=mvc&amp;redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&amp;response_type=code&amp;scope=openid%20profile%20api1&amp;code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&amp;code_challenge_method=S256&amp;response_mode=form_post&amp;nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&amp;state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&amp;x-client-SKU=ID_NETSTANDARD2_0&amp;x-client-ver=5.5.0.0" />

                            <div class="form-group">
                                <label for="Username">Username</label>
                                <input class="form-control" placeholder="Username" autofocus type="text" data-val="true" data-val-required="The Username field is required." id="Username" name="Username" value="">
                            </div>
                            <div class="form-group">
                                <label for="Password">Password</label>
                                <input type="password" class="form-control" placeholder="Password" autocomplete="off" data-val="true" data-val-required="The Password field is required." id="Password" name="Password">
                            </div>
                                <div class="form-group">
                                    <div class="form-check">
                                        <input class="form-check-input" type="checkbox" data-val="true" data-val-required="The RememberLogin field is required." id="RememberLogin" name="RememberLogin" value="true">
                                        <label class="form-check-label" for="RememberLogin">
                                            Remember My Login
                                        </label>
                                    </div>
                                </div>
                            <button class="btn btn-primary" name="button" value="login">Login</button>
                            <button class="btn btn-secondary" name="button" value="cancel">Cancel</button>
                        <input name="__RequestVerificationToken" type="hidden" value="CfDJ8EvLzXx95NhOpTKk_JopLRDTtcucnBzI1HMQFrP12uFbjXEoii8lxOgJo92xYvtcgba2unOgfrjPFfHEIvZUgOl1xF_SOI-8t7bVVb1Rf40U8yCL7sEpj9_ZTZBImUDXGxkryW_8FmBO8qQL8nOprI4" /><input name="RememberLogin" type="hidden" value="false"></form>
                    </div>
                </div>
            </div>


    </div>
</div>
    </div>

    <script src="/lib/jquery/dist/jquery.slim.min.js"></script>
    <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>

    
</body>
</html>

重定向至登录页,响应登录页html

2.5 登录操作

请求

POST /Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0 HTTP/1.1
Host: localhost:5001
Content-Type: application/x-www-form-urlencoded

ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0&Username=admin&Password=admin123456%21&button=login&__RequestVerificationToken=CfDJ8EvLzXx95NhOpTKk_JopLRDTtcucnBzI1HMQFrP12uFbjXEoii8lxOgJo92xYvtcgba2unOgfrjPFfHEIvZUgOl1xF_SOI-8t7bVVb1Rf40U8yCL7sEpj9_ZTZBImUDXGxkryW_8FmBO8qQL8nOprI4&RememberLogin=false

响应

HTTP/1.1 302 Found
Server: Kestrel
Location: /connect/authorize/callback?client_id=mvc&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&response_type=code&scope=openid%20profile%20api1&code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&code_challenge_method=S256&response_mode=form_post&nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0
Set-Cookie: idsrv.session=AF3EB53184951E2E7E8748B7AB0118E2; path=/; samesite=none
Set-Cookie: idsrv=CfDJ8EvLzXx95NhOpTKk_JopLRDcizx-_TS8GrKeHvXLpVBeXxi00r1ZJV6x26_-b8wbj3fBuAovCy-d-MlZ2A23E7gszaRru1rjf2erNXLwdGBf5rhZVchSzTzfhYM8fCiu6g6_TI3StO88A91t18AfWt3509ZUKl9ZmJ4PYnQ8SehoIBpgESO7Z25k839FNUq9VN8jnzEzuy7kGDasL0vQs9C6Ol2KRYLGoGZUDNfnrNB9jPztG2f4dgHMXPc07Uhsxl_e3PKHB2YUBk6jy0xgRS0QNRwdmk5jFbYrxjJhj6TWVQ9omKOED2sCpqQVmUhJIpxiIYGeRsccXlMNMx5hJ0fSa_Gxwp-acGo5Uk8P-H-4MW60VCOJob2HoNMYkOR0coWHtbZWWQjLfYZ8ooB_Www2VyYJ2mcEt-WFQZkFjxUAc7Co9AtkO7WxYqqqbaJcV2oBCOzQPNlZlkQ3MzXT9bLBrZidWJfcxMi3GU2GArZix-8xDqzTWu-2cQVffvdUZgg_xOc4r71QPd9IzBJ-O2c; path=/; samesite=none; httponly

登录操作,在原有的参数基础上,增加Username,Password,Post提交,响应302重定向,并Set-Cookie

2.6 重定向至授权回调

请求

GET /connect/authorize/callback?client_id=mvc&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&response_type=code&scope=openid%20profile%20api1&code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&code_challenge_method=S256&response_mode=form_post&nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0 HTTP/1.1
Host: localhost:5001

响应

HTTP/1.1 302 Found
Server: Kestrel
Location: http://localhost:5001/consent?returnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0

authorize授权认证成功回调,重定向consent页面

2.7 请求授权选择页面

请求

GET /consent?returnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36

响应

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Server: Kestrel
Referrer-Policy: no-referrer
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" />

    <title>IdentityServer4</title>
    
    <link rel="icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
    
    <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="/css/site.css" />
</head>
<body>
    

<div class="nav-page">
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">

        <a href="/" class="navbar-brand">
            <img src="/icon.png" class="icon-banner">
            IdentityServer4
        </a>

            <ul class="navbar-nav mr-auto">
                <li class="nav-item dropdown">
                    <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">admin <b class="caret"></b></a>
                    
                    <div class="dropdown-menu">
                        <a class="dropdown-item" href="/Account/Logout">Logout</a>
                    </div>
              </li>
            </ul>
    
    </nav>
</div>

   
    <div class="container body-container">
        
<div class="page-consent">
    <div class="lead">
        <h1>
            mvc
            <small class="text-muted">is requesting your permission</small>
        </h1>
        <p>Uncheck the permissions you do not wish to grant.</p>
    </div>

    <div class="row">
        <div class="col-sm-8">
            
        </div>
    </div>

    <form action="/Consent" method="post">
        <input type="hidden" id="ReturnUrl" name="ReturnUrl" value="/connect/authorize/callback?client_id=mvc&amp;redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&amp;response_type=code&amp;scope=openid%20profile%20api1&amp;code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&amp;code_challenge_method=S256&amp;response_mode=form_post&amp;nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&amp;state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&amp;x-client-SKU=ID_NETSTANDARD2_0&amp;x-client-ver=5.5.0.0" />
        <div class="row">
            <div class="col-sm-8">
                    <div class="form-group">
                        <div class="card">
                            <div class="card-header">
                                <span class="glyphicon glyphicon-user"></span>
                                Personal Information
                            </div>
                            <ul class="list-group list-group-flush">
                                    
<li class="list-group-item">
    <label>
        <input class="consent-scopecheck"
               type="checkbox"
               name="ScopesConsented"
               id="scopes_openid"
               value="openid"
               checked="checked"
               disabled="disabled" />
            <input type="hidden"
                   name="ScopesConsented"
                   value="openid" />
        <strong>Your user identifier</strong>
    </label>
        <span><em>(required)</em></span>
</li>
                                    
<li class="list-group-item">
    <label>
        <input class="consent-scopecheck"
               type="checkbox"
               name="ScopesConsented"
               id="scopes_profile"
               value="profile"
               checked="checked" />
        <strong>User profile</strong>
            <span class="glyphicon glyphicon-exclamation-sign"></span>
    </label>
        <div class="consent-description">
            <label for="scopes_profile">Your user profile information (first name, last name, etc.)</label>
        </div>
</li>
                            </ul>
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="card">
                            <div class="card-header">
                                <span class="glyphicon glyphicon-tasks"></span>
                                Application Access
                            </div>
                            <ul class="list-group list-group-flush">
                                    
<li class="list-group-item">
    <label>
        <input class="consent-scopecheck"
               type="checkbox"
               name="ScopesConsented"
               id="scopes_api1"
               value="api1"
               checked="checked" />
        <strong>My API</strong>
    </label>
</li>
                            </ul>
                        </div>
                    </div>

                <div class="form-group">
                    <div class="card">
                        <div class="card-header">
                            <span class="glyphicon glyphicon-tasks"></span>
                            Description
                        </div>
                        <div class="card-body">
                            <input class="form-control" placeholder="Description or name of device" autofocus type="text" id="Description" name="Description" value="">
                        </div>
                    </div>
                </div>

                    <div class="form-group">
                        <div class="form-check">
                            <input class="form-check-input" type="checkbox" checked="checked" data-val="true" data-val-required="The RememberConsent field is required." id="RememberConsent" name="RememberConsent" value="true">
                            <label class="form-check-label" for="RememberConsent">
                                <strong>Remember My Decision</strong>
                            </label>
                        </div>
                    </div>
            </div>
        </div>

        <div class="row">
            <div class="col-sm-4">
                <button name="button" value="yes" class="btn btn-primary" autofocus>Yes, Allow</button>
                <button name="button" value="no" class="btn btn-secondary">No, Do Not Allow</button>
            </div>
            <div class="col-sm-4 col-lg-auto">
            </div>
        </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8EvLzXx95NhOpTKk_JopLRA54swTWpkQLVRbM-dBtBN-4-PMbI27cIZqWHDqHMrqBo_PwvHJZK5uz7G7KwTauALmI5jX8fFuliNia3GO1WhWAXTwWSBmlHAlwHWNybM70wK9JlQYmW4QBMdduJn3x07Fh0urqzSIk3jrYdJTZ4TI3qrLx1DIp7s9H_CnkzBaJg" /><input name="RememberConsent" type="hidden" value="false"></form>
</div>

    </div>

    <script src="/lib/jquery/dist/jquery.slim.min.js"></script>
    <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>

    
</body>
</html>

验证用户名、密码,服务端cookie已设置,验证成功,再次响应302,重定向consent页面,让用户确认是否同意授权,即相关api资源的授权勾选。

2.8 同意授权

请求

POST /Consent HTTP/1.1
Host: localhost:5001
Content-Type: application/x-www-form-urlencoded

ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dmvc%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A6002%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520api1%26code_challenge%3DvDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4%26state%3DCfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0&ScopesConsented=openid&ScopesConsented=profile&ScopesConsented=api1&Description=&RememberConsent=true&button=yes&__RequestVerificationToken=CfDJ8EvLzXx95NhOpTKk_JopLRA54swTWpkQLVRbM-dBtBN-4-PMbI27cIZqWHDqHMrqBo_PwvHJZK5uz7G7KwTauALmI5jX8fFuliNia3GO1WhWAXTwWSBmlHAlwHWNybM70wK9JlQYmW4QBMdduJn3x07Fh0urqzSIk3jrYdJTZ4TI3qrLx1DIp7s9H_CnkzBaJg&RememberConsent=false

响应

HTTP/1.1 302 Found
Server: Kestrel
Location: /connect/authorize/callback?client_id=mvc&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&response_type=code&scope=openid%20profile%20api1&code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&code_challenge_method=S256&response_mode=form_post&nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0
Set-Cookie: ConsentResponse.CBQAI6quFiONZvGmAvFsFStkleTmRdoaVXSd3xSOzGQ=CfDJ8EvLzXx95NhOpTKk_JopLRAunDGUnaFsACxZxmiqGGd2CONUYTggvUQOJqL-slVk9CjrFedMxPiMdDVN8Gr0dk1bpdbqOjTPEkVJeeslUFjBvtwk7M3cqkTaFgfcgPsTaixC3CRnCEyKTTVx5mswVWXRLX4gP84hx8LH1ummLDfP3RXx4OvvNIWbhQJmvnMU1V63vTP6i1ANRrOiPVKeBA9-yW8nYOj3v61D4WYKtWZkaN-GMIIaIKVOQLcvuOwgMAKvBPsila2TkIzUGXXnYMkooKvhhAjomIX8hfUldoFA; path=/; httponly

与登录操作类似,post同意授权的scope清单,以及是否同意,ScopesConsented=openid&ScopesConsented=profile&ScopesConsented=api1&Description=&RememberConsent=true&button=yes,响应302重定向至授权回调

2.9 重定向至授权回调,返回授权码

请求

GET /connect/authorize/callback?client_id=mvc&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&response_type=code&scope=openid%20profile%20api1&code_challenge=vDiRaZB2pHkoow4SiD-4D5YObxjluheQmi6jM2vYcLM&code_challenge_method=S256&response_mode=form_post&nonce=637302073815947799.ZjMzMTkwMzUtZDQ5YS00OTkxLTllNzQtMDNhODk0NDQzNGU5ZGIzMDI3MGMtMWQzMC00YzY5LThiZjItMDA5OTNkNTE2MGQ4&state=CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

响应

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Kestrel
Set-Cookie: idsrv=CfDJ8EvLzXx95NhOpTKk_JopLRBNjXlFt3nvrJDTaWLYWcCU3fje7b_kmurwoGUCej07sRMLrLxFkSMhMOXbgl8xvjYhpERGpISxD-QoxdCcLICzVUIGYGD7RvJQdfvHF3QXpR1_Kffm2e9WXE27wf4Qp5CR87xQSmNmL4qx8i7fLBjnTm7Nhzv3zOSV2bRjVLRU3BlKjqqkalj1z6sL5vaGr4NhLZRNBiDPLJxDghXrtu-dK1U6VlGGVJ4sg87u4W9Q8E23xmUlZiVMkDztjNYxW6I2WoRypZhjIiuoPSUsHqs4wBZ5bsLEMjbCGcoKbeBFyJzhi13P2yU-c1TGB6wcBUDgTV6TqHTu8d8lmzIDcMDeaKJSnv5F7h5BRiOe8FV2INbws6RUfeo0zsbIZr46M1gppTLZoNRl8W7Y2fuwoDj_irPkx5rGQYI4Wia-aM64ASEZpvI7ztNGSnq-ToSMzxX8JPFRq7inVWVhMoJOsHBFFRdiu9aN35IPgc4y8tn7w_13IX7wXh-BqnDBD8b0C50GS09u4GhjoEFHwPgHG_U7pV4qbctj2EFef2aUrbjX0g; path=/; samesite=none; httponly
Content-Security-Policy: default-src 'none'; script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='
X-Content-Security-Policy: default-src 'none'; script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='
Referrer-Policy: no-referrer
<html><head><meta http-equiv='X-UA-Compatible' content='IE=edge' /><base target='_self'/></head><body><form method='post' action='http://localhost:6002/signin-oidc'><input type='hidden' name='code' value='8F80E2D57D10FBA66BE5FDD44C28C55414F04A884075461104C1EF7828DAE961' />
<input type='hidden' name='scope' value='openid profile api1' />
<input type='hidden' name='state' value='CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag' />
<input type='hidden' name='session_state' value='lHCZqkJ0suot4KBIbaBadd17-zTF9pyuMpfbZqfv-hE.BBA2DB34D59FF6A60AF3FBD6EFF6A3D4' />
<noscript><button>Click to continue</button></noscript></form><script>window.addEventListener('load', function(){document.forms[0].submit();});</script></body></html>

又重定向至authorize回调,此时回调响应html页面

里面有一个表单

<html>
 <head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <base target="_self" />
 </head>
 <body>
  <form method="post" action="http://localhost:6002/signin-oidc">
   <input type="hidden" name="code" value="8F80E2D57D10FBA66BE5FDD44C28C55414F04A884075461104C1EF7828DAE961" /> 
   <input type="hidden" name="scope" value="openid profile api1" /> 
   <input type="hidden" name="state" value="CfDJ8EvLzXx95NhOpTKk_JopLRAtCPNf259LPzLsz20hoZ9vEALtJi8Ms99_BXC-Cra7prdpF58nHahlLqSHZz_pyId1Kf4CCFvY5juG2p2RqTbCcZCQ6_G5Fd4FzTT0RtCaLbhRPDDGMb6D7PSWd-cy-tn64CsYkRa85yEeklZHLHtVADjK0CbBhSR5nXERBptLeNyayrGInKAQHR5aXI9qvD00NodlABRotjw2ALGnRwQRXjZ5ZGMvi4v3LWYHtuyvXyAhIglZ3l1QP1oNQraTuYWvSceK4AqyitMIQ0ZvBsOF8Q14rmvq9JQvuzf6fX9Fj_YRB7Tfs2bV7CR1kgLB3Ss5amy_cwBTQHTTqLKeLyyvgb1zMC6LOcLL26oQj9cWag" /> 
   <input type="hidden" name="session_state" value="lHCZqkJ0suot4KBIbaBadd17-zTF9pyuMpfbZqfv-hE.BBA2DB34D59FF6A60AF3FBD6EFF6A3D4" /> 
   <noscript>
    <button>Click to continue</button>
   </noscript>
  </form>
  <script>window.addEventListener('load', function(){document.forms[0].submit();});</script>
 </body>
</html>

并在load时自动触发submit

window.addEventListener('load', function(){document.forms[0].submit();});

提交至http://localhost:6002/signin-oidc,此时code会被存入mvc客户端后台,这里细节,需要研究过源码才能解答

2.10 请求token端点

请求

POST /connect/token HTTP/1.1
Host: localhost:5001
User-Agent: Microsoft ASP.NET Core OpenIdConnect handler
Request-Id: |d8ea1674-480ea8a77b20fcf1.
Content-Type: application/x-www-form-urlencoded

client_id=mvc&client_secret=secret-mvc&code=8F80E2D57D10FBA66BE5FDD44C28C55414F04A884075461104C1EF7828DAE961&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&code_verifier=uCbO1SO2dtSr-bIZ9rsX1lJk2pSjVSFMXmoSzzov_bY

响应

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Server: Kestrel
{"id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6Ijc2OEFDMTBCNEEzNzI4RTIwNjQ0MDU4QjZFREY1MDUxIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ2MTA1ODUsImV4cCI6MTU5NDYxMDg4NSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAxIiwiYXVkIjoibXZjIiwibm9uY2UiOiI2MzczMDIwNzM4MTU5NDc3OTkuWmpNek1Ua3dNelV0WkRRNVlTMDBPVGt4TFRsbE56UXRNRE5oT0RrME5EUXpOR1U1WkdJek1ESTNNR010TVdRek1DMDBZelk1TFRoaVpqSXRNREE1T1ROa05URTJNR1E0IiwiaWF0IjoxNTk0NjEwNTg1LCJhdF9oYXNoIjoiNU1YZWNXTW9scjc0OGtqWmRCTFlCUSIsInNfaGFzaCI6IlpOTzhmeE44N3l1QkRrTFhQOFJWMmciLCJzaWQiOiJBRjNFQjUzMTg0OTUxRTJFN0U4NzQ4QjdBQjAxMThFMiIsInN1YiI6IjEiLCJhdXRoX3RpbWUiOjE1OTQ2MTA1ODMsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.FBqN2mPMYfBkz-O8CS_8AMET5rINB7k1DwsgF5BK4WsOrRgT-3lAPaGQ6FvxUX6Zoyr6Yg4wjCgqIEB2B9yixQJe1tdYDiOZ1-LrfziSW8crI83UgsMGnobSZAjf4ZuUdnCnu5EWT0q03EUpx7UxlMW1HR9EkvslQ16CoaFVA8R9srYaxHDyia-p-_0eCHZkSuOmUvcidaJv1SD-9WRw2p1sZ_eAnttYrKCBy1-LNxdX_GaEvKqbZNZ8rB0gGQ8tAUfbhtbA_kNhPkRd_7pfD6EiEKvQpivopH8_8_VqCScRHkq3u2bNC7qHobKgrzZCEXP39eRBmDMq_FAJ5XjGQg","access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6Ijc2OEFDMTBCNEEzNzI4RTIwNjQ0MDU4QjZFREY1MDUxIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTQ2MTA1ODUsImV4cCI6MTU5NDYxNDE4NSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAxIiwiY2xpZW50X2lkIjoibXZjIiwic3ViIjoiMSIsImF1dGhfdGltZSI6MTU5NDYxMDU4MywiaWRwIjoibG9jYWwiLCJqdGkiOiI0RDZGM0E1OTdGMjY4N0E2RTM4OTkxN0JGMjFFM0Y5QyIsInNpZCI6IkFGM0VCNTMxODQ5NTFFMkU3RTg3NDhCN0FCMDExOEUyIiwiaWF0IjoxNTk0NjEwNTg1LCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpMSJdLCJhbXIiOlsicHdkIl19.YJT5fOPAJ5Zfkn0lx3eFlfg4mhMgeUEkeQZMUY02mtO9YuFATCuIRT8GSKD_kwollEqZXwdI20jKkCHKE8W6K7BIP4kRNOn1XiRFo3cJ11nhZxXOmnhD5ViRnQklKXhvjWccsCObY8PLteSaE6hZb1P4rDRcIhfh3XAbYjrq9k5l5WkAoivkUax_bgONONLCWKz4-xzp6poCkc-fvi0p2iEMifMNCiA-spw_k2NORVi0ZNhGCn8AzmGARRVk54_MliDkWjfZk4oeB-SwqX_FTzx70IUpmcYruq361pNFU8oIcJ6G_sqd2_GmHRwrm9fUTYh5fFsm8HHvV2oHdayqxw","expires_in":3600,"token_type":"Bearer","scope":"openid profile api1"}

codescopeclient_id,,grant_type等必要参数作为post参数请求token端点,特别提一下此时需要客户端传递code_verifier,最后返回id_tokenaccess_tokenexpires_inscope

2.11 注销登录-请求end_session_endpoint

请求

GET /connect/endsession?post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignout-callback-oidc&id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6Ijc2OEFDMTBCNEEzNzI4RTIwNjQ0MDU4QjZFREY1MDUxIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ2MTA1ODUsImV4cCI6MTU5NDYxMDg4NSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAxIiwiYXVkIjoibXZjIiwibm9uY2UiOiI2MzczMDIwNzM4MTU5NDc3OTkuWmpNek1Ua3dNelV0WkRRNVlTMDBPVGt4TFRsbE56UXRNRE5oT0RrME5EUXpOR1U1WkdJek1ESTNNR010TVdRek1DMDBZelk1TFRoaVpqSXRNREE1T1ROa05URTJNR1E0IiwiaWF0IjoxNTk0NjEwNTg1LCJhdF9oYXNoIjoiNU1YZWNXTW9scjc0OGtqWmRCTFlCUSIsInNfaGFzaCI6IlpOTzhmeE44N3l1QkRrTFhQOFJWMmciLCJzaWQiOiJBRjNFQjUzMTg0OTUxRTJFN0U4NzQ4QjdBQjAxMThFMiIsInN1YiI6IjEiLCJhdXRoX3RpbWUiOjE1OTQ2MTA1ODMsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.FBqN2mPMYfBkz-O8CS_8AMET5rINB7k1DwsgF5BK4WsOrRgT-3lAPaGQ6FvxUX6Zoyr6Yg4wjCgqIEB2B9yixQJe1tdYDiOZ1-LrfziSW8crI83UgsMGnobSZAjf4ZuUdnCnu5EWT0q03EUpx7UxlMW1HR9EkvslQ16CoaFVA8R9srYaxHDyia-p-_0eCHZkSuOmUvcidaJv1SD-9WRw2p1sZ_eAnttYrKCBy1-LNxdX_GaEvKqbZNZ8rB0gGQ8tAUfbhtbA_kNhPkRd_7pfD6EiEKvQpivopH8_8_VqCScRHkq3u2bNC7qHobKgrzZCEXP39eRBmDMq_FAJ5XjGQg&state=CfDJ8EvLzXx95NhOpTKk_JopLRCfEOKDdY1T1-2l1vCzWMUWhnbg1dxg4-yeWSLZYk7nUYoe2Zw4ENckDO9ZJbthlJ5wJ8lVGc1yfk0WV82pZuBHysuTg-BjCmYBpzF1VvTovaehzUmFkBrPnje5aihe2lsk4ipihnNhw7zixwM3t-cZ&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://localhost:6002/

响应

HTTP/1.1 302 Found
Server: Kestrel
Location: http://localhost:5001/Account/Logout?logoutId=CfDJ8EvLzXx95NhOpTKk_JopLRAZbKYODnbu_Ya4aqh80r3vYXAgJ9105xekmnNEpSDtSsZYne0jN6Fp5yAS2oqvrSQdkdZVrrQT5REYstZ9ID5Nprq83mrPv5W5-5U8V6LyvSIV9JbG5OI1z1L6yArhyAIT5vZukUUnf8KKZjNo4YKXcvJIJp303YfawX4YNaV7n0M2eE3M7gehTYEEMAUoqKAZNyp31qrDLnljkL4hNdG3x9yDb_cTchhy6HPxpKowVgmukA37RSQ0juyUtRfse8dXSb0qH5_6QKBGadU14rYFcPdG0O6vzmNawrVrGurRxRcptcHGxtykFomerFKHFaTzNyJXJszMCFSsx_SZoZHo0LJwiUGP1H0FST7cR9tH3syPbJw-bGEWQRXyvU8QZoWk_ILDlCRT3aVFoJ7MbRUSUX0AJY2U4Mzlwk27a6arLRioalD2EKW8bXvOLFSYfLrmcQc96nsCdGkdarWrBvacuRg6ReedaMOWXGFhXzaS7qh4yM5dah8KV6JVrtItZ7jlJOHAgL0onolUeWV_d59LuCTd9SHVluXl3xxgL3TKtQNSE8aim_G1GwQT0u0h2E3_csGepIeohUecVfzrpFbhYYbkjfOPiIY1KykNYImxuplw2o1vCAsdt0GsqvzuqKZCs0Fy0Be1Sse9UgvhAKfSNZdHo-WJGiSXEuXeFzTPvg

请求服务端endsession端点,传递参数id-token,响应302重定向注销登录页面。

2.12 请求Logout页面

请求

GET /Account/Logout?logoutId=CfDJ8EvLzXx95NhOpTKk_JopLRAZbKYODnbu_Ya4aqh80r3vYXAgJ9105xekmnNEpSDtSsZYne0jN6Fp5yAS2oqvrSQdkdZVrrQT5REYstZ9ID5Nprq83mrPv5W5-5U8V6LyvSIV9JbG5OI1z1L6yArhyAIT5vZukUUnf8KKZjNo4YKXcvJIJp303YfawX4YNaV7n0M2eE3M7gehTYEEMAUoqKAZNyp31qrDLnljkL4hNdG3x9yDb_cTchhy6HPxpKowVgmukA37RSQ0juyUtRfse8dXSb0qH5_6QKBGadU14rYFcPdG0O6vzmNawrVrGurRxRcptcHGxtykFomerFKHFaTzNyJXJszMCFSsx_SZoZHo0LJwiUGP1H0FST7cR9tH3syPbJw-bGEWQRXyvU8QZoWk_ILDlCRT3aVFoJ7MbRUSUX0AJY2U4Mzlwk27a6arLRioalD2EKW8bXvOLFSYfLrmcQc96nsCdGkdarWrBvacuRg6ReedaMOWXGFhXzaS7qh4yM5dah8KV6JVrtItZ7jlJOHAgL0onolUeWV_d59LuCTd9SHVluXl3xxgL3TKtQNSE8aim_G1GwQT0u0h2E3_csGepIeohUecVfzrpFbhYYbkjfOPiIY1KykNYImxuplw2o1vCAsdt0GsqvzuqKZCs0Fy0Be1Sse9UgvhAKfSNZdHo-WJGiSXEuXeFzTPvg HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://localhost:6002/

响应

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Server: Kestrel
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: idsrv.session=.; expires=Sat, 13 Jul 2019 03:23:10 GMT; path=/; samesite=none
Set-Cookie: idsrv=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; samesite=none; httponly
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" />

    <title>IdentityServer4</title>
    
    <link rel="icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
    
    <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="/css/site.css" />
</head>
<body>
    

<div class="nav-page">
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">

        <a href="/" class="navbar-brand">
            <img src="/icon.png" class="icon-banner">
            IdentityServer4
        </a>

    
    </nav>
</div>

   
    <div class="container body-container">
        

<div class="logged-out-page">
    <h1>
        Logout
        <small>You are now logged out</small>
    </h1>

        <div>
            Click <a class="PostLogoutRedirectUri" href="http://localhost:6002/signout-callback-oidc?state=CfDJ8EvLzXx95NhOpTKk_JopLRCfEOKDdY1T1-2l1vCzWMUWhnbg1dxg4-yeWSLZYk7nUYoe2Zw4ENckDO9ZJbthlJ5wJ8lVGc1yfk0WV82pZuBHysuTg-BjCmYBpzF1VvTovaehzUmFkBrPnje5aihe2lsk4ipihnNhw7zixwM3t-cZ">here</a> to return to the
            <span>mvc</span> application.
        </div>

        <iframe width="0" height="0" class="signout" src="http://localhost:5001/connect/endsession/callback?endSessionId=CfDJ8EvLzXx95NhOpTKk_JopLRD-iDHpQvqvs7oMHfRayDl1TWmAw1sxkh_HGTCQELzyrP8UobnaEJWXNW7kDkeLCcKHSj9eieXp9e7QJZaVi_lX9dPjORcItuExlHR8oozCOCWod1BaJWWwEwGyRklKp6kfsvfWMgTRP2BhDLFMc5YgeQvONdDVpVfQ_nPBosK2fHwssuocHqtjDw3RhGwbMRBUOFKhwiJ9GFZtyRvaowanRrlk62h33DSsJByUniXPLNDcL-a3COGpY-fbwF3mUp4"></iframe>
</div>


    </div>

    <script src="/lib/jquery/dist/jquery.slim.min.js"></script>
    <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>

    

</body>
</html>

重定向至Logout页面,并通过Set-CookieIndentityServer-localhost:5001的cookie置为空,且响应一段包含隐藏src="http://localhost:5001/connect/endsession/callback"的iframe的html

2.13 触发endsession回调

请求

GET /connect/endsession/callback?endSessionId=CfDJ8EvLzXx95NhOpTKk_JopLRD-iDHpQvqvs7oMHfRayDl1TWmAw1sxkh_HGTCQELzyrP8UobnaEJWXNW7kDkeLCcKHSj9eieXp9e7QJZaVi_lX9dPjORcItuExlHR8oozCOCWod1BaJWWwEwGyRklKp6kfsvfWMgTRP2BhDLFMc5YgeQvONdDVpVfQ_nPBosK2fHwssuocHqtjDw3RhGwbMRBUOFKhwiJ9GFZtyRvaowanRrlk62h33DSsJByUniXPLNDcL-a3COGpY-fbwF3mUp4 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-
Cookie: .AspNetCore.Antiforgery.-IwGtD3QVi8=CfDJ8EvLzXx95NhOpTKk_JopLRC52AxoSRHn9ciblh7wwEnyoJI4hEVfPW8ZrSerXc81TOVLPDoIpIS4w4idShomXf2jiiUcgqYsCP6XaeH2i681CSh6xBc-uP1PI9cYvHuUdiMFC25Ig67pxU3pnNo4j0s

响应

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Kestrel
Content-Security-Policy: default-src 'none'; style-src 'sha256-u+OupXgfekP+x/f6rMdoEAspPCYUtca912isERnoEjY='
X-Content-Security-Policy: default-src 'none'; style-src 'sha256-u+OupXgfekP+x/f6rMdoEAspPCYUtca912isERnoEjY='
<!DOCTYPE html><html><style>iframe{display:none;width:0;height:0;}</style><body></body></html>

触发回调,cookie已删除

3.补充

在述2.5小节之后,如果IdentityServer4**没有配置用户选择选项,或者RequireConsent=false,**代码如下

new Client
{
    ClientId="mvc",
    ClientSecrets={ new Secret("secret-mvc".Sha256())},
    AllowedGrantTypes = GrantTypes.Code,
    
    //// 需要用户同意授权,默认为false
    //RequireConsent=true,

    // where to redirect to after login
    RedirectUris = { "http://localhost:6002/signin-oidc" },

    // where to redirect to after logout
    PostLogoutRedirectUris = { "http://localhost:6002/signout-callback-oidc" },

    AllowedScopes = new List<string>
    {
        "api1",
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile
    }
},

就会直接到authorize回调,返回授权码,请知晓。

请求

GET /connect/authorize/callback?client_id=mvc&redirect_uri=http%3A%2F%2Flocalhost%3A6002%2Fsignin-oidc&response_type=code&scope=openid%20profile%20api1&code_challenge=K5sDcRY6SK9pMnC16oEWk9H8hOdre2MZ1qwpTrTygl4&code_challenge_method=S256&response_mode=form_post&nonce=637302247176725439.YWE3ZGZkYjEtZjZiOS00NjAwLTk5YmMtNjlhM2I1MjY4ZjFiZjJjYjhlYjctOTdmYi00Y2EzLWI1M2YtZjBjYjA3OWY0ZmZl&state=CfDJ8EvLzXx95NhOpTKk_JopLRB57an6y-MwhUZuh8Ez7z73Nv03xcjFhtP1yf0mh14hmoEZdulUBGkZVKk2oa-TBq9GL3E1MzqJPSwkUxcQVfmWIO6mEgLTJ3L_146JP9z_4Bf-ALMR68YPCHwgP2A1S5rEHYAXCKZ4LHfuG9Xi3bjIuUlCfoWQpHuThSDmaPX-9SeIwkywb0T1ghYCb8-TIpHZ9cBWDV0ElGmnYv4QjRQeBPtbUAKgiAmjE677kG8gOzpi7eTz5QPpym6YqZsTLdjUx6RIY2XMaBluXmC7ieU3iMsios44nRRPokH-jXGN6XqDyT26Utbsc4kL2bFBfBD63R5VPjsESoxw0xzDJY4DHGV2HU0uaSgSxNvrpO4Feg&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0 HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

响应

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Kestrel
Set-Cookie: idsrv=CfDJ8EvLzXx95NhOpTKk_JopLRBI8aySjsT2ffevQWnFQVMIfXq4pSj1LEKY0ili_u8gCklbVAaaSAtFpncya0FDBApDu5rPDXpjSIy3ziHBht1UheFB93tW4FvhJaFvsdv2xji-5dh373EWilGrh-bFHubPuo3XsG_dyfwjXFOpA3AFluuRdD6wUILB_eQVjfdBT_5xgXAy1AYliF-LgeKza2kJqXTrarewO5mMfmg-l0odP1_KMsQo79iurO2jqSMv_asxGsWgAJRE7BJwWiqAn-7cftv-tHHIoHLAwVH5rBxPessMq1GXcp2NHo2qflHvsax02-F2-nkBG6FRs7mJtbKkWWpZ14rgucoU6fW8gGGWnH4oay9PwtDNTOS4uRmHn5YHZRJx1XxGq5TSclBS7XnH7k-VsPIlDf9mHOwik9C8FuQ8KXdll4Psm1zgeLA6PP1tglt-_QAXwPtviNfxDv60gYxJC2GwMTcEGoWxqM7LkHlm4xpEabdzl00z6hXENny8pqxu2DDVlkHddVubZ7lwVNClgsGtRMMzBLa-m2oRhuWolFXTSjT7tYS7WLMmLA; path=/; samesite=none; httponly
Content-Security-Policy: default-src 'none'; script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='
X-Content-Security-Policy: default-src 'none'; script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='
Referrer-Policy: no-referrer
<html><head><meta http-equiv='X-UA-Compatible' content='IE=edge' /><base target='_self'/></head><body><form method='post' action='http://localhost:6002/signin-oidc'><input type='hidden' name='code' value='85B95996FFF98CC066BE9C7EAE5FBA3DF189767823CE4C0ECDE9556D5D448E11' />
<input type='hidden' name='scope' value='openid profile api1' />
<input type='hidden' name='state' value='CfDJ8EvLzXx95NhOpTKk_JopLRB57an6y-MwhUZuh8Ez7z73Nv03xcjFhtP1yf0mh14hmoEZdulUBGkZVKk2oa-TBq9GL3E1MzqJPSwkUxcQVfmWIO6mEgLTJ3L_146JP9z_4Bf-ALMR68YPCHwgP2A1S5rEHYAXCKZ4LHfuG9Xi3bjIuUlCfoWQpHuThSDmaPX-9SeIwkywb0T1ghYCb8-TIpHZ9cBWDV0ElGmnYv4QjRQeBPtbUAKgiAmjE677kG8gOzpi7eTz5QPpym6YqZsTLdjUx6RIY2XMaBluXmC7ieU3iMsios44nRRPokH-jXGN6XqDyT26Utbsc4kL2bFBfBD63R5VPjsESoxw0xzDJY4DHGV2HU0uaSgSxNvrpO4Feg' />
<input type='hidden' name='session_state' value='uVc1Al5eKyFI6hPGeTZYQ5T2rH7bTBj1UI8foq2Qerk.596FC31C9582DFC13A47E5E114399274' />
<noscript><button>Click to continue</button></noscript></form><script>window.addEventListener('load', function(){document.forms[0].submit();});</script></body></html>

紧接着请求token端点