I am attempting to get a token from a .net core api controller using a password with identity server 4. I am receiving Error invalid_client.
here is the controller.
[HttpGet]
public async Task<IActionResult> Get()
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("https://localhost:44321");
var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "htmlClient",
ClientSecret = "secretpassword",
UserName = "[email protected]",
Password = "password",
Scope = "WebApi.ReadAccess"
});
return Ok();
}
here is the config
public class Config
{
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource(
"WebApi.ReadAccess",
"WebApi API",
new List<string> {
JwtClaimTypes.Id,
JwtClaimTypes.Email,
JwtClaimTypes.Name,
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName
}
),
new ApiResource("WebApi.FullAccess", "WebApi API")
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
Enabled = true,
ClientName = "HTML Page Client",
ClientId = "htmlClient",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secretpassword")
},
AllowedScopes = { "WebApi.ReadAccess" }
}
};
}
}
in startup.cs in configureServices
services.AddIdentityServer()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddProfileService<ProfileService>()
.AddDeveloperSigningCredential();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme =
JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme =
JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.Authority = "https://localhost:44321";
o.Audience = "WebApi.ReadAccess";
o.RequireHttpsMetadata = false;
});
and in configure I have app.UseIdentityServer();
public void Configure(IApplicationBuilder app, IHostingEnvironment env, BooksContext booksContext)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseIdentityServer();
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options =>
options.SwaggerEndpoint("/swagger/v2/swagger.json", "Book Chapter Service"));
app.UseDefaultFiles();
app.UseStaticFiles();
}
Try changing your code to following. I have given the generic code, you can change it according to your need.
return new List<ApiResource>
{
new ApiResource
{
Name = "api",
DisplayName = "WebApi API",
Scopes =
{
new Scope("WebApi.ReadAccess", "Read write access to web api")
}
},
new ApiResource
{
Name = "api",
DisplayName = "WebApi API",
Scopes =
{
new Scope("WebApi.FullAccess", "Full access to web api")
}
}
}
and
o.Audience = "api";
The reason being, Your o.Audience name should match ApiResource.Name because it indicates mapping between your authority and audience. For example in your case Authority https://localhost:44321 has audience lets say called "api". "api" also is a name of your ApiResource which is giving authority to create access token. Hope this helps!