I’m trying to implement an authorization code flow using Identity Server 4 but when I attempt to generate my authorization code all I get is a generic error page with nothing but the message ‘Sorry, there was an error’. (Title is ‘Error’).
I get this whether I’m using Postman or programmatically submitting a GET request with the required parameters.
To run my test, in Visual studio I start the Identity server and my API server. I start my MVC site to log in as the test user if needed and to make the callback url available. I then press the ‘Get New Access Token’ button in Postman. The result is that generic error.
I understand that when I programmatically submit the GET request the response should be the Auth Code which would be ideal but at this point I just want to successfully authenticate the client.
Can anyone see anything I might be missing?
In Postman my parameters are as follows in this image:
My Client is set up as follows:
new Client
{
ClientId = "mvc",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code ,
// where to redirect to after login
RedirectUris = { "https://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1",
IdentityServerConstants.StandardScopes.Email
}
}
My test user is this one that comes with the Identity Server Github code:
new TestUser
{
SubjectId = "88421113",
Username = "bob",
Password = "bob",
Claims =
{
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.WebSite, "http://bob.com"),
new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
}
}
My Startup for Identity Server:
public class Startup
{
public IWebHostEnvironment Environment { get; }
public Startup(IWebHostEnvironment environment)
{
Environment = environment;
}
public void ConfigureServices(IServiceCollection services)
{
// uncomment, if you want to add an MVC-based UI
services.AddControllersWithViews();
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "<insert here>";
options.ClientSecret = "<insert here>";
});
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication (options =>
{
options.Authority = "https://localhost:5001";
options.ApiName = "testapis";
});
var builder = services.AddIdentityServer(options =>
{
// see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
options.EmitStaticAudienceClaim = true;
})
.AddDeveloperSigningCredential() //This is for dev only scenarios when you don’t have a certificate to use.
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users)
.AddCustomTokenRequestValidator<CustomTokenRequestValidator>();
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
//// uncomment if you want to add MVC
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
//// uncomment, if you want to add MVC
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
2
Answers
I've finally been able to get my access tokens and from what I can tell, when the AllowedGrantType on the target client is 'ClientCredentials', you cannot request the openid or profile scopes. For my test client I had added those two scopes to the AllowedScopes list but always failed to get my auth code. If I only request an ApiScope it's fine. If the scope is an IdentityResource it will not work.
This is fine as my project requires that I implement the Code grantType which I've got working to a degree.
One problem is that you should always ask for the openid scope, not just ap1.