1. Business Scenarios
IdentityServer4 in the authorization configuration Client AllowedScopes , set the specific API site name, which is the user-set ApiName , sample code:
Authorization Center Configuration new client{ ClientId = "Client_id_1", allowedgranttypes = Granttypes.resourceownerpassword, Allowofflineaccess = True, accesstokenlifetime = 3600 * 6,//6 hours slidingrefreshtokenlifetime = 1296000,// 15 days Clientsecrets = {new Secret ("Secret"). Sha256 ()) }, allowedscopes = {"api_name1"},}//API service configuration app. Useidentityserverauthentication (new identityserverauthenticationoptions{ authority = $ "http://localhost:5000 ", apiname =" Api_name1 ", Requirehttpsmetadata = false});
The above two api_name1 configurations to be consistent, the problem comes, because the authorization center scope configuration is the entire API service, if we have multiple Client configurations, such as a foreground and background, and then need access api_name1 , there will be some problems.
For example, api_name1 an interface service configuration code in the service:
[Authorize ()] [Route ("Api/values")] [Httpget]public iactionresult Get () {return Ok ();}
Authorize()Configuration, which indicates that the api/values interface requires access after authorization, if the authorization center is configured with two Client (foreground and background), and scope both are included, there are api_name1 two scenarios:
Front Client and back office Client , both require authorization after Access api/values interface: no problem.
Front desk Client does not need authorization after access, background Client need authorization after access: There is a problem, the front desk has Client no way to access, because the api/values interface set up Authorize() .
In fact, the explanation is white, is how to let the API service specify Client authorized access? For example: [Authorize(ClientId = 'client_id_1')] .
2. Solution
There is no [Authorize(ClientId = 'client_id_1')] such solution, but it can be used [Authorize(Roles = 'admin')] .
The code for the Authorization center is ResourceOwnerPasswordValidator modified as follows:
public class Resourceownerpasswordvalidator:iresourceownerpasswordvalidator{private ReadOnly Iuserservice _ Userservice;public resourceownerpasswordvalidator (Iuserservice userservice) { _userservice = UserService; } Public async Task Validateasync (resourceownerpasswordvalidationcontext context) {var user = await _ Userservice.login (context. UserName, context. Password); if (user! = null) {var claims = new List<claim> () {New Claim ("Role", "admin")};//According to the user object, set different R Olecontext. Result = new Grantvalidationresult (user. Userid.tostring (), OidcConstants.AuthenticationMethods.Password, claims);}}
The configuration of the authorization center is startup modified as follows
var builder = Services. Addidentityserver (); builder. Addtemporarysigningcredential ()//. Addinmemoryidentityresources (Config.getidentityresources ()). Addinmemoryapiresources (New list<apiresource> {new Apiresource ("Api_name1", "Api1") {userclaims = new List <string> {"Role"}},//Add role claimnew Apiresource ("Api_name2", "Api2") {userclaims = new list<string> {"Role "}} }) . Addinmemoryclients (Config.getclients ());
API Service interface, you only need to configure the following:
[Authorize ()] [Route ("Api/values")] [Httpget]public iactionresult Get () {return Ok ();} [Authorize (Roles = "admin")] [Route ("Api/values2")] [Httpget]public iactionresult Get2 () {return Ok ();} [Authorize (Roles = "Admin,normal")] [Route ("Api/values3")] [Httpget]public iactionresult Get3 () {return Ok ();}
It is important to note that api/values although the interface is not set up specifically Roles , it Role can be accessed by each.