将IdentityServer4与WebAPI集成 [英] Integrating IdentityServer4 With 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.
- IdentityServer4 [一个单独的项目]
- WebApi
- JavaScript应用程序[使用Extjs]
我已经实现了 ResourceOwnerPassword 流,而我想做的是
I have implemented the ResourceOwnerPassword flow and what I am trying to do is,
- 向包含用户名和密码的WebApi的 AccountController 发出 post 请求
- 在AccountController内部,调用IdentityServer令牌终结点以获取访问令牌,并将访问令牌返回给客户端(javascript应用)
- 向WebApi发出包含访问令牌的请求.
- Make a post request to AccountController of the WebApi containing username and password
- Inside the AccountController call the IdentityServer token endpoint for an access token and return the access token to the client (javascript app)
- 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:
- values()[返回成功且无需身份验证]
-
SecureValues [返回成功并需要验证]
- values() [returns success and requires no authentication]
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屋!