将IdentityServer4与WebAPI集成 [英] Integrating IdentityServer4 With WebAPI

查看:492
本文介绍了将IdentityServer4与WebAPI集成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to integrate IdentityServer4 with ASP.NET MVC WebAPI.I want to achieve role based authorization. I have the following projects running.

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

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

I have implemented the ResourceOwnerPassword flow and what I am trying to do is,

  1. 向包含用户名和密码的WebApi的 AccountController 发出 post 请求
  2. 在AccountController内部,调用IdentityServer令牌终结点以获取访问令牌,并将访问令牌返回给客户端(javascript应用)
  3. 向WebApi发出包含访问令牌的请求.
  1. Make a post request to AccountController of the WebApi containing username and password
  2. Inside the AccountController call the IdentityServer token endpoint for an access token and return the access token to the client (javascript app)
  3. Make a request to the WebApi containing the access token.

对于上面的部分,我很成功,这里是代码

For the above part I am success full, here is the code

POSTMAN登录电话

AccountController

 [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 };
        }
    }

SecurityService

  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内部还有两个操作(仅用于测试):

I have two more actions inside the AccountController (just for testing) namely:

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

  1. values() [returns success and requires no authentication]
  2. SecureValues [returns success and requires authentication]

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

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

调用"Values" 操作会返回成功,这很明显,调用"SecureValues" 会显示以下信息

calling "Values" action returns the success which is quite obvious, calling the "SecureValues" gives following

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

Which means that the user is not Authenticated.

我的 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
        });
       }

推荐答案

看来,您在UseIdentityServerBearerTokenAuthentication中间件中的授权是错误的.我认为应该是" http://localhost:5000 ".

It looks like your Authority in your UseIdentityServerBearerTokenAuthentication middleware is wrong. I think it should be "http://localhost:5000".

还可以启用日志记录(带有跟踪)到控制台,您可以看到为什么有时会挑战您的授权.

Also enabling logging (with trace) to console you can see why your authorization was challenged sometimes.

这篇关于将IdentityServer4与WebAPI集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆