【问题标题】:Integrating IdentityServer4 With WebAPI将 IdentityServer4 与 WebAPI 集成
【发布时间】:2017-04-28 04:13:30
【问题描述】:

我正在尝试将 IdentityServer4 与 ASP.NET MVC WebAPI 集成。我想实现基于角色的授权。我正在运行以下项目。

  1. IdentityServer4 [一个单独的项目]
  2. WebApi
  3. Javascript 应用程序 [使用 Extjs]

我已经实现了 ResourceOwnerPassword 流程,我想要做的是,

  1. 向包含用户名和密码的 WebApi 的 AccountController 发出 post 请求
  2. 在 AccountController 内部调用 IdentityServer 令牌端点以获取访问令牌并将访问令牌返回给客户端(javascript 应用程序)
  3. 向包含访问令牌的 WebApi 发出请求。

以上部分我已经成功了,这里是代码

POSTMAN 调用登录

帐户控制器

 [ActionName("Login")]
    [AllowAnonymous]
    [HttpPost]
    public async Task<BaseModel> Login(LoginModel model)
    {
        model.RememberMe = false;
        var status = await _security.Login(model.Email, model.Password, model.RememberMe);

        if (status.Status == LoginStatus.Succeded)
        {
            return new BaseModel { success = true, message = "login", data = status.Data };
        }
    }

安全服务

  public async Task<LoginResponse> Login(string userName, string password, bool persistCookie = false)
    {
        // discover endpoints from metadata
        var disco = await DiscoveryClient.GetAsync("http://localhost:5000");

        // request token
        var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
        var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(userName, password, "api1");

        if (tokenResponse.IsError)
        {
            return new LoginResponse { Status = LoginStatus.Failed, Message = tokenResponse.Error };
        }

        return new LoginResponse { Status = LoginStatus.Succeded, Data = tokenResponse.Json };
    }

保护 API

我在 AccountController 中还有两个操作(仅用于测试),即:

  1. values() [返回成功并且不需要身份验证]
  2. SecureValues [返回成功并需要身份验证]

    [HttpGet]
    public BaseModel values()
    {
        return new BaseModel
        {
            success = true
        };
    }
    
    [Authorize]
    [HttpGet]
    public BaseModel SecureValues()
    {
        return new BaseModel
        {
            success = true
        };
    }
    

调用 "Values" 操作返回成功,这是非常明显的,调用 "SecureValues" 会得到以下结果

这意味着用户未经过身份验证。

我的IdentityServer4配置如下:

 public class Config
{
    // scopes define the resources in your system
    public static IEnumerable<Scope> GetScopes()
    {
        return new List<Scope>
        {
            StandardScopes.OpenId,
            StandardScopes.Profile,

            new Scope
            {
                Name = "api1",
                Description = "My API",
                DisplayName = "API Access",
                Type = ScopeType.Resource,
                IncludeAllClaimsForUser = true,
                Claims = new List<ScopeClaim>
                {
                    new ScopeClaim(ClaimTypes.Name),
                    new ScopeClaim(ClaimTypes.Role)
                }
            },
           new Scope
           {
               Enabled = true,
               Name  = "role",
               DisplayName = "Role(s)",
               Description = "roles of user",
               Type = ScopeType.Identity,
               Claims = new List<ScopeClaim>
               {
                   new ScopeClaim(ClaimTypes.Role,false)
               }
           },
           StandardScopes.AllClaims
        };
    }

    // clients want to access resources (aka scopes)
    public static IEnumerable<Client> GetClients()
    {
        // client credentials client
        return new List<Client>
        {
            new Client
            {
                ClientId = "client",
                AllowedGrantTypes = GrantTypes.ClientCredentials,

                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedScopes = { "api1" }
            },

            // resource owner password grant client
            new Client
            {
                ClientId = "ro.client",
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedScopes = { "api1" }
            },

            // OpenID Connect implicit flow client (MVC)
            new Client
            {
                ClientId = "mvc",
                ClientName = "MVC Client",
                AllowedGrantTypes = GrantTypes.Implicit,

                //flow

                RedirectUris = { "http://localhost:5002/signin-oidc" },
                PostLogoutRedirectUris = { "http://localhost:5002" },

                AllowedScopes =
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    "role"
                }
            },
            //for hybrid flow
            new Client
            {
                ClientId = "mvchybrid",
                ClientName ="mvc hybrid client",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },

                RedirectUris = {"http://localhost:5003/signin-oidc"},
                PostLogoutRedirectUris = {"http://localhost:5003"},

                AllowedScopes =
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    StandardScopes.OfflineAccess.Name,
                    "api1"
                }
            },
            new Client
            {
                ClientId = "js",
                ClientName = "javascript client",
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowAccessTokensViaBrowser= true,
                RedirectUris = {"http://localhost:5004/callback.html"},
                PostLogoutRedirectUris = {"http://localhost:5004/index.html"},
                AllowedCorsOrigins = {"http://localhost:5004"},

                AllowedScopes =
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    "api1",
                    "role",
                    StandardScopes.AllClaims.Name
                }
            },
            //aspnet identity client
            new Client
            {
                ClientId = "mvcIdentity",
                ClientName = "Mvc Identity Client",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                RequireConsent = false,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                RedirectUris = {"http://localhost:5005/signin-oidc"},
                PostLogoutRedirectUris = {"http://localhost:5005"},
                AllowedScopes =
                {
                     StandardScopes.OpenId.Name,
                     StandardScopes.Profile.Name,
                     StandardScopes.OfflineAccess.Name,
                     "api1"
                }
            }
        };
    }

    public static List<InMemoryUser> GetUsers()
    {
        return new List<InMemoryUser>
        {
            new InMemoryUser
            {
                Subject = "1",
                Username = "alice@yahoo.com",
                Password = "password",

                Claims = new List<Claim>
                {
                    new Claim("name", "Alice"),
                    new Claim("website", "https://alice.com"),
                    new Claim(ClaimTypes.Role,"FreeUser")
                }
            },
            new InMemoryUser
            {
                Subject = "2",
                Username = "bob@yahoo.com",
                Password = "password",

                Claims = new List<Claim>
                {
                    new Claim("name", "Bob"),
                    new Claim("website", "https://bob.com"),
                    new Claim(ClaimTypes.Role,"PaidUser")
                }
            }
        };
    }
}

WebApi 配置

 public void ConfigureAuth(IAppBuilder app)
    {

        app.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions
        {
            Authority = "localhost:5000",
            RequiredScopes = new[] { "api1" },
            ClientId = "ro.client",
            ClientSecret = "secret",
            PreserveAccessToken = true
        });
       }

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api oauth-2.0 identityserver3 identityserver4


    【解决方案1】:

    看起来您在UseIdentityServerBearerTokenAuthentication 中间件中的权限是错误的。我认为应该是“http://localhost:5000”。

    还启用日志记录(带跟踪)到控制台,您可以看到您的授权有时会受到质疑的原因。

    【讨论】:

    • 使用IdentityServer3.AccessTokenValidation验证IdentityServer4生成的token是否正确
    • @muhammadwaqas 是的,这很好 :) 他们都验证提供者发出的令牌发出 JWT,IdentityServer3.AccessTokenValidation 是 Web Api 2.2/AspNet 4.x 中使用的中间件,其中IdentityServer4.AccessTokenValidation用于 AspNet Core 应用程序。
    • 我已将授权 URL 更正为指向 http:/localhost:5000 但问题是一样的,
    • 现在我也收到以下错误响应,无法从程序集“IdentityModel,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“IdentityModel.Client.DiscoveryResponse”。 . 我在 ObjectBrowser 中检查了我有 3 个版本的 IdentityModel 和 IdentityModel.Client.DiscoveryResponse 仅在最新版本中可用,但不知道如何强制它使用最新版本..
    • 我应该在哪里启用登录 API 或 IdentityServer?以及如何?
    猜你喜欢
    • 2019-02-17
    • 2018-09-19
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 2019-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多