question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JWT Token always Invalid

See original GitHub issue

Hello everybody, I am migrating from 1.0 to 3.1 … I have managed everything so far, but the token is not accepted, if I check it on jwt.io, it is also invalid.

Can anyone spot a mistake? The Type in the Screenshot below is also interesting, “at+jwt” and not as before “JWT”…

Received with postman 2020-01-30 18_18_05-Postman

Tryed on jwt.io 2020-01-30 18_18_43-JSON Web Tokens - jwt io

public void ConfigureServices(IServiceCollection services)
        {
            // Load app settings from web.config / appsettings.json to object
            var appSettings = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettings);

            // Add config for injection to controller
            services.AddSingleton<IConfiguration>(Configuration);

            // Add framework services.
            services.AddDbContext<ApplicationDbContext>(options =>
            {
                // Configure the context to use Microsoft SQL Server.
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));

                // Register the entity sets needed by OpenIddict.
                // Note: use the generic overload if you need
                // to replace the default OpenIddict entities.
                options.UseOpenIddict();
            });

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddMvc();

            // Replace PasswordHasher
            services.AddScoped<IPasswordHasher<ApplicationUser>, AspNetMembershipHasher<ApplicationUser>>();

            // Self-signed cert: 
            // PS C:\Windows\system32> $cert = New-SelfSignedCertificate -DnsName mydomain.com -CertStoreLocation "cert:\LocalMachine\My"
            // PS C:\Windows\system32 > $password = ConvertTo - SecureString - String “abc.123" -Force -AsPlainText
            // PS C:\Windows\system32 > Export - PfxCertificate - Cert $cert - FilePath "d:\temp\cert.pfx" - Password $password
            _signingCertificate = new X509Certificate2(Configuration["AppSettings:PfxFullFileName"], Configuration["AppSettings:PfxPassword"]); 

            var tokenValidationParameters = new TokenValidationParameters
            {
                // The signing key must match!
                ValidateIssuerSigningKey = false,
                //IssuerSigningKey = signingKey,

                // Validate the JWT Issuer (iss) claim
                ValidateIssuer = true,
                ValidIssuer = Configuration["AppSettings:IssuerUrl"],

                // Validate the JWT Audience (aud) claim
                ValidateAudience = true,
                ValidAudience = Configuration["AppSettings:Audiences"],

                // Validate the token expiry
                ValidateLifetime = true,

                // If you want to allow a certain amount of clock drift, set that here:
                ClockSkew = TimeSpan.Zero,

                IssuerSigningKey = new X509SecurityKey(_signingCertificate)
            };

            services.Configure<IdentityOptions>(options =>
            {
                options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
                options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
                options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
            });


            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.Audience = Configuration["AppSettings:Audiences"];
                options.Authority = Configuration["AppSettings:IssuerUrl"];
                options.RequireHttpsMetadata = false;
                options.MetadataAddress = Configuration["AppSettings:MetadataUrl"];
                options.TokenValidationParameters = tokenValidationParameters;
            });

            // Register the OpenIddict services.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            services.AddOpenIddict()
                // Register the Entity Framework stores.
                // Register the OpenIddict core services.
                .AddCore(options =>
                {
                    options.UseEntityFrameworkCore()
                           .UseDbContext<ApplicationDbContext>();
                })


                 .AddServer(options =>
                 {

                     // AddMvcBinders() is now UseMvc()- but wont exist ... 
                     options.SetIssuer(new Uri(Configuration["AppSettings:IssuerUrl"]));

                     options.SetAuthorizationEndpointUris("/connect/authorize");
                     options.SetLogoutEndpointUris("/connect/logout");
                     options.SetTokenEndpointUris("/connect/token");
                     options.SetUserinfoEndpointUris("/api/userinfo");

                     options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
                           OpenIdConnectConstants.Scopes.Profile,
                           OpenIdConnectConstants.Scopes.OpenId,
                           OpenIddictConstants.Scopes.Roles);

                     options.AllowPasswordFlow();
                     options.AllowClientCredentialsFlow();
                     options.AllowImplicitFlow();
                     options.AllowAuthorizationCodeFlow();
                     options.AllowRefreshTokenFlow();

                     options.UseAspNetCore()
                                .EnableStatusCodePagesIntegration()
                                .EnableAuthorizationEndpointPassthrough()
                                .EnableLogoutEndpointPassthrough()
                                .EnableTokenEndpointPassthrough()
                                .EnableUserinfoEndpointPassthrough()
                                .EnableVerificationEndpointPassthrough()
                                .DisableTransportSecurityRequirement(); // During development, you can disable the HTTPS requirement.

                     /* options.IgnoreEndpointPermissions()
                             .IgnoreGrantTypePermissions()
                             .IgnoreScopePermissions();
                             */

                     options.AddEncryptionCertificate(_signingCertificate);

                     options.AddSigningCertificate(_signingCertificate);
                 })
                // Register the OpenIddict validation components.
                .AddValidation(options =>
                {
                    // Configure the audience accepted by this resource server.
                    // The value MUST match the audience associated with the
                    // "demo_api" scope, which is used by ResourceController.
                    options.AddAudiences("resource_server");

                    // Import the configuration from the local OpenIddict server instance.
                    options.UseLocalServer();

                    // Register the ASP.NET Core host.
                    options.UseAspNetCore();
                });

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(options => options.MapControllerRoute(
             name: "default",
             pattern: "{controller=Home}/{action=Index}/{id?}"));
        }
[HttpGet("~/connect/authorize")]
[HttpPost("~/connect/authorize")]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Authorize()
{
	var request = HttpContext.GetOpenIddictServerRequest() ??
	throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");

	// Retrieve the user principal stored in the authentication cookie.
	// If it can't be extracted, redirect the user to the login page.
	var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
	if (result == null || !result.Succeeded)
	{
		// If the client application requested promptless authentication,
		// return an error indicating that the user is not logged in.
		if (request.HasPrompt(Prompts.None))
		{
			return Forbid(
				authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
				properties: new AuthenticationProperties(new Dictionary<string, string>
				{
					[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
					[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
				}));
		}

		return Challenge(
			authenticationSchemes: IdentityConstants.ApplicationScheme,
			properties: new AuthenticationProperties
			{
				RedirectUri = Request.PathBase + Request.Path + QueryString.Create(
					Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList())
			});
	}

	// If prompt=login was specified by the client application,
	// immediately return the user agent to the login page.
	if (request.HasPrompt(Prompts.Login))
	{
		// To avoid endless login -> authorization redirects, the prompt=login flag
		// is removed from the authorization request payload before redirecting the user.
		var prompt = string.Join(" ", request.GetPrompts().Remove(Prompts.Login));

		var parameters = Request.HasFormContentType ?
			Request.Form.Where(parameter => parameter.Key != Parameters.Prompt).ToList() :
			Request.Query.Where(parameter => parameter.Key != Parameters.Prompt).ToList();

		parameters.Add(KeyValuePair.Create(Parameters.Prompt, new StringValues(prompt)));

		return Challenge(
			authenticationSchemes: IdentityConstants.ApplicationScheme,
			properties: new AuthenticationProperties
			{
				RedirectUri = Request.PathBase + Request.Path + QueryString.Create(parameters)
			});
	}

	// If a max_age parameter was provided, ensure that the cookie is not too old.
	// If it's too old, automatically redirect the user agent to the login page.
	if (request.MaxAge != null && result.Properties?.IssuedUtc != null &&
		DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))
	{
		if (request.HasPrompt(Prompts.None))
		{
			return Forbid(
				authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
				properties: new AuthenticationProperties(new Dictionary<string, string>
				{
					[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
					[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
				}));
		}

		return Challenge(
			authenticationSchemes: IdentityConstants.ApplicationScheme,
			properties: new AuthenticationProperties
			{
				RedirectUri = Request.PathBase + Request.Path + QueryString.Create(
					Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList())
			});
	}


	// Retrieve the profile of the logged in user.
	var user = await _userManager.GetUserAsync(result.Principal) ??
		throw new InvalidOperationException("The user details cannot be retrieved.");

	// Retrieve the application details from the database.
	var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
		throw new InvalidOperationException("Details concerning the calling client application cannot be found.");

	// Create a new authentication ticket.
	var ticket = await CreateUserTicketAsync(request, user);
	ticket = AddResourcesToTicket(ticket);

	// Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
	return SignIn(ticket.Principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
kevinchaletcommented, Jan 30, 2020

Yes, remove .AddJwtBearer() but keep the .AddValidation() call. Don’t forget to replace JwtBearerDefaults by the equivalent in OpenIddictValidationAspNetCoreDefaults.

If it still doesn’t work, you’ll have to post your complete logs to figure out what’s going on.

0reactions
x360andycommented, Feb 6, 2020

yes this solve the hole problem 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Always getting invalid signature in jwt.io - node.js
I always get invalid signature when I input the generated token in jwt.io Here is my code for making the token
Read more >
Key Based Authentication Failed with "JWT token is invalid" ...
This article explains what factors might cause key-based authentication to fail with the error "JWT token is invalid" and how to resolve it....
Read more >
JWT (JSON Web Tokens) Errors | Invalid JWT Signature
For Invalid JWT Signature, check if your service account key has expired. Go to your APIs & Services to add a new key...
Read more >
Generated JWT token is invalid
You may be receiving an opaque access token, which is not formatted as a JWT and would throw this error when pasted into...
Read more >
JWT token always has invalid signature - OAuth/OIDC
What I noticed by debugging any token generated by my organization in jwt.io is that they ALWAYS have invalid signature.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found