Trying to update my api to .net core 2.0 and am now getting the exception below. Upon upgrade I changed my startup.cs with the authentication settings below and I have confirmed that the settings are all being correctly pulled from config and set as the options with the debugger. I'm sure i'm doing something wrong but It not obvious to me what that is yet.
services
.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(opts => {
// base-address of your identityserver
opts.Authority = Configuration.GetSection("Id4Settings")["Authority"];
// name of the API resource
opts.ApiName = Configuration.GetSection("Id4Settings")["ApiName"];
opts.RequireHttpsMetadata = bool.Parse(Configuration.GetSection("Id4Settings")["RequireHttps"]);
});
System.InvalidOperation: You must either set Authority or IntrospectionEndpoint
Nothing really relevant in the log because of the way I'm handling errors right now it continues to process after this error and the token is successfully validated.
System.InvalidOperationException: You must either set Authority or IntrospectionEndpoint
at Microsoft.AspNetCore.Builder.OAuth2IntrospectionOptions.Validate()
at IdentityModel.AspNetCore.OAuth2Introspection.PostConfigureOAuth2IntrospectionOptions.PostConfigure(String name, OAuth2IntrospectionOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<InitializeAsync>d__42.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.<GetHandlerAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationService.<AuthenticateAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.IdentityServerAuthenticationHandler.<HandleAuthenticateAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<AuthenticateAsync>d__47.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationService.<AuthenticateAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 155671.3652ms 500 application/json
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 155671.3652ms 500 application/json
[21:38:45 Information] Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler
Successfully validated the token.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[2]
Successfully validated the token.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[2]
Successfully validated the token.
[21:38:45 Information] Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler
AuthenticationScheme: BearerIdentityServerAuthenticationJwt was successfully authenticated.
my guess is that this does not work:
opts.Authority = Configuration.GetSection("Id4Settings")["Authority"];
Thanks Dominick,
The settings are being pulled from the config correctly and the issue has been _resolved_ by specifying opts.ApiSecret.
As I understand it the secret is only necessary if the Api needs to validate a reference token. I'm sending a jwt so it seems to me that the back channel communication is not necessary and thus the secret shouldn't be either...
Interestingly I now get an introspection error and still successful validation at the same time. So from the perspective of my api clients everything is working again but the api logs look like this:
[11:30:38 Error] IdentityModel.AspNetCore.OAuth2Introspection.OAuth2IntrospectionHandler
Error returned from introspection endpoint: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
[11:30:38 Information] Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler
Successfully validated the token.
fail: IdentityModel.AspNetCore.OAuth2Introspection.OAuth2IntrospectionHandler[0] Error returned from introspection endpoint: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[2]
Successfully validated the token.
fail: IdentityModel.AspNetCore.OAuth2Introspection.OAuth2IntrospectionHandler[0] Error returned from introspection endpoint: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[2]
Successfully validated the token.
[11:30:38 Information] IdentityModel.AspNetCore.OAuth2Introspection.OAuth2IntrospectionHandler
BearerIdentityServerAuthenticationIntrospection was not authenticated. Failure message: Error returned from introspection endpoint: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
[11:30:38 Information] Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler
AuthenticationScheme: BearerIdentityServerAuthenticationJwt was successfully authenticated.
I just compared that with the behavior and log output from here:
I can't repro any of those issues - please compare that to your project.
I'm also getting this "You must either set Authority or IntrospectionEndpoint" exception. But I can not resolve it by setting an ApiSecret.
Now I switched to the plain JwtBearer and with it, it works. But not with the IdentityServerAuthentication.
Update: I only get this exception from IdentityServerAuthentication if there is no Authorization-Header set in the request. With a valid token in it, there is no exception.
I gave up on trying to upgrade my projects to .net core 2.0 and instead just created new projects and ported code over. That resolved the issue for me.
OK - I tried it again and cannot repro any of the issues. Glad it's working now.
I was struggling with this issue and getting the same exception - in my case, I had copied and pasted the token into the Authoriation header incorrectly, so it wasn't a valid JWT. Fixing the token immediately fixed the issue.
Based on that and @erikkolo's comment, it looks like failure to extract a valid JWT causes this exception.
I added more logging (trace level) - so it should be easier to diagnose what kind of token was found.
Is there a way to have this return the response as a 401 instead of a 500? In pre 2.0 the request would just go through unauthenticated and I'd return a 401 so the client could react off that 401 status code and request a new token
For now I injected some middleware to catch the exception and modify the response
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (InvalidOperationException exc)
{
but wasn't sure if there exists a better integration point
If there is a 500, that's a bug. What do the logs say?
Pretty much the error message from the original post but let me grab mine real quick... Before if there was a bad token the request would still just get through to controllers that allowed anonymous access and the request would just be unauthenticated. So I would just take these cases and return a 401 back to the client if the client had intended to be authenticated.
I have some tests I run against asp.net core which just insert garbage into the Bearer header token to test this behavior.
An unhandled exception has occurred while executing the request
System.InvalidOperationException: You must either set Authority or IntrospectionEndpoint
at Microsoft.AspNetCore.Builder.OAuth2IntrospectionOptions.Validate()
at IdentityModel.AspNetCore.OAuth2Introspection.PostConfigureOAuth2IntrospectionOptions.PostConfigure(String name, OAuth2IntrospectionOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<InitializeAsync>d__42.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.<GetHandlerAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.FederatedSignOut.FederatedSignoutAuthenticationHandlerProvider.<GetHandlerAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationService.<AuthenticateAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler.<HandleAuthenticateAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<AuthenticateAsync>d__47.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationService.<AuthenticateAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.<AuthenticateAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter.<OnAuthorizationAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.IdentityServerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.BaseUrlMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.IdentityServerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.BaseUrlMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 885.5916ms 500 text/html; charset=utf-8
But what token are you actually sending - JWT or reference token?
My implementation uses JWT tokens.
For my test
I just send a GUID so it's set to something to emulate a "bad token"
HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Guid.NewGuid().ToString());
I don't have anything that sets the client like this
client.AccessTokenType = AccessTokenTypes.Reference;
I don't set the AccessTokenType anywhere
So does it work when you send a valid JWT token? Also - have you tried setting the SupportedTokens on the handler?
OK - I had a look -
so basically you are sending a token that looks like a reference token, but don't configure the handler correctly for reference tokens (the ApiSecret is missing) - right?
I agree that the exception is misleading - so either
On a related note - if you are using JWTs only - our handler doesn't really give you any extra features. It is only useful if you need to support JWTs and reference tokens in the same API.
I also had this problem and had to switch.
https://github.com/damienbod/AspNetCoreAngularSignalRSecurity/blob/master/ApiServer/Startup.cs#L99
I have no bearer token in the header.
it looks like setting the secret worked as well... I had the secret set on the Clients that get added in later on from this call AddInMemoryClients but I'm probably just mixed up with how I'm thinking it ties together. I figured since the ApiName matched up then handler just used those clients
hehe ... I added this test mainly because I noticed that tokens seem to get invalidated for lots of unforeseen reasons ... I have certificate data encryption setup and noticed if the DataProtection libraries get updated then all tokens from a previous versions invalidate.... So gradually I just ended up where I'm at with these tests to try and cover my #@$ in whatever scenarios I can think of. They might also be left over from when I was using a beta version of ASOS :-/
Either way
Thanks for the info about just switching to AddJwt
Thanks for the link to the sample as well @damienbod .. I'll just go that route to minimize possibility of things like this coming up
Hi!
This happens in Quickstart6_AspNetIdentity sample if I switch to reference token:
IdentityServerWithAspNetIdentity project:
public static IEnumerable
...
AccessTokenType = AccessTokenType.Reference,
Api project:
options.SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Reference;
But after some experiments the issue goes away :))
If I supply the api secret (Identity and api):
IdentityServerWithAspNetIdentity (Config.cs):
ApiSecrets = new List
{
new Secret("api_secret".Sha256())
},
Api:
options.ApiSecret = "api_secret";
For me this error occurs when sending a request from a JavaScript client to Web API only when Authorization header is on the request but the token is null, like so - Authorization: Bearer null or Authorization: Bearer
I'm getting this exception when "access" instead of valid JWT is sent from HttpClient...
see above discussion.
https://github.com/IdentityServer/IdentityServer4/issues/1627#issuecomment-339102001
When a malformed JWT is passed to a .NET Core 2.0 API using IdentityServer Authentication and a 500 status code is returned instead of a 401, setting options.SupportedTokens = SupportedTokens.Jwt; in the Startup.cs ConfigureServices() solved this problem.
My Senario:
GET to API requiring OAuth (client credentials is grant type) where I sent some string that cannot be decoded as a JWT.
Header:
Accept:application/json
Authorization:Bearer SomeStringThatIsNotAJwtThatCantbeDecoded
Exception message in the body contains:
InvalidOperationException: You must either set Authority or IntrospectionEndpoint
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
When a malformed JWT is passed to a .NET Core 2.0 API using IdentityServer Authentication and a 500 status code is returned instead of a 401, setting
options.SupportedTokens = SupportedTokens.Jwt;in the Startup.cs ConfigureServices() solved this problem.My Senario:
GET to API requiring OAuth (client credentials is grant type) where I sent some string that cannot be decoded as a JWT.
Header:
Accept:application/json
Authorization:Bearer SomeStringThatIsNotAJwtThatCantbeDecoded
Exception message in the body contains:
InvalidOperationException: You must either set Authority or IntrospectionEndpoint