I'm trying to understand how this works, so please bear with me.
Here is my config for identity server:
public static IEnumerable<ApiResource> GetApiResources(IConfiguration configuration)
{
return new []
{
new ApiResource
{
Name = "invoices.api",
ApiSecrets =
{
new Secret("invoices.api.secret".Sha256()),
},
Scopes =
{
new Scope("invoices.api.scope"),
},
UserClaims =
{
"custom_role",
}
}
};
}
public static IEnumerable<Client> GetClients(IConfiguration configuration)
{
return new []
{
new Client
{
ClientId = "invoices.ui",
RequireConsent = false,
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AccessTokenType = AccessTokenType.Reference,
AllowedCorsOrigins = configuration.GetSection("Redirect").Get<RedirectOptions>().AllowedCorsOrigins.ToList(),
RedirectUris = configuration.GetSection("Redirect").Get<RedirectOptions>().RedirectUris.ToList(),
PostLogoutRedirectUris = configuration.GetSection("Redirect").Get<RedirectOptions>().PostLogoutRedirectUris.ToList(),
ClientSecrets =
{
new Secret("invoices.ui.secret".Sha256())
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
"invoices.api.scope",
},
}
};
}
public static IEnumerable<TestUser> GetUsers(IConfiguration configuration)
{
return new []
{
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "123",
Claims =
{
new Claim("custom_role", "user"),
},
},
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "123",
Claims =
{
new Claim("custom_role", "admin"),
},
}
};
}
public static IEnumerable<IdentityResource> GetIdentityResources(IConfiguration configuration)
{
return new []
{
new IdentityResources.OpenId(),
};
}
And this is how my MVC client is setup:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(opts =>
{
//opts.ExpireTimeSpan = TimeSpan.FromSeconds(60);
})
.AddOpenIdConnect("oidc", opts =>
{
opts.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
opts.DisableTelemetry = true;
opts.Authority = Configuration.GetValue<string>("IdentityServer");
opts.RequireHttpsMetadata = false;
opts.ClientId = "invoices.ui";
opts.ClientSecret = "invoices.ui.secret";
opts.ResponseType = "code id_token";
opts.SaveTokens = true;
opts.GetClaimsFromUserInfoEndpoint = true;
opts.Scope.Clear();
opts.Scope.Add("openid");
opts.Scope.Add("invoices.api.scope");
});
After a user is authenticated, i'm trying to see it's claims in view like this:
#foreach (var claim in User.Claims)
{
<dt>#claim.Type</dt>
<dd>#claim.Value</dd>
}
But the list doesn't contain any "custom_role" claim.
The identity server logs shows that the user info has been requested by the client from user info endpoint, but my "custom_role" wasn't transfered there, however it shows in logs of identity server, that user has it.
How to access my custom claims in my MVC app?
I need to get them from user endpoint and use for authorization.
If you ask for an Access Token and Identity Token ("code id_token") Identity Server will not include user claims by default.
The solution is to set AlwaysIncludeUserClaimsInIdToken to true. See http://docs.identityserver.io/en/release/reference/client.html
The explanation on why this settings exists is here: https://leastprivilege.com/2016/12/14/optimizing-identity-tokens-for-size/
Seems that adding an identity resource with specified claims solves the problem even with built-in ProfileService implementation:
public static IEnumerable<IdentityResource> GetIdentityResources(IConfiguration configuration)
{
return new []
{
new IdentityResources.OpenId(),
new IdentityResource
{
Name = "roles.scope",
UserClaims =
{
"custom_role",
}
}
};
}
Also added it as a scope for a client:
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
"invoices.api.scope",
"roles.scope",
},
Related
###I am using identity server 4 for authentication for .net and angular apps.
if I log out from one client it does not log out from others.###
how can I delete the user session and implement single-signout for all clients
#the config class in identity server#
//MVC Client
new Client
{
ClientName = ".NET 4 MVC website",
ClientId = "net4mvcclient",
ClientSecrets =
{
new Secret("secret3".Sha256())
},
//Grant types are a way to specify how a client wants to interact with IdentityServer
AllowedGrantTypes = GrantTypes.Implicit,
RequireConsent = false,
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
RedirectUris = { $"{_config.GetValue<string>("IdentityServerSettings:MVCBaseUri")}/signin-oidc" },
PostLogoutRedirectUris = { $"{_config.GetValue<string>("IdentityServerSettings:MVCBaseUri")}/" },
AllowedScopes = {"openid", "profile", "offline_access", "api1", "api2" } ,
AllowedCorsOrigins = {$"{_config.GetValue<string>("IdentityServerSettings:MVCBaseUri")}"},
AccessTokenLifetime = 50000
},
//angular_spa
new Client {
RequireConsent = false,
ClientId = "angular_spa",
ClientName = "Angular SPA",
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = { "openid", "profile", "offline_access", "api1", "api2" },
RedirectUris = { $"{_config.GetValue<string>("IdentityServerSettings:AngularBaseUri")}/#auth-callback/#" },
PostLogoutRedirectUris = { $"{_config.GetValue<string>("IdentityServerSettings:AngularBaseUri")}/" },
AllowedCorsOrigins = { $"{_config.GetValue<string>("IdentityServerSettings:AngularBaseUri")}" },
AllowAccessTokensViaBrowser = true,
AccessTokenLifetime = 3600
}
};
startup class in MVC client
public void ConfigureIdentityServer(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
Authority = ConfigurationManager.AppSettings["IdentityServerUrl"], //Identity server Url
ClientId = "net4mvcclient",
ClientSecret = "secret3",
RedirectUri = ConfigurationManager.AppSettings["HourlyMVCUrl"] +"/signin-oidc", //Net4MvcClient's URL
PostLogoutRedirectUri = ConfigurationManager.AppSettings["HourlyMVCUrl"]+"/", //MVC Client URL
ResponseType = "id_token token",
RequireHttpsMetadata = false,
Scope = "openid profile api1 api2 offline_access",
TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
NameClaimType = "name"
},
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
n.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
n.AuthenticationTicket.Identity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
return Task.FromResult(0);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var id_token_claim = n.OwinContext.Authentication.User.Claims.FirstOrDefault(x => x.Type == "id_token");
if (id_token_claim != null)
{
n.ProtocolMessage.IdTokenHint = id_token_claim.Value;
}
}
return Task.FromResult(0);
}
}
});
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
app.UseNLog((eventType) => LogLevel.Debug);
}
#the logout function in identity server#
public async Task<IActionResult> Logout(LogoutInputModel model)
{
// build a model so the logged out page knows what to display
var vm = await BuildLoggedOutViewModelAsync(model.LogoutId);
if (User?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
// Request.GetOwinContext().Authentication.SignOut();
await HttpContext.SignOutAsync();
await _signInManager.SignOutAsync();
// raise the logout event
await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
}
// check if we need to trigger sign-out at an upstream identity provider
if (vm.TriggerExternalSignout)
{
// build a return URL so the upstream provider will redirect back
// to us after the user has logged out. this allows us to then
// complete our single sign-out processing.
string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
// this triggers a redirect to the external provider for sign-out
return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
}
if (vm.PostLogoutRedirectUri != null)
{
return SignOut(new AuthenticationProperties { RedirectUri = vm.PostLogoutRedirectUri }, vm.ExternalAuthenticationScheme);
}
return View("LoggedOut", vm);
}
I've been trying to setup a project with IdentityServer4 for a while. However I'm getting the following error:
Sso.Application.CentralHandler: Information: AuthenticationScheme: central was challenged.
IdentityServer4.Hosting.IdentityServerMiddleware: Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize
IdentityServer4.Validation.AuthorizeRequestValidator: Error: Unknown client or not enabled: oauthClient
IdentityServer4.Endpoints.AuthorizeEndpoint: Error: Request validation failed
IdentityServer4.Endpoints.AuthorizeEndpoint: Information: {
"SubjectId": "anonymous",
"RequestedScopes": "",
"PromptMode": "",
"Raw": {
"client_id": "oauthClient",
"scope": "weatherforecasts.read",
"response_type": "code",
"redirect_uri": "https://localhost:44375/signin-central",
"code_challenge": "Rdi0rU5OkG1gWzh9xfvOxbZLiGbDHqujbMzl9d3u7Qs",
"code_challenge_method": "S256",
"state": "CfDJ8PC7ZLg_v2RDsl0VaXUuuT_-sT-at-LgQD1krwu8LESVXDKkQxQd8_eUQZJqOiGREAzBtfZ4U9X0BJDIn15AvYXKR2omUEBW5LzJm1Vz3ykaScc_kC89f6hCimDBmqCAdUOF0wnEn8FfDD8GPJtPBgxqoqrCNnyGKxh58XOIa85sN-zDSU5Oa73pzKt5FrFIkBCqUOfpCM_KZajZR_3DWFNCbwn8tS-XR0of7ga72XDILC--N9bCqA2eIlTSxf9HHPXmmLninU1ri7RM-XMsOzH__mtQQPOXCuaHw3Q0Nkedmpj4NaTCdcB1k55IdsX1eLrub8ptagCWzMIzXcYIWlJc74Zj-_H2uDZE4M-Blbdr"
}
}
I've been looking on SO for how to solve this error for the entire day, but I can't figure out what's wrong with it.
This is the code in the Startup of the IdentityProvider project:
services
.AddDbContext<SsoCentralContext>();
//.AddScoped<Repositories.IAccountRepository, Repositories.AccountRepository>();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<SsoCentralContext>();
var isb = services.AddIdentityServer();
isb
.AddInMemoryClients(new List<Client>
{
new Client
{
ClientId = "oauthClient",
ClientName = "oauthClient",
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
Enabled = true,
ClientSecrets = new List<Secret> {new Secret("SuperSecretPassword".Sha256())}, // change me!
AllowedScopes = new List<string> {"weatherforecasts.read"},
RedirectUris = new List<string>
{
"https://localhost:44375/signin-central"
},
}
})
.AddInMemoryIdentityResources(new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource
{
Name = "role",
UserClaims = new List<string> {"role"}
}
})
.AddInMemoryApiResources(new List<ApiResource>
{
new ApiResource
{
Name = "api1",
DisplayName = "API #1",
Description = "Allow the application to access API #1 on your behalf",
Scopes = new List<string> { "weatherforecasts.read", "weatherforecasts.write"},
ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},
UserClaims = new List<string> {"role"}
}
})
.AddInMemoryApiScopes(new List<ApiScope>
{
new ApiScope("weatherforecasts.read", "Read Access to API #1"),
new ApiScope("weatherforecasts.write", "Write Access to API #1")
})
.AddTestUsers(new List<IdentityServer4.Test.TestUser>
{
new IdentityServer4.Test.TestUser
{
SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
Username = "Pieterjan",
Password = "password",
Claims = new List<System.Security.Claims.Claim> {
new System.Security.Claims.Claim(IdentityModel.JwtClaimTypes.Email, "pieterjan#example.com"),
new System.Security.Claims.Claim(IdentityModel.JwtClaimTypes.Role, "admin")
}
}
})
.AddDeveloperSigningCredential();
isb
.AddOperationalStore(options =>
{
options.ConfigureDbContext = (builder) => builder.UseInMemoryDatabase("SsoCentral");
})
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = (builder) => builder.UseInMemoryDatabase("SsoCentral");
});
isb.AddAspNetIdentity<IdentityUser>();
The above code is definitely being called, so the oauthClient should exist for sure. Also the client is definitely enabled.
This is the code in Startup of the Identity project:
services
.AddAuthentication(options =>
{
})
.AddOAuth<CentralOptions, CentralHandler>("central", options =>
{
options.ClaimsIssuer = "https://localhost:44359"; // This is the URL of the IdentityProvider
options.SaveTokens = true;
options.ClientId = "oauthClient";
options.ClientSecret = "SuperSecretPassword";
options.Scope.Add("weatherforecasts.read");
options.UsePkce = true;
});
How can I fix this error? Would anyone know how to figure out what's wrong here?
Also would I still need to use OpenIdConnect on top of what's been configured here?
Update:
I've added a call just to get the clients from the IS4 ClientStore:
[HttpGet("Clients")]
public async Task<IActionResult> GetClients()
{
//var client = await clientStore.FindClientByIdAsync("SsoApplicationClient");
var _inner = (IdentityServer4.EntityFramework.Stores.ClientStore)clientStore.GetType().GetField("_inner", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(clientStore);
var Context = (IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext)_inner.GetType().GetField("Context", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(_inner);
var Clients = Context.Clients;
return Ok(Clients);
}
To my amazement, what I get from this is an entirely empty list:
Alright, so when you have the following configuration:
services.AddIdentityServer()
...
.AddOperationalStore(options =>
{
options.ConfigureDbContext = (builder) => builder.UseInMemoryDatabase("SsoCentral");
})
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = (builder) => builder.UseInMemoryDatabase("SsoCentral");
})
The InMemoryClients don't exist anymore. Just commented it out and it seems to be working now.
I'm trying to get IdentityServer4 to work but unfortunately no luck. I'll explain the issue in more detail. I'm using IdentityServer4 and also .NET core Identity. I have a .net core mvc application which has login page. You basically login with username and password. When you login I need to generate jwt token I'm doing this using the following code:
[HttpGet]
public async Task<IActionResult> GetClientToken(string clientId, string clientSecret, string grantType, string scope, string username, string password)
{
var serverClient = HttpClientFactory.CreateClient();
var discoveryDocument = await serverClient.GetDiscoveryDocumentAsync($"{Request.Scheme}://{Request.Host.Value}");
var tokenClient = HttpClientFactory.CreateClient();
var tokenResponse = await tokenClient.RequestPasswordTokenAsync(
new PasswordTokenRequest
{
ClientId = clientId,
ClientSecret = clientSecret,
GrantType = grantType,
Address = discoveryDocument.TokenEndpoint,
UserName = username,
Password = password,
Scope = scope,
});
if (!tokenResponse.IsError)
{
return Ok(new TokenResponseModel()
{
access_token = tokenResponse.AccessToken,
refresh_token = tokenResponse.RefreshToken,
expires_in = tokenResponse.ExpiresIn,
scope = tokenResponse.Scope,
token_type = tokenResponse.TokenType,
});
}
return BadRequest(tokenResponse.Error);
}
Every time I request for a token I get unauthorised client.
My seeding data is as follows:
public static IEnumerable<ApiResource> GetApis() =>
new List<ApiResource>
{
new ApiResource("AppointmentBookingApi"),
new ApiResource("PaymentApi", new string[] { "patient.portal.api.payment" }),
};
public static IEnumerable<IdentityResource> GetIdentityResources() =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResource
{
Name = "patient.portal.api",
UserClaims =
{
"patient.portal",
},
}
};
public static IEnumerable<Client> GetClients() =>
new List<Client>
{
new Client
{
ClientId = "patient.portal.client.refresh",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
RequirePkce = true,
RedirectUris = { "https://localhost:44307/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:44307/Home/Index" },
AllowedScopes =
{
"AppointmentBookingApi",
"PaymentApi",
IdentityServerConstants.StandardScopes.OpenId,
"patient.portal.api",
},
AllowOfflineAccess = true,
RequireConsent = false,
},
new Client
{
ClientId = "patient.portal.client.code",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes =
{
"AppointmentBookingApi",
},
},
};
does anyone know where I'm I going wrong here????
I am using Identity Server 4 and ASP.NET Core 2.1.
I have an API and an Auth application and tried to following:
var discoveryClient = new DiscoveryClient("https://localhost:5002");
discoveryClient.Policy.RequireHttps = true;
var discovery = await discoveryClient.GetAsync();
if (discovery.IsError)
Console.WriteLine(discovery.Error);
But I got the following error:
Error connecting to https://localhost:5002/.well-known/openid-configuration:
The SSL connection could not be established
The remote certificate is invalid according to the validation procedure.
However if I access the url "https://localhost:5002/.well-known/openid-configuration" in the browser I get the correct information and not errors.
What am I doing wrong?
The API application has the following configuration:
public void ConfigureServices(IServiceCollection services) {
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddRouting(x => { x.LowercaseUrls = true; });
services.AddHsts(x => {
x.Preload = true;
x.IncludeSubDomains = true;
x.MaxAge = TimeSpan.FromDays(60);
});
services.AddHttpsRedirection(x => {
x.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
x.HttpsPort = 5001;
});
services.AddApiVersioning(x => {
x.ApiVersionSelector = new CurrentImplementationApiVersionSelector(x);
x.AssumeDefaultVersionWhenUnspecified = true;
x.DefaultApiVersion = new ApiVersion(1, 0);
x.ReportApiVersions = false;
});
services.AddCors(x => {
x.AddPolicy("AllowAll", y => y.AllowAnyMethod().AllowAnyOrigin().AllowAnyHeader());
});
services.AddAuthorization();
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(x => {
x.ApiName = "api";
x.Authority = "https://localhost:5002";
x.RequireHttpsMetadata = false;
});
} // ConfigureServices
public void Configure(IApplicationBuilder application, IHostingEnvironment environment) {
if (environment.IsDevelopment()) {
application.UseDeveloperExceptionPage();
} else {
application.UseHsts();
}
application.UseAuthentication();
application.UseHttpsRedirection();
application.UseMvc();
} // Configure
And the Auth application with the following configuration:
public void ConfigureServices(IServiceCollection services) {
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddRouting(x => { x.LowercaseUrls = true; });
services.AddHsts(x => {
x.Preload = true;
x.IncludeSubDomains = true;
x.MaxAge = TimeSpan.FromDays(60);
});
services.AddHttpsRedirection(x => {
x.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
x.HttpsPort = 5002;
});
services
.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetTestUsers());
} // ConfigureServices
public void Configure(IApplicationBuilder application, IHostingEnvironment environment) {
if (environment.IsDevelopment()) {
application.UseDeveloperExceptionPage();
} else {
application.UseHsts();
}
application.UseHttpsRedirection();
application.UseIdentityServer();
application.UseMvc();
} // Configure
Where Config that defines Clients, Resources and Test Users is:
public class Config {
public static List<ApiResource> GetApiResources() {
return new List<ApiResource> {
new ApiResource("api", "API Resource")
};
}
public static List<IdentityResource> GetIdentityResources() {
return new List<IdentityResource> {
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
public static List<Client> GetClients() {
return new List<Client> {
new Client {
ClientId = "app",
ClientName = "APP Client",
ClientSecrets = { new Secret("app".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "api" }
},
new Client {
ClientId = "mvc",
ClientName = "MVC Client",
ClientSecrets = { new Secret("mvc".Sha256()) },
Enabled = true,
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AllowOfflineAccess = true,
RequireConsent = false,
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002" },
FrontChannelLogoutUri = "http://localhost:5002/signout-oidc",
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api"
}
},
new Client {
ClientId = "spa",
ClientName = "SPA Client",
ClientSecrets = { new Secret("spa".Sha256()) },
Enabled = true,
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api"
},
RedirectUris = { "https://localhost:5000" },
PostLogoutRedirectUris = { "https://localhost:5000/home" },
AllowedCorsOrigins = { "https://localhost:5000" }
}
};
}
public static List<TestUser> GetTestUsers() {
return new List<TestUser> {
new TestUser { SubjectId = "1", Username = "john", Password = "john", Claims = new List<Claim> { new Claim("name", "John") } },
};
}
} // Config
I want to use the function IntrospectionClient to verify the token in identity server, but it always returns: Unauthorized
Identity server startup code:
services.AddIdentityServer()
.AddSigningCredential(myPrivatecert)
.AddInMemoryApiResources(Config.GetResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetTestUsers())
.AddValidationKey(myPubliccert)
.AddJwtBearerClientAuthentication()
.AddValidators();
I add a api resource, a client info and a test user in config file
My Config is :
public class Config
{
//ApiResource
public static IEnumerable<ApiResource> GetResources()
{
return new List<ApiResource>
{
new ApiResource("api")
};
}
//Client
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client()
{
ClientId = "site",
AccessTokenLifetime = 180,
RefreshTokenExpiration = TokenExpiration.Absolute,
AbsoluteRefreshTokenLifetime = 1800,
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AlwaysSendClientClaims = true,
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
AllowedScopes =
{
"api"
},
AccessTokenType = AccessTokenType.Jwt,
AllowOfflineAccess = true
},
};
}
//TestUser
public static List<TestUser> GetTestUsers()
{
return new List<TestUser>{
new TestUser{
SubjectId="1",
Username="wyt",
Password="123456",
Claims = new List<Claim>()
{
new Claim("wawa", "aoao"),
}
}
};
}
}
My Client Startup is:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).
AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:6001";
options.RequireHttpsMetadata = false;
options.ApiName = "api";
});
get token :
//token
var tokenClient = new TokenClient(dico.TokenEndpoint, "site", "secret");
var tokenResponse = tokenClient.RequestResourceOwnerPasswordAsync("wyt", "123456").Result;
want use introspection:
var introspectionClient = new IntrospectionClient(
dico.IntrospectionEndpoint,
"api",
"secret");
var vresponse = await introspectionClient.SendAsync
(
new IntrospectionRequest { Token = tokenResult.AccessToken }
);
but the vresponse is always Unauthorized
where is wrong?
I ran into the same issue, the documentation is not very clear.
You need to add an ApiSecret to your ApiResource:
public static IEnumerable<ApiResource> GetResources()
{
return new List<ApiResource>
{
new ApiResource("api")
{
ApiSecrets = { new Secret("secret".Sha256()) }
}
};
}
And then you call the introspection endpoint passing the api name and the api secret, like you did:
var introspectionClient = new IntrospectionClient(
dico.IntrospectionEndpoint,
"api",
"secret");