I try to do central Authentication microservices using Identity server 4 and invoke another API microservices with Ocelot API gateway and all of them based on docker and docker-compose but always get unauthorize 401 Error with valid Access Token. this Question is also same as my problem what I had Ocelot Identity Server: message: Request for authenticated route {api-path} by was unauthenticated
Config.cs
public static class Config
{
public static IEnumerable<ApiResource> ApiResources =>
new ApiResource[]
{
new ApiResource("scope1")
{
Scopes = new List<string>{ "scope1"},
ApiSecrets = new List<Secret>{ new Secret("supersecret".Sha256()) }
}
};
public static IEnumerable<IdentityResource> IdentityResources =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope("scope1"),
new ApiScope("scope2"),
};
public static IEnumerable<Client> Clients =>
new Client[]
{
// m2m client credentials flow client
new Client
{
ClientId = "m2m.client",
ClientName = "Client Credentials Client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedScopes = { "scope1" }
},
// interactive client using code flow + pkce
new Client
{
ClientId = "interactive",
ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = { "https://localhost:44300/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:44300/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:44300/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "scope2" }
},
};
}
and this is Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
//services.AddIdentityServer()
// .AddDeveloperSigningCredential()
// .AddInMemoryIdentityResources(Config.IdentityResources)
// .AddInMemoryApiScopes(Config.ApiScopes)
// .AddInMemoryClients(Config.Clients);
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
options.EmitStaticAudienceClaim = true;
})
.AddTestUsers(TestUsers.Users);
// in-memory, code config
builder.AddInMemoryIdentityResources(Config.IdentityResources);
builder.AddInMemoryApiScopes(Config.ApiScopes);
builder.AddInMemoryClients(Config.Clients);
builder.AddInMemoryApiResources(Config.ApiResources);
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
services.AddAuthentication()
.AddGoogle(options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
// register your IdentityServer with Google at https://console.developers.google.com
// enable the Google+ API
// set the redirect URI to https://localhost:5001/signin-google
options.ClientId = "copy client ID from Google here";
options.ClientSecret = "copy client secret from Google here";
});
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Api Microservice Startup.cs
services.AddAuthentication(
options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}
)
.AddJwtBearer(options =>
{
IdentityModelEventSource.ShowPII = true;
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "scope1";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidAudiences = new List<string>
{
"scope1"
}
};
});
Ocelot Statup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
var authenticationProviderKey = "IdentityApiKey";
//…
services.AddAuthentication()
.AddJwtBearer(authenticationProviderKey, x =>
{
x.Authority = identityUrl;
x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudiences = new[] { "scope1" }
};
});
Ocelot.js
{
"RouteIsCaseSensitive": false,
"DownstreamPathTemplate": "/api/inventory",
"DownstreamScheme": "http",
"DownstreamHostandPorts": [
// <-------------Local Host details ------------>
{
"Host": "inventoryservice",
"Port": 80
}
],
"UpstreamPathTemplate": "/inventory",
"UpstreamHttpMethod": [ "Get", "Post" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": []
}
}