身份服务器4

问题描述:

入门级查询警报. IdentityServer4教程在完成这些教程之后,我得出的结论是-

Beginner level query alert. IdentityServer4 Tutorial After going through the tutorials what I inferred was that-

  1. 我创建了一个授权服务器,其工作是通过适当的身份验证为客户端颁发令牌.
  2. 我的授权服务器首先运行,并且包含有关API和客户端的信息和定义.
  3. API具有身份验证中间件,该中间件可验证传入的令牌,以确保其是否来自受信任的来源以及其范围.
  4. 客户端从授权服务器请求令牌,然后使用接收到的令牌将请求发送到API.

为此,我必须先运行授权服务器,然后运行API,然后运行客户端.我的要求是,我不需要单独运行的启动和停止服务器来进行身份验证.我有一个API,我也需要将它兼作授权服务器.这可能吗? API是否可以始终使用IdentityServer4生成令牌,对其进行验证,然后倾向于请求.

For all this, I had to run the authorization server first, the API next and then the Client. My requirement is that I don't need a start and stop server which runs separately to take care of authentication. I have one API and I need it to double as the authorization server too. Is this possible? Is it possible for the API to generate tokens, validate them and then tend to the requests, all the while using IdentityServer4.

更新2020年1月:对于在与ASP.NET Core API控制器相同的项目中使用IdentityServer4的ASP.NET Core 3.1示例,您可以查看我的 IdentityServer4, MVC控制器和AppInsights示例存储库.目的是测试AppInsights,但它确实演示了SPA存根,该存根同时调用OpenID端点(使用客户端凭据,在不建议使用的wa中)和控制器端点.

Update Jan 2020: For a ASP.NET Core 3.1 example of using IdentityServer4 in the same project as ASP.NET Core API controllers, you can have a look at my IdentityServer4 with MVC Controllers and AppInsights sample repo. It's goal was to test AppInsights, but it does demonstrate a SPA stub that calls both OpenID endpoints (⚠ in a non-recommended wa, using client credentials), and controller endpoints.

尽管通常Auth服务器将与资源服务器分开,但这不是必须的.您可以将所有内容添加到一个应用程序中.这是一个例子.

Although typically the Auth Server will be separate from the Resource Server, this doesn't need to be the case. You can just add all of it to one application. Here's an example.

  1. 创建一个新的ASP.NET Core(我使用2.0)Web API应用程序.
  2. Install-Package IdentityServer4 -Version 2.0.0-rc1(在编写rc1时是具有.NET Core 2.x支持的版本)
  3. Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
  4. 通过模板在ValuesController上设置[Authorize]
  5. 将此代码添加到app.UseMvc()上方class Startup中的Configure(...)中:

  1. Create a new ASP.NET Core (I used 2.0) Web API application.
  2. Install-Package IdentityServer4 -Version 2.0.0-rc1 (at the time of writing rc1 is the version with .NET Core 2.x support)
  3. Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
  4. Set [Authorize] on ValuesController from the template
  5. Add this code to Configure(...) in class Startup above app.UseMvc():

// calls app.UseAuthentication() for us
// See: http://docs.identityserver.io/en/release/quickstarts/6_aspnet_identity.html
app.UseIdentityServer();

  • 将此代码添加到class Startup中的ConfigureServices(...):

    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryApiResources(new[]
        {
            new ApiResource
            {
                Name = "MyApi",
                ApiSecrets = { new Secret("supersecret".Sha256()) },
                Scopes = { new Scope("myapi") },
            }
        })
        .AddInMemoryClients(new[]
        {
            new Client
            {
                ClientId = "api",
                ClientSecrets = { new Secret("supersecret".Sha256()) },
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                AllowedScopes = { "myapi" },
            }
        })
        .AddTestUsers(new List<TestUser>
        {
            new TestUser
            {
                SubjectId = "some-unique-id-12345678980",
                Username = "john",
                Password = "123456"
            }
        });
    
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(opts =>
        {
            opts.Authority = "http://localhost:51689";
            opts.Audience = "MyApi";
            opts.RequireHttpsMetadata = !env.IsDevelopment();
        });
    

  • 如果您现在 F5 该应用程序,则由于显示"401未经授权"响应,因此它将显示一个空白页面.现在,您还可以检查以下端点:http://localhost:51689/.well-known/openid-configuration(当然还有您的开发端口).

    If you now F5 the app it will show an empty page because of a "401 Unauthorized" response. You can also now check this endpoint: http://localhost:51689/.well-known/openid-configuration (with your dev port of course).

    您现在也可以执行以下操作:

    You can also do this now:

    curl -X POST \
      http://localhost:51689/connect/token \
      -H 'authorization: Basic YXBpY2xpZW50aWQ6c3VwZXJzZWNyZXQ=' \
      -H 'cache-control: no-cache' \
      -H 'content-type: application/x-www-form-urlencoded' \
      -d 'username=john&password=123456&grant_type=password'
    

    请注意,authorization标头包含表示字符串"apiclientid:supersecret"的base64编码的字符串.这应该给您这样的结果:

    Note that the authorization header contains a base64 encoded string representing the string "apiclientid:supersecret". This should give you a result like this:

    {
        "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjczODhkMjY0MDg4Y2NjOGRiZTcwODIzZGIxYzY3ZWNkIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDUwODE3OTAsImV4cCI6MTUwNTA4NTM5MCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MTY4OSIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0OjUxNjg5L3Jlc291cmNlcyIsIk15QXBpIl0sImNsaWVudF9pZCI6ImFwaWNsaWVudGlkIiwic3ViIjoic29tZS11bmlxdWUtaWQtMTIzNDU2Nzg5ODAiLCJhdXRoX3RpbWUiOjE1MDUwODE3OTAsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsibXlhcGkiXSwiYW1yIjpbInB3ZCJdfQ.sxWodlJKDJgjoOj-8njZ8kONOqiKgj3E5YlKXGX5cz-WqUK7RHKJacNX09D00Y8YtmZpkc5OrY0xzOx7UuSAtDku4oOX_1o38XEGJPBSJHdjqgVGSOU-hwDkzin8HSRJ0Kna1vM3ZzTh80cFTVhP8h903GAPRrAyV8PtRXnwV0CPel8NdvML6dV-mfDpGi0l7crp-TPnH4nIG0olpRYUPV5EsgCVMG9vswnOnKz3RPOGaU8yJy7_9mbQW5GHKfN0J6swiSt5rY3NKs_t1P9-tnCDKBOAafaXjLEO3Kx4fP4xTgwK92uKcEDDnRZo_-T0CkBxnSQm0oz1sUyrW8_3Pg",
        "expires_in": 3600,
        "token_type": "Bearer"
    }
    

    除了切换到其他身份验证流程的选项之外,您还可以添加如下所示的控制器方法:

    In addition to the option of switching to other authentication flows, you can also add a controller method like this:

    [Route("api/token")]
    public class TokenController
    {
        [HttpPost("request")]
        public async Task<JObject> Request(string username, string password)
        {
            var tokenClient = new TokenClient("http://localhost:51689/connect/token", "apiclientid", "supersecret");
            var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password);
    
            if (tokenResponse.IsError) { /* Log failed login attempt! */ } 
    
            return tokenResponse.Json;
        }
    }
    

    然后这样称呼它:

    curl -X POST \
      http://localhost:51689/api/token/request \
      -H 'cache-control: no-cache' \
      -H 'content-type: application/x-www-form-urlencoded' \
      -d 'username=john&password=123456'
    

    这应该给出与上述类似的响应.

    This should give a similar response as above.

    您现在可以像这样提供access_token insde标头Authorization: Bearer access_token_should_go_here:

    You can now provide this access_token insde a header Authorization: Bearer access_token_should_go_here like this:

    curl -X GET \
      http://localhost:51689/api/values \
      -H 'authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjczODhkMjY0MDg4Y2NjOGRiZTcwODIzZGIxYzY3ZWNkIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDUwODIyODQsImV4cCI6MTUwNTA4NTg4NCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MTY4OSIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0OjUxNjg5L3Jlc291cmNlcyIsIk15QXBpIl0sImNsaWVudF9pZCI6ImFwaWNsaWVudGlkIiwic3ViIjoic29tZS11bmlxdWUtaWQtMTIzNDU2Nzg5ODAiLCJhdXRoX3RpbWUiOjE1MDUwODIyODQsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsibXlhcGkiXSwiYW1yIjpbInB3ZCJdfQ.hQ60zzEbZOSVpP54yGAnnzfVEks18YXn3gU2wfFgNB33UxQabk1l3xkaeUPTpuFdmFTm4TbVatPaziGqaxjzYgfdVoAwQ3rYJMuYzOh0kUowKxXTkquAlD13ScpvxrGeCXGxFTRHrxX2h-1hHGQ9j2y2f3-ESynzrCdxp5HEH1271BSYfQ7pZIzvyxxpbmOzzKDzdYfcJV6ocnOU4jXBhw6iOzqpR03zxxtjIjGbJd2QwWklBGqZlO_thdZZFi-t7zu5eC4wqRCYGGZYWOUC17_Btc_Irg2SsvLCUDzsaBw7AVgLpZ7YjF-RsVqIi6oxNQ2K0zllzUy8VbupbWKr5Q' \
      -H 'cache-control: no-cache' \
    

    现在您应该超越[Authorize]属性.是的!

    And now you should get past the [Authorize] atribute. Yay!

    您现在拥有一个一个 Web应用程序,它既可以作为Auth服务器又可以作为资源服务器.

    You now have one web application, which acts as both an Auth Server and a Resource Server.

    有趣的事实:在上面的示例中,AddJwtBearer选项将应用程序自身的URL指定为Authority,从而使来自其自身的应用程序请求成为用于验证令牌的公共密钥.相反,您也可以使用代码直接将此密钥提供给身份验证中间件.

    Fun fact: with the above example the AddJwtBearer options specify the application's own url as an Authority, making the app request from itself the public key to use for validating the tokens. You could instead also use code to directly provide this key to the authentication middleware.