This is my config for krakend.json
"async_agent": [
{
"name": "test-agent",
"connection": {
"max_retries": 10,
"backoff_strategy": "exponential-jitter"
},
"consumer": {
"topic": "krakend",
"workers": 5
},
"backend": [
{
"url_pattern": "/greeted",
"method": "POST",
"host": [ "http://127.0.0.1:2999" ],
"disable_host_sanitize": false
}
],
"extra_config": {
"async/amqp": {
"host": "amqp://guest:guest#localhost:5672/",
"name": "krakend",
"exchange": "ApiGatewayExchange",
"durable": true,
"delete": false,
"exclusive": false,
"no_wait": false,
"auto_ack": false
}
}
}
]
Messages are sent from service-a like so:
export class AppService {
constructor(#Inject('GREETING_SERVICE') private client: ClientProxy){}
getHello(): ResponseDTO {
const responseDTO: ResponseDTO = {
action: 'Hello',
service: 'from service A'
}
this.client.emit('', responseDTO);
return responseDTO;
}
}
And imported GREETING_SERVICE config like so:
imports: [
ClientsModule.register([
{
name: 'GREETING_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://test:test#localhost:5672/'],
queue: 'krakend'
}
}
])
],
Lastly, this is the endpoint in another service (let's call this service-c) that gets that message from the consumer:
#Post('greeted')
TestHello(#Body() data: any) {
console.log(data)
return data
}
The message is successfully consumed as set by the async_agent in my krakend file, but the message isn't posted as a body to that endpoint. When I did a console.log of that data supposedly passed, it just prints {}.
Am I doing anything wrong here? Been scratching my head for hours.
The async part of your krakend.json configuration looks good to me, but I am suspecting about the problem you might have.
Most of the javascript frameworks today will require you to pass specific headers to work their magic like Content-Type or Accept. You have to take into account that KrakenD will pass a very reduced set of headers to your NestJS application (Accept-Encoding and User-Agent as far as I can remember).
I am unfamiliar with NestJS, but I would bet that you need to pass the Content-Type and you are good to go. Here's my suggestion of configuration:
"async_agent": [
{
"name": "test-agent",
"connection": {
"max_retries": 10,
"backoff_strategy": "exponential-jitter"
},
"consumer": {
"topic": "krakend",
"workers": 5
},
"backend": [
{
"url_pattern": "/greeted",
"method": "POST",
"host": [
"http://127.0.0.1:2999"
],
"disable_host_sanitize": false,
"extra_config": {
"modifier/martian": {
"header.Modifier": {
"scope": [
"request"
],
"name": "Content-Type",
"value": "application/json"
}
}
}
}
],
"extra_config": {
"async/amqp": {
"host": "amqp://guest:guest#localhost:5672/",
"name": "krakend",
"exchange": "ApiGatewayExchange",
"durable": true,
"delete": false,
"exclusive": false,
"no_wait": false,
"auto_ack": false
}
}
}
]
}
Hope this helps
I have created an asp.net core web application with individual accounts security and configure it to be used for authorization/authentication of the external spa i have added following configuration in appset5tings.json file
{
"ConnectionStrings":
{
"DefaultConnection":
"Server=localhost;Database=itrSts;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"IdentityServer": {
"Clients": {
"itr.childcare.webapp": {
"Profile": "SPA",
"RedirectUri": "http://localhost:3000/signin-callback",
"LogoutUri": "http://localhost:3000/signout-callback",
"AccessTokenLifetime": 600,
"Scopes": "openid profile gateway-api roles"
},
"Itr.Sts": {
"Profile": "IdentityServerSPA"
}
}
"Resources": {
"gateway-api": {
"Profile": "API",
"UserClaims": [
"role"
]
}
}
}
}
It works fine when "openid profile gateway-api" scopes are requested but when roles scope is also requested i get invalid scope error can anyone help me and tell what should i should do? Thanks
What is missing is the Identity Resource definitions. They define what claims (including Roles) that should be available to the clients.
See this article about Identity Resources.
If you are using IdentityServer4, version 4.x, then you should also look into defining ApiScopes.
In code, the definition for IdentityResources can look like this:
var employeeInfoScope = new IdentityResource()
{
Name = "employee_info",
DisplayName = "Employee information",
Description = "Employee information including seniority and status...",
Emphasize = true,
Enabled = true,
Required = true,
ShowInDiscoveryDocument = true,
UserClaims = new List<string>
{
"employment_start",
"seniority",
"contractor",
"employee",
}
};
_identityResources = new List<IdentityResource>()
{
new IdentityResources.OpenId(),
new IdentityResources.Email(),
new IdentityResources.Profile(),
new IdentityResources.Address(),
employeeInfoScope
};
I am using IdentityServer4 (version 3.0.2.0) and facing no client id issue. The exact error is
ERROR| No client with id 'myclientId' found. aborting
Startup.cs of IdentityServer4 project
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// .AddInMemoryCaching()
.AddInMemoryApiResources(Configuration.GetSection("IdentityServer:ApiResources"))
.AddInMemoryClients(Configuration.GetSection("IdentityServer:Clients"))
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = Convert.ToBoolean(Configuration["CleanUp:IsEnabled"]);
options.TokenCleanupInterval = Convert.ToInt32(Configuration["CleanUp:Interval"]); // interval in seconds
});
Also, I have sha256 converted client_secret in appsettings.json file, sample appsettings.json
"IdentityServer": {
"ApiResources": [
{
"Name": "myapi",
"DisplayName": "my api",
"Scopes": [
{
"Name": "mycustomscope"
},
{
"Name": "openid"
}
],
"ApiSecrets": [
{
"Value": "my sha256 converted secret string",
"Description": "my api"
}
]
}
],
"Clients": [
{
"Enabled": true,
"ClientId": "myclientId",
"AccessTokenLifetime": 100000000,
"ProtocolType": "oidc",
"RequireClientSecret": true,
"IdentityTokenLifetime": 300,
"AuthorizationCodeLifetime": 300,
"ConsentLifetime": 300,
"AbsoluteRefreshTokenLifetime": 2592000,
"SlidingRefreshTokenLifetime": 1296000,
"RefreshTokenExpiration": true,
"AlwaysSendClientClaims": false,
"ClientName": "myclientId",
"ClientSecrets": [
{
"Value": "my sha256 converted secret string",
"Type": "SharedSecret"
}
],
"AllowedGrantTypes": [ "client_credentials", "password" ],
"AllowedScopes": [ "mycustomscope", "openid" ],
"RequireConsent": true
}
]
}
Sample token request from postman/JMeter
url: https://myip:port/myappPool/connect/token
method type: POST
Parameters are:
{
"client_id":"myclientId",
"client_secret": "plaintext secret",
"username":"abcdefghijkl",
"scope":"mycustomscope",
"device_id":"custom property",
"password": "mypassword",
"grant_type":"password",
"app_version":"custom property",
"hashed_value":"custom property"
}
I am posting answer to my own question because I have solved the issue. For me below given field was making an issue. After removing this field, the code ran just fine.
"RefreshTokenExpiration": true
Turns out, IdentityServer4.Models.Client does not have any boolean field named RefreshTokenExpiration but class object.
I have Kestrel section in appsettings.json and I also call ConfigureKestrel() in Program.cs. When I run the app, there is an error:
11:10:36 [Warning] () Overriding address(es) '"https://localhost:5003"'. Binding to endpoints defined in "UseKestrel()" instead.
11:10:36 [Fatal] () Unable to start Kestrel.
System.IO.IOException: Failed to bind to address https://[::]:5003: address already in use. ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use ---> System.Net.Sockets.SocketException: Address already in use
Here is my appsettings.json:
"Kestrel": {
"Endpoints": {
"HttpsInlineCertFile": {
"Url": "https://localhost:5003",
"Certificate": {
"Path": "/tmp/localhost.pfx",
"Password": "password"
}
},
"HttpsDefaultCert": {
"Url": "https://localhost:5003"
},
"Https": {
"Url": "https://*:5003",
"Certificate": {
"Path": "/tmp/localhost.pfx",
"Password": "password"
}
}
},
"Certificates": {
"Default": {
"Path": "/tmp/localhost.pfx",
"Password": "password"
}
}
},
Here is my ConfigureKestrel():
.ConfigureKestrel((context, options) =>
{
options.Listen(IPAddress.Any, 5003, listenOptions =>
{
listenOptions.UseHttps(o => o.SslProtocols = SslProtocols.Tls12);
listenOptions.UseConnectionLogging();
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});
});
OR:
.ConfigureKestrel((context, options) =>
{
options.Configure(context.Configuration.GetSection("Kestrel"))
.Endpoint("Https", listenOptions =>
{
listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
listenOptions.ListenOptions.UseConnectionLogging();
listenOptions.ListenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});
});
So, which is which? I am confused. Can I do everything in appsettings.json?
Update: I have figured out how to configure other options in appsettings.json except 2: listenOptions.HttpsOptions.SslProtocols and UseConnectionLogging
I am using postman and I am trying to get the users list from identity Manager. But I am unable to configure the app correctly. I try to get the users from https://localhost/idm/api/users
I get the token with the API+idmgr+openid scopes and I have the Administrator role in my claims.
Here is the startup file:
namespace WebHost
{
internal class Startup
{
public void Configuration(IAppBuilder app)
{
LogProvider.SetCurrentLogProvider(new NLogLogProvider());
string connectionString = ConfigurationManager.AppSettings["MembershipRebootConnection"];
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseOpenIdConnectAuthentication(new Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
Authority = "https://localhost/ids",
ClientId = "postman",
RedirectUri = "https://localhost",
ResponseType = "id_token",
UseTokenLifetime = false,
Scope = "openid idmgr",
SignInAsAuthenticationType = "Jwt",
Notifications = new Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
n.AuthenticationTicket.Identity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
return Task.FromResult(0);
}
}
});
X509Certificate2 cert = Certificate.Get();
app.Map("/idm", adminApp =>
{
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AllowedAudiences = new string[] { "https://localhost/ids" + "/resources" },
AuthenticationType = "Jwt",
IssuerSecurityTokenProviders = new[] {
new X509CertificateSecurityTokenProvider("https://localhost/ids", cert)
},
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active
});
var factory = new IdentityManagerServiceFactory();
factory.Configure(connectionString);
var securityConfig = new ExternalBearerTokenConfiguration
{
Audience = "https://localhost/ids" + "/resources",
BearerAuthenticationType = "Jwt",
Issuer = "https://localhost/ids",
SigningCert = cert,
Scope = "openid idmgr",
RequireSsl = true,
};
adminApp.UseIdentityManager(new IdentityManagerOptions()
{
Factory = factory,
SecurityConfiguration = securityConfig
});
});
app.Map(ConfigurationManager.AppSettings["IdentityServerSuffix"], core =>
{
IdentityServerServiceFactory idSvrFactory = Factory.Configure();
idSvrFactory.ConfigureCustomUserService(connectionString);
var options = new IdentityServerOptions
{
SiteName = "Login",
SigningCertificate = Certificate.Get(),
Factory = idSvrFactory,
EnableWelcomePage = true,
RequireSsl = true
};
core.UseIdentityServer(options);
});
}
}
}
What Am I missing?
For those who may want to know how I did it, well I made a lot of search about Owin stuff and how Identity Server works and find out my problem was not that far.
I removed the JwtSecurityTokenHandler.InboundClaimTypeMap
I removed the UseOpenId stuff (don't remove it if you are using an openId external login provider (if you are using google, facebook or twitter, there is classes for that, just install the nuget, it's pretty straight forward)
This section let you configure the bearer token which is the default type token i used in my app(I decided to use password authentication to simplify Postman request to do automatic testing but I still user Code authentication in my apps)
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["AuthorityUrl"],
ValidationMode = ValidationMode.ValidationEndpoint,
RequiredScopes = new[] { ConfigurationManager.AppSettings["ApiScope"] }
});
I have disabled the IdentityManagerUi interface as I was planning to use the API
app.Map(ConfigurationManager.AppSettings["IdentityManagerSuffix"].ToString(), idmm =>
{
var factory = new IdentityManagerServiceFactory();
factory.Configure(connectionString);
idmm.UseIdentityManager(new IdentityManagerOptions()
{
DisableUserInterface = true,
Factory = factory,
SecurityConfiguration = new HostSecurityConfiguration()
{
HostAuthenticationType = Constants.BearerAuthenticationType
}
});
});
And I configure the Identity Server like this:
app.Map(ConfigurationManager.AppSettings["IdentityServerSuffix"], core =>
{
IdentityServerServiceFactory idSvrFactory = Factory.Configure();
idSvrFactory.ConfigureCustomUserService(connectionString);
var options = new IdentityServerOptions
{
SiteName = ConfigurationManager.AppSettings["SiteName"],
SigningCertificate = Certificate.Get(),
Factory = idSvrFactory,
EnableWelcomePage = true,
RequireSsl = true,
};
core.UseIdentityServer(options);
});
In IdentityServerServiceFactory I call this chunk of code:
var clientStore = new InMemoryClientStore(Clients.Get());
And the code for the Client should be something like:
public static Client Get()
{
return new Client
{
ClientName = "PostMan Application",
ClientId = "postman",
ClientSecrets = new List<Secret> {
new Secret("ClientSecret".Sha256())
},
Claims = new List<Claim>
{
new Claim("name", "Identity Manager API"),
new Claim("role", IdentityManager.Constants.AdminRoleName),
},
**Flow = Flows.ResourceOwner**, //Password authentication
PrefixClientClaims = false,
AccessTokenType = AccessTokenType.Jwt,
ClientUri = "https://www.getpostman.com/",
RedirectUris = new List<string>
{
"https://www.getpostman.com/oauth2/callback",
//aproulx - 2015-11-24 -ADDED This line, url has changed on the postman side
"https://app.getpostman.com/oauth2/callback"
},
//IdentityProviderRestrictions = new List<string>(){Constants.PrimaryAuthenticationType},
AllowedScopes = new List<string>()
{
"postman",
"IdentityManager",
ConfigurationManager.AppSettings["ApiScope"],
Constants.StandardScopes.OpenId,
IdentityManager.Constants.IdMgrScope,
}
};
}
On the postman side just do:
POST /ids/connect/token HTTP/1.1
Host: local-login.net
Cache-Control: no-cache
Postman-Token: 33e98423-701f-c615-8b7a-66814968ba1a
Content-Type: application/x-www-form-urlencoded
client_id=postman&client_secret=SecretPassword&grant_type=password&scope=APISTUFF&username=apiViewer&password=ICanUseTheApi
Hope that it will help somebody
Shaer,
I saw your comment and because of that I've created a project (make sure you clone the postmanexample branch) where you can see a working example related to Alegrowin's post. The idea is use postman to access the IdentityManager Api.
Steps
Open postman and choose the POST verb
Put this as url: https://localhost:44337/ids/connect/token
In header put key = Content-Type and value = application/x-www-form-urlencoded
In the body, choose raw and paste this client_id=postman&client_secret=ClientSecret&grant_type=password&scope=idmgr&username=admin&password=admin
Hit send
After this you are going to receive something like this
{"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJjbGllbnRfaWQiOiJwb3N0bWFuIiwic2NvcGUiOiJpZG1nciIsInN1YiI6Ijk1MWE5NjVmLTFmODQtNDM2MC05MGU0LTNmNmRlYWM3YjliYyIsImFtciI6WyJwYXNzd29yZCJdLCJhdXRoX3RpbWUiOjE1MDU1ODg1MTgsImlkcCI6Imlkc3J2IiwibmFtZSI6IkFkbWluIiwicm9sZSI6IklkZW50aXR5TWFuYWdlckFkbWluaXN0cmF0b3IiLCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDMzNy9pZHMiLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo0NDMzNy9pZHMvcmVzb3VyY2VzIiwiZXhwIjoxNTA1NTkyMTE4LCJuYmYiOjE1MDU1ODg1MTh9.h0KjlnKy3Ml-SnZg6cYSPJW4XxsOFxDB8K9JY4Zx_I1KbMQxctjkDrTVfSylfjFXlwpyBD-qqfxmRkOKsz_6zSZneaJpyWsJt2FTqCNOWJJV9BdPbViWcM_vADFkVpwiiSaTCv7k08xwj8StGCq5zlYLU68k8awYpXzgpz0O8zPZpfc0oSN3ZQJVFEKBfE4ATbPo6ut2i0_Y3lPbQiwjXJgA_wwp-W0L3zY8A5rfYSwKU0KzS51BKBSn6svBCjTu84Dm2KM-zlManMar1Ybjoy108Xvuliq_zBNdbeEt-Daau_RNrasw1tya_cZicK85IB1TJdUSKPGwNG5xEirNzg",
"expires_in": 3600,
"token_type": "Bearer"}
Copy the access token and create a GET request
Put this as url: https://localhost:44337/idm/api/users?count=10&start=0
Into the headers put key = Authorization and value = Bearer [paste the token]
Example
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJjbGllbnRfaWQiOiJwb3N0bWFuIiwic2NvcGUiOiJpZG1nciIsInN1YiI6Ijk1MWE5NjVmLTFmODQtNDM2MC05MGU0LTNmNmRlYWM3YjliYyIsImFtciI6WyJwYXNzd29yZCJdLCJhdXRoX3RpbWUiOjE1MDU1ODg1MTgsImlkcCI6Imlkc3J2IiwibmFtZSI6IkFkbWluIiwicm9sZSI6IklkZW50aXR5TWFuYWdlckFkbWluaXN0cmF0b3IiLCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDMzNy9pZHMiLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo0NDMzNy9pZHMvcmVzb3VyY2VzIiwiZXhwIjoxNTA1NTkyMTE4LCJuYmYiOjE1MDU1ODg1MTh9.h0KjlnKy3Ml-SnZg6cYSPJW4XxsOFxDB8K9JY4Zx_I1KbMQxctjkDrTVfSylfjFXlwpyBD-qqfxmRkOKsz_6zSZneaJpyWsJt2FTqCNOWJJV9BdPbViWcM_vADFkVpwiiSaTCv7k08xwj8StGCq5zlYLU68k8awYpXzgpz0O8zPZpfc0oSN3ZQJVFEKBfE4ATbPo6ut2i0_Y3lPbQiwjXJgA_wwp-W0L3zY8A5rfYSwKU0KzS51BKBSn6svBCjTu84Dm2KM-zlManMar1Ybjoy108Xvuliq_zBNdbeEt-Daau_RNrasw1tya_cZicK85IB1TJdUSKPGwNG5xEirNzg
Hit send
You should receive something like this
{
"data": {
"items": [
{
"data": {
"subject": "081d965f-1f84-4360-90e4-8f6deac7b9bc",
"username": "alice",
"name": "Alice Smith"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/081d965f-1f84-4360-90e4-8f6deac7b9bc",
"delete": "https://localhost:44337/idm/api/users/081d965f-1f84-4360-90e4-8f6deac7b9bc"
}
},
{
"data": {
"subject": "5f292677-d3d2-4bf9-a6f8-e982d08e1306",
"username": "bob",
"name": "Bob Smith"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/5f292677-d3d2-4bf9-a6f8-e982d08e1306",
"delete": "https://localhost:44337/idm/api/users/5f292677-d3d2-4bf9-a6f8-e982d08e1306"
}
},
{
"data": {
"subject": "e3c7fd2b-3942-456f-8871-62e64c351e8c",
"username": "xoetuvm",
"name": "Uylocms Xcyfhpc"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/e3c7fd2b-3942-456f-8871-62e64c351e8c",
"delete": "https://localhost:44337/idm/api/users/e3c7fd2b-3942-456f-8871-62e64c351e8c"
}
},
{
"data": {
"subject": "0777d8de-91be-41e2-82ae-01c4576c7aca",
"username": "xdbktbb",
"name": "Qbcqwrg Mypxduu"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/0777d8de-91be-41e2-82ae-01c4576c7aca",
"delete": "https://localhost:44337/idm/api/users/0777d8de-91be-41e2-82ae-01c4576c7aca"
}
},
{
"data": {
"subject": "10d2760a-2b3f-4912-af2a-2bcd9d113af9",
"username": "acrkkzf",
"name": "Qcmwcha Kdibtke"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/10d2760a-2b3f-4912-af2a-2bcd9d113af9",
"delete": "https://localhost:44337/idm/api/users/10d2760a-2b3f-4912-af2a-2bcd9d113af9"
}
},
{
"data": {
"subject": "5e16f086-a487-4429-b2a6-b05a739e1e71",
"username": "wjxfulk",
"name": "Eihevix Bjzjbwz"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/5e16f086-a487-4429-b2a6-b05a739e1e71",
"delete": "https://localhost:44337/idm/api/users/5e16f086-a487-4429-b2a6-b05a739e1e71"
}
},
{
"data": {
"subject": "256e23de-410a-461d-92cc-55684de8be6f",
"username": "zputkfb",
"name": "Vhwjjpd Stfpoum"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/256e23de-410a-461d-92cc-55684de8be6f",
"delete": "https://localhost:44337/idm/api/users/256e23de-410a-461d-92cc-55684de8be6f"
}
},
{
"data": {
"subject": "725cc088-96c3-490d-bc66-a376c8ca34ff",
"username": "teshydj",
"name": "Tirsnex Tdlkfii"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/725cc088-96c3-490d-bc66-a376c8ca34ff",
"delete": "https://localhost:44337/idm/api/users/725cc088-96c3-490d-bc66-a376c8ca34ff"
}
},
{
"data": {
"subject": "ac773092-e3db-4711-9c95-a2a57c1ff25f",
"username": "blulsuj",
"name": "Puuncng Lbmlcsb"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/ac773092-e3db-4711-9c95-a2a57c1ff25f",
"delete": "https://localhost:44337/idm/api/users/ac773092-e3db-4711-9c95-a2a57c1ff25f"
}
},
{
"data": {
"subject": "81f878b1-016e-4fea-9929-54e3b1d55cce",
"username": "yeqwlfy",
"name": "Qtfimdr Sxvgizd"
},
"links": {
"detail": "https://localhost:44337/idm/api/users/81f878b1-016e-4fea-9929-54e3b1d55cce",
"delete": "https://localhost:44337/idm/api/users/81f878b1-016e-4fea-9929-54e3b1d55cce"
}
}
],
"start": 0,
"count": 10,
"total": 18806,
"filter": null
},
"links": {
"create": {
"href": "https://localhost:44337/idm/api/users",
"meta": [
{
"type": "username",
"name": "Username",
"dataType": 0,
"required": true
},
{
"type": "password",
"name": "Password",
"dataType": 1,
"required": true
},
{
"type": "name",
"name": "Name",
"dataType": 0,
"required": true
},
{
"type": "Age",
"name": "Age",
"dataType": 4,
"required": true
},
{
"type": "IsNice",
"name": "IsNice",
"dataType": 5,
"required": true
},
{
"type": "role.admin",
"name": "Is Administrator",
"dataType": 5,
"required": true
}
]
}
}
}
Kind regards
Daniel