4-OAuth2 & OpenID Connect & Asp net core 使用IDP

一、在 ImageGallery Client 项目启用 IDP

  1. 更改项目属性为使用 SLL, 方法同之前配置 IDP 一样
  2. 修改 IDP 项目的 Config 类中的 GetClients 方法,增加一个客户端
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>()
            {
                new Client()
                {
                    ClientName = "Image Gallery",
                    ClientId = "junguoguoimagegalleryclient",
                    AllowedGrantTypes = GrantTypes.Hybrid,
                    RedirectUris = new List<string>()
                    {
                        "https://localhost:44314/signin-oidc"
                    },
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile
                    },
                    ClientSecrets =
                    {
                        new Secret("junguoguosecret".Sha256())
                    }
                }
            };
        }
  1. 修改 ImageGallery.Client 的 startup 类, 支持 IDP 权限验证
  • ConfigureServices 方法增加如下:
                services.AddAuthentication(options =>
                {
                    options.DefaultScheme = "Cookies";
                    options.DefaultChallengeScheme = "oidc";
                }).AddCookie("Cookies")
                .AddOpenIdConnect("oidc", options =>
                {
                    options.SignInScheme = "Cookies";
                    // IDP server 的url
                    options.Authority = "https://localhost:44319/";
                    options.ClientId = "junguoguoimagegalleryclient";
                    // specify use hybrid mode
                    options.ResponseType = "code id_token";
                    //options.CallbackPath = new PathString("oidc");
                    options.Scope.Add("openid");
                    options.Scope.Add("profile");
                    options.SaveTokens = true;
                    options.ClientSecret = "junguoguosecret";
                });
  • Configure 方法增加如下
            // 需要放在 UseMvc 前
            app.UseAuthentication();

二、权限验证实际操作

  1. 在需要增加权限的地方加上属性标记[Authorize],这里我们直接在类 GalleryController上添加
    添加如下方法
        private async Task WriteOutIdentityInformation()
        {
            // 获取保存的 identity token
            var identityToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.IdToken);

            Debug.WriteLine($"Identity token:{identityToken}");

            // 打印出 User Claims
            foreach (var claim in User.Claims)
            {
                Debug.WriteLine($"Claim type : {claim.Type} - Claim value : {claim.Value}");
            }
        }

并在 Index() 开头调用 await WriteOutIdentityInformation();
调试查看Log

IdentityServer4.Endpoints.AuthorizeEndpoint:Information: ValidatedAuthorizeRequest
{
  "ClientId": "junguoguoimagegalleryclient",
  "ClientName": "Image Gallery",
  "RedirectUri": "https://localhost:44314/signin-oidc",
  "AllowedRedirectUris": [
    "https://localhost:44314/signin-oidc"
  ],
  "SubjectId": "anonymous",
  "ResponseType": "code id_token",
  "ResponseMode": "form_post",
  "GrantType": "hybrid",
  "RequestedScopes": "openid profile",
  "State": "CfDJ8MUXARYmDzBChfPQYArN2SFocvVoTFAx3QMN6tR6pIKi3s3D5eabWiyKUI45I_TYXf3VFhHYOR8v_k97C5vARQJKugB4mGVzinSNi3-Lbn7N0tMsSH1n4iTlVdQqXCqUqSx-SEuwB3dEzJ2KnFJycV2jgDvZkcHmz5VL_F_TaCOA0moKECkjmEww1RDVJPrLvOtZtwz9lDiHCXNAdJIfHIFlFYJryZMAq9_J4O0TDTT6CHPQ1iEZMTGV_aTL17E6rov5ubPegbLtCE75KUnYxN-ujnxLY4UKqAGsmsNrz2KVGautm3500_Av-XVzQnZeD0S39eRUyCL31iY2mxHhwb8",
  "Nonce": "636690543330175298.Y2I2ODYwNzMtNTJlYi00Y2FiLTgzY2YtYjI0YjBlOWRkMDg0MDUxOGZjOTktNWViZS00MmZjLTg2MjQtMjUwODAwNWU0N2Rl",
  "Raw": {
    "client_id": "junguoguoimagegalleryclient",
    "redirect_uri": "https://localhost:44314/signin-oidc",
    "response_type": "code id_token",
    "scope": "openid profile",
    "response_mode": "form_post",
    "nonce": "636690543330175298.Y2I2ODYwNzMtNTJlYi00Y2FiLTgzY2YtYjI0YjBlOWRkMDg0MDUxOGZjOTktNWViZS00MmZjLTg2MjQtMjUwODAwNWU0N2Rl",
    "state": "CfDJ8MUXARYmDzBChfPQYArN2SFocvVoTFAx3QMN6tR6pIKi3s3D5eabWiyKUI45I_TYXf3VFhHYOR8v_k97C5vARQJKugB4mGVzinSNi3-Lbn7N0tMsSH1n4iTlVdQqXCqUqSx-SEuwB3dEzJ2KnFJycV2jgDvZkcHmz5VL_F_TaCOA0moKECkjmEww1RDVJPrLvOtZtwz9lDiHCXNAdJIfHIFlFYJryZMAq9_J4O0TDTT6CHPQ1iEZMTGV_aTL17E6rov5ubPegbLtCE75KUnYxN-ujnxLY4UKqAGsmsNrz2KVGautm3500_Av-XVzQnZeD0S39eRUyCL31iY2mxHhwb8",
    "x-client-SKU": "ID_NET",
    "x-client-ver": "2.1.4.0"
  }
}

Login 界面登陆后

IdentityServer4.Endpoints.AuthorizeCallbackEndpoint:Information: Authorize endpoint response
{
  "SubjectId": "b7539694-97e7-4dfe-84da-b4256e1ff5c7",
  "ClientId": "junguoguoimagegalleryclient",
  "RedirectUri": "https://localhost:44314/signin-oidc",
  "State": "CfDJ8MUXARYmDzBChfPQYArN2SFocvVoTFAx3QMN6tR6pIKi3s3D5eabWiyKUI45I_TYXf3VFhHYOR8v_k97C5vARQJKugB4mGVzinSNi3-Lbn7N0tMsSH1n4iTlVdQqXCqUqSx-SEuwB3dEzJ2KnFJycV2jgDvZkcHmz5VL_F_TaCOA0moKECkjmEww1RDVJPrLvOtZtwz9lDiHCXNAdJIfHIFlFYJryZMAq9_J4O0TDTT6CHPQ1iEZMTGV_aTL17E6rov5ubPegbLtCE75KUnYxN-ujnxLY4UKqAGsmsNrz2KVGautm3500_Av-XVzQnZeD0S39eRUyCL31iY2mxHhwb8",
  "Scope": "openid profile"
}

然后是 token request

IdentityServer4.Validation.TokenRequestValidator:Information: Token request validation success
{
  "ClientId": "junguoguoimagegalleryclient",
  "ClientName": "Image Gallery",
  "GrantType": "authorization_code",
  "AuthorizationCode": "7be30468050e4af46c5a806adc6abeba09755766bd1abdd3a01464e03b4fe61d",
  "Raw": {
    "client_id": "junguoguoimagegalleryclient",
    "client_secret": "***REDACTED***",
    "code": "7be30468050e4af46c5a806adc6abeba09755766bd1abdd3a01464e03b4fe61d",
    "grant_type": "authorization_code",
    "redirect_uri": "https://localhost:44314/signin-oidc"
  }
}

然后是自定义方法输出的

Identity token:eyJhbGciOiJSUzI1NiIsImtpZCI6ImM5ODExYjU4NDg5Yzk4Y2RlOTNlYWM2NmJmMjVhNzUzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzM0NTc3MjMsImV4cCI6MTUzMzQ1ODAyMywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTkiLCJhdWQiOiJqdW5ndW9ndW9pbWFnZWdhbGxlcnljbGllbnQiLCJub25jZSI6IjYzNjY5MDU0MzMzMDE3NTI5OC5ZMkkyT0RZd056TXROVEpsWWkwMFkyRmlMVGd6WTJZdFlqSTBZakJsT1dSa01EZzBNRFV4T0daak9Ua3ROV1ZpWlMwME1tWmpMVGcyTWpRdE1qVXdPREF3TldVME4yUmwiLCJpYXQiOjE1MzM0NTc3MjMsImF0X2hhc2giOiJ6cUJtYjJIZmtQZk5XcnZxUlU3bVNnIiwic2lkIjoiNzc1YTRkM2E0YWY3OTQ3M2YxMTNmMmM3NjliZmVlYTMiLCJzdWIiOiJiNzUzOTY5NC05N2U3LTRkZmUtODRkYS1iNDI1NmUxZmY1YzciLCJhdXRoX3RpbWUiOjE1MzM0NTc2NzIsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.F0SVNnvhAiG9MW_BSr8YRql4KLaAGnD6xGFBDubbmmzQBGRc9198_NVQlhOtS-w9aV0daIwZaJZEvwoUS_qV03Jb_3J9VIuJ6NY44BVtnLo600KhYMlsqEoDZmjADLNqWCY4hdE-S31PXlmUNawq8jL6t9kbZRPiaSbKciAp5OHZL6UcZuAdASb-0Ivt3TE5QpwrsQ3AyHjUmYPgN4Ob3sN7wkhrDv9dD11VfZN4mtqOI-t7U3W9omloGsi22KSOBePbNQbYX3d_qcSttNyi-dW1A2TQS6WFNV8zq2ZrH-tvWU67njH-jokt10uKI7FEBAqVQ5MgApKTjahMkAlTxA
Claim type : sid - Claim value : 775a4d3a4af79473f113f2c769bfeea3
Claim type : http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier - Claim value : b7539694-97e7-4dfe-84da-b4256e1ff5c7
Claim type : http://schemas.microsoft.com/identity/claims/identityprovider - Claim value : local
Claim type : http://schemas.microsoft.com/claims/authnmethodsreferences - Claim value : pwd

复制 identity token 到 jwt.io, 可以看到解析后如下所示:

image.png

  1. 添加注销登录的功能
    打开 _Layout.cshtml, 在导航栏添加如下代码
                    @if (User.Identity.IsAuthenticated)
                    {
                        <li><a asp-area="" asp-controller="Gallery" asp-action="Logout">注销登录</a></li>
                    }

在 Controller 的 Logout 中编写:

        public async Task Logout()
        {
            // 从 Client 端注销登录
            await HttpContext.SignOutAsync("Cookies");
            // 从 IdentityServer 注销登录
            await HttpContext.SignOutAsync("oidc");
        }

运行后看日志发现有如下错误

IdentityServer4.Validation.EndSessionRequestValidator:Information: End session request validation failure: Invalid post logout URI
{
  "ClientId": "junguoguoimagegalleryclient",
  "ClientName": "Image Gallery",
  "SubjectId": "b7539694-97e7-4dfe-84da-b4256e1ff5c7",
  "Raw": {
    "post_logout_redirect_uri": "https://localhost:44314/signout-callback-oidc",
    "id_token_hint": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImM5ODExYjU4NDg5Yzk4Y2RlOTNlYWM2NmJmMjVhNzUzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzM0NTg3NDQsImV4cCI6MTUzMzQ1OTA0NCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTkiLCJhdWQiOiJqdW5ndW9ndW9pbWFnZWdhbGxlcnljbGllbnQiLCJub25jZSI6IjYzNjY5MDU1NTM2OTI2MDc1NS5NVGhpTm1SbE5EUXRNbVZrWXkwME0yRmxMV0l5T1RjdE9ETmxOMlUyTVRJMU1qbGxNRGt3WlRNMU5EQXRORE0wWmkwME0yVXdMVGxpTW1NdE1EZzBNamMzT0dKa01EWTUiLCJpYXQiOjE1MzM0NTg3NDQsImF0X2hhc2giOiJDZmxFZXBZQXJiblZsa3NmampteWtRIiwic2lkIjoiZjc1MjBjNzBlZTQxZWZhNWI5NjZkNmRjNWEyODkzMDUiLCJzdWIiOiJiNzUzOTY5NC05N2U3LTRkZmUtODRkYS1iNDI1NmUxZmY1YzciLCJhdXRoX3RpbWUiOjE1MzM0NTg3NDAsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.n9AbUy1zl90Xg35aSpW-iDPQJVbEXBCDzLZxI7EVk-zdnyqnZnh--CyqIg2SGmypzSCx2H3LhA4KW6SCmlFaZj-BvEmxIpALXpgzxsA55GLf1xWB5OA7H8u94e3mx1231xqh3_GGNLjDdohp8qiuktdVoWuz3M5nNbuiTHzPAjCuwDsS1OTV9CCOX_WFpdct_7RaiOetlzeRY1Msc_MRQ3vnYYGGE4pwW57IhXM7oQAJ7ruLnzAkZ6h3bugY_c7vHKkG4gAmrBxrI0IcniXsY-DkkFQBZRyGaj-AhSNbTet7Nz-vEQOWtgo4OBmoIlcVbhPLTHt1xSuSx5pn4Fdfpg",
    "state": "CfDJ8MUXARYmDzBChfPQYArN2SH3JdRYY7x6NjAVdLn5flJFBf5lLyeOw88_tyPtFtS-0oeM80VZDjEtp1ypnpT30J8tUAJdsFONzgPtFOA7bBl3DBKIT83uyss72ZrEteN07tjGRP9YSxhE4_s3lJu83vXJCBT6ElCA055pBg_xRFaN",
    "x-client-SKU": "ID_NET",
    "x-client-ver": "2.1.4.0"
  }
}
  1. 在 IDP 的 Config 中配置登出的 redirect url, 添加如下代码
                    PostLogoutRedirectUris = new List<string>()
                    {
                        "https://localhost:44314/signout-callback-oidc"
                    },

Client 端对应配置


image.png

这两句也可以不要,因为是默认的配置
再次运行,注销登录会发现如下日志

IdentityServer4.Validation.EndSessionRequestValidator:Information: End session request validation success
{
  "ClientId": "junguoguoimagegalleryclient",
  "ClientName": "Image Gallery",
  "SubjectId": "b7539694-97e7-4dfe-84da-b4256e1ff5c7",
  "PostLogOutUri": "https://localhost:44314/signout-callback-oidc",
  "State": "CfDJ8MUXARYmDzBChfPQYArN2SHO-kKXV181UqBNd_rBw7RP_frYMPrHFlBWao7R7_IUiOv5l9zbB3PHEHSk4O74Uk9EPD2PeFQ3HMRm5DvHRTylXgMDGUKbEYag7sKpSLLyhBFWUXsYpjCujxr8ZxUvSUeyx8OzvCQzhzFpA5QEnUJ0",
  "Raw": {
    "post_logout_redirect_uri": "https://localhost:44314/signout-callback-oidc",
    "id_token_hint": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImM5ODExYjU4NDg5Yzk4Y2RlOTNlYWM2NmJmMjVhNzUzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzM0NTkxNTQsImV4cCI6MTUzMzQ1OTQ1NCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTkiLCJhdWQiOiJqdW5ndW9ndW9pbWFnZWdhbGxlcnljbGllbnQiLCJub25jZSI6IjYzNjY5MDU1OTIzNjM0Mzc2OS5PVEZpT0RZM1ltVXRNakk0TmkwME1tSTFMV0UzWm1JdE5qWmtORFpsWWpNNU5EY3paRGd5WWpBeFkyTXROV1l4TkMwME9USTFMVGt3TmprdFpEazJOamhoT1dJNE0ySTIiLCJpYXQiOjE1MzM0NTkxNTQsImF0X2hhc2giOiI2Zjdxa0ZtdFg2ZXJVa1pIRTdkTEdnIiwic2lkIjoiYjA5ZTc5Mjc2ZWYzNTE4MWJlNTk2OTkzYWM3YWMzYWQiLCJzdWIiOiJiNzUzOTY5NC05N2U3LTRkZmUtODRkYS1iNDI1NmUxZmY1YzciLCJhdXRoX3RpbWUiOjE1MzM0NTkxNTAsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.FZOb_EWRZklp9uhiWR-mLaOu0Or41rjztnwIk888t178fgFSvBn0ei_Zg3x1FuDb_0nHUXxwK_kHceCPrbNBGdmKyjpyfKDRtdX7Fnhhm91UGATlrtNG2VQs4srkwkkoj3iQUq05IhIPxBWAS3YR482WrQ3HEqe90b8cWgoN9S2OObO7d-Pjc7CH5fmDEAvkUAfC5HA4MGv3ludSJixK6Vyt3M_HyA-Wnva8m4UOWbMHcWRgZGNbFnwjYWr9oZ7wO03rlLRuZ8bmsl4sZ-oSK_YY_DUwzdxRSS1gZCwA58Xg1vITjK5XQn3nTt_0A7KmMBAjNMTRc81ckM6GvgKHtg",
    "state": "CfDJ8MUXARYmDzBChfPQYArN2SHO-kKXV181UqBNd_rBw7RP_frYMPrHFlBWao7R7_IUiOv5l9zbB3PHEHSk4O74Uk9EPD2PeFQ3HMRm5DvHRTylXgMDGUKbEYag7sKpSLLyhBFWUXsYpjCujxr8ZxUvSUeyx8OzvCQzhzFpA5QEnUJ0",
    "x-client-SKU": "ID_NET",
    "x-client-ver": "2.1.4.0"
  }
}

此时注销登录会显示一个是否跳转回 Client 配置的 redirect uri 的页面,如果要实现自动跳转
打开 IDP 项目的 AccountOptions, 将下面的字段改为 true 即可

public static bool AutomaticRedirectAfterSignOut = true;
  1. 我们配置了 options.Scope.Add("profile"); 但是查看日志并没有返回自定义的那些 Claims
    Client 端对应配置增加
    image.png

    从 IDP 的 UserInfoEndpoint 获取数据
    image.png

    可以发现也只有name相关属性被返回了,至于其他属性信息,下来的课程再讨论
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 4,867评论 0 9
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,754评论 0 5
  • 大家好,我是一名刚步入社会就遭遇92中年危机的千千万万咸鱼中的一条咸鱼君, 都说咸鱼没有梦想(ps...
    爱生气和没头脑阅读 1,110评论 1 1
  • 《百年孤独》是我读的第一本魔幻现实主义小说。 那是一个天色晦暗的下午,我翻开了第一页:“多年以后,面对行刑队,奥雷...
    唐門大少阅读 284评论 10 5