I have implemented IdentityServer4 in my project. After I run it and use Postman to send a request for token I get 404 status code for not found, even though URL exists.
I want to use Implicit grant_type so I am sending only client_id using Basic Auth.
Problem can also be related to the format of request for implicit flow of OAuth 2. As I've understood the only thing you need to pass when you using this flow is client_id and use Basic authentication. Maybe I am wrong about that one?
In VisualStudio I can see that request are coming to IdentityServer
Even if I go to see debug message I don't see what kind of error is returning 404, all I got is this:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST http://localhost:44305/baseurl/connect/token 0
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.Request","time":"2017-01-06T11:02:42.0216819Z","tags":{"ai.device.roleInstance":"DESKTOP-3TKHRTV","ai.operation.id":"p4f7oSz6Ng0=","ai.user.userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36","ai.operation.name":"POST /baseurl/connect/token","ai.internal.sdkVersion":"aspnet5c:1.0.0"},"data":{"baseType":"RequestData","baseData":{"ver":2,"id":"p4f7oSz6Ng0=","name":"POST /baseurl/connect/token","startTime":"2017-01-06T11:02:42.0216819+00:00","duration":"00:00:00.0028138","success":false,"responseCode":"404","url":"https://localhost:44305/baseurl/connect/token","httpMethod":"POST","properties":{"DeveloperMode":"true"}}}}
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 48.134ms 404
Code for IdentityServer is pretty straightforward and standard:
public class Startup
{
private readonly IHostingEnvironment environment;
public Startup(IHostingEnvironment env)
{
environment = env;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var cert = new X509Certificate2(Path.Combine(environment.ContentRootPath, "idsvr3test.pfx"), "idsrv3test");
services.AddMvc();
services.AddApplicationInsightsTelemetry(Configuration);
services.AddIdentityServer()
.AddSigningCredential(cert)
.AddInMemoryIdentityResources(ClientConfig.GetIdentityResources())
.AddInMemoryApiResources(ClientConfig.GetApiResources())
.AddInMemoryClients(ClientConfig.GetClients())
.AddInMemoryUsers(ClientConfig.GetUsers());
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseApplicationInsightsRequestTelemetry();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseApplicationInsightsExceptionTelemetry();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
public class ClientConfig
{
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "mob.client",
ClientName = "Mobile client",
AllowedGrantTypes = GrantTypes.Implicit,
AccessTokenType = AccessTokenType.Jwt,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:44311/Unauthorized" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
}
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("MyLegislatureAPI", "BEE MyLegislature API")
};
}
public static List<InMemoryUser> GetUsers()
{
return new List<InMemoryUser>
{
new InMemoryUser{Subject = "818727", Username = "alice", Password = "alice",
Claims = new Claim[]
{
new Claim(JwtClaimTypes.Name, "Alice Smith"),
new Claim(JwtClaimTypes.GivenName, "Alice"),
new Claim(JwtClaimTypes.FamilyName, "Smith"),
new Claim(JwtClaimTypes.Email, "[email protected]"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.Role, "Admin"),
new Claim(JwtClaimTypes.Role, "Geek"),
new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServerConstants.ClaimValueTypes.Json)
}
},
new InMemoryUser{Subject = "88421113", Username = "bob", Password = "bob",
Claims = new Claim[]
{
new Claim(JwtClaimTypes.Name, "Bob Smith"),
new Claim(JwtClaimTypes.GivenName, "Bob"),
new Claim(JwtClaimTypes.FamilyName, "Smith"),
new Claim(JwtClaimTypes.Email, "[email protected]"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.Role, "Developer"),
new Claim(JwtClaimTypes.Role, "Geek"),
new Claim(JwtClaimTypes.WebSite, "http://bob.com"),
new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServerConstants.ClaimValueTypes.Json)
}
}
};
}
}
Does anyone sees what I am doing wrongly?
Furthermore the token endpoint can be extended to support extension grant types. IdentityServer supports a subset of the OpenID Connect and OAuth 2.0 token request parameters. For a full list, see here.
It supports the password, authorization_code, client_credentials, refresh_token and urn:ietf:params:oauth:grant-type:device_code grant types. Furthermore the token endpoint can be extended to support extension grant types. IdentityServer supports a subset of the OpenID Connect and OAuth 2.0 token request parameters.
You can use the IdentityModel client library to programmatically access the token endpoint from .NET code. For more information check the IdentityModel docs.
client identifier (required – Either in the body or as part of the authorization header.) client secret either in the post body, or as a basic authentication header.
What you're missing here is the part where you inject the Identity Server middleware in the pipeline. At the moment, all you're doing is registering the necessary services in the DI container.
In your Configure
method, you need to call app.UseIdentityServer
at some point.
Please have a look at the amazing documentation the core developers put together.
Check your IdentityServer project URL.
I see you have "baseurl" as part of your path.
mine is: http://localhost:5000/connect/token
.
To help you verify check your configuration URL to make sure that works.
mine is: http://localhost:5000/.well-known/openid-configuration
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With