I'm implementing login using Microsoft provider also implement the default login using jwt
when I run the project I got this error (Scheme already exists: Bearer)
when i comment this part, project run successfully
//.AddJwtBearer(x =>
// {
// x.SaveToken = true;
// x.TokenValidationParameters = tokenValidationParameters;
// })
here is my code
var jwtSettings = new JWTSettings();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.Secret)),
ValidateIssuer = false,
ValidateAudience = false,
RequireExpirationTime = false,
ValidateLifetime = true
};
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.SaveToken = true;
x.TokenValidationParameters = tokenValidationParameters;
})
.AddMicrosoftIdentityWebApi(configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
Scheme already exists: Bearer
It means you have more than one schemes with the same name.
You can try to set the parameter authenticationScheme into JwtBearerExtensions.AddJwtBearer Method.Here is the official doc.
And if you want to select the scheme,you can refer to the doc,and try to use:
[Authorize(AuthenticationSchemes = xxx)]
Related
I have a WPF app that I am connecting to a SignalR API. However, I am having some issues with my Identity. When I actually call an API Endpoint GET, POST, PUT, or DELETE The Identity is populated correctly (all of the claims are there). When I am connecting to SignalR the Identity Claims are not there.
This is where I register my Jwt token
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = configuration["Jwt:Issuer"],
ValidAudience = configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"]))
};
options.Authority = configuration["Jwt:Authority"];
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/hubs")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
},
};
});
and here is where I register my connection
_connection = new HubConnectionBuilder()
.ConfigureLogging(logBuilder =>
{
logBuilder.AddConsole();
logBuilder.AddDebug();
})
.WithUrl($"{url}/hubs", options =>
{
options.AccessTokenProvider = _userService.GetToken;//returns Task.FromResult(userToken)
})
.WithAutomaticReconnect(new[]
{
TimeSpan.Zero,
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(30),
TimeSpan.FromSeconds(60),
TimeSpan.FromSeconds(120)
})
.Build();
My Jwt object in configuration
"jwt":{
"Key":"some random generated key",
"Issuer":"https://localhost:5001/",
"Audience":"https://localhost:5001/",
"Authority":"https://localhost:5001/"
},
Can you please explain what I am doing wrong here?
I actually found the answer to my own question.
I changed
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
to
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
});
and that did it!
Hope this helps someone else.
I store my JWT in HTTPOnly Cookies, and after the token expire, the cookie still active. How can I delete or expire the cookie, when the JTW expires too?
Here is my Startup:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
options.SaveToken = true;
options.Events = new JwtBearerEvents();
options.Events.OnMessageReceived = context =>
{
if (context.Request.Cookies.ContainsKey("X-Access-Token"))
{
context.Token = context.Request.Cookies["X-Access-Token"];
}
return Task.CompletedTask;
};
})
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
At Login, I pass my JWT to the cookie:
Response.Cookies.Append("X-Access-Token", generatedToken, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure = true });
I'm trying to authenticate with JWT in .NET Core 2.2 with SignalR. I don't get an error message that it doesn't work on either the server or the client-side. I have set breakpoints on the server-side where the authentication is supposed to happen. Does anyone have any idea why it's not working? The JWT is built with an asymmetric signature algorithm.
This is how I generate the JWT:
var utcNow = DateTime.UtcNow;
using (RSA privateRsa = RSA.Create())
{
privateRsa.FromXmlFile(Path.Combine(HttpContext.Current.Server.MapPath("~"),
"Keys",
ConfigurationManager.AppSettings["PrivateKey"]
));
var privateKey = new RsaSecurityKey(privateRsa);
SigningCredentials signingCredentials = new SigningCredentials(privateKey, SecurityAlgorithms.RsaSha256);
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.ID.ToString()),
//new Claim(JwtRegisteredClaimNames.NameId, user.FullName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, utcNow.ToString())
};
var jwt = new JwtSecurityToken(
signingCredentials: signingCredentials,
claims: claims,
notBefore: utcNow,
expires: utcNow.AddMonths(12),
audience: "https://pacsonweb.com",
issuer: "PACSonWEB3 App"
);
return new JwtSecurityTokenHandler().WriteToken(jwt);
This is how i'm authenticating on the server side :
RsaSecurityKey signingKey = new RsaSecurityKey(publicRsa);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(config =>
{
config.RequireHttpsMetadata = true;
config.SaveToken = true;
config.TokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = signingKey,
ValidateAudience = true,
ValidAudience = this.Configuration["Tokens:Audience"],
ValidateIssuer = true,
ValidIssuer = this.Configuration["Tokens:Issuer"],
ValidateLifetime = true,
ValidateIssuerSigningKey = true
};
});
This is how I send the JWT with SignalR on the client side:
hubConnection = new HubConnectionBuilder().WithUrl(hubUrl, (opts) =>
{
opts.AccessTokenProvider = () => Globals.GetJWTToken();
opts.HttpMessageHandlerFactory = (message) =>
{
if (message is HttpClientHandler clientHandler)
{
// bypass SSL certificate
clientHandler.ServerCertificateCustomValidationCallback += CheckCertificate;
clientHandler.CheckCertificateRevocationList = false;
}
return message;
};
}).Build();
I'm trying to implement JWT Authentication in my Web API Project (developed in .Net Core 2.2), But I'm getting an error due to the configuration in Startup Class. When I run my Application without this code then it runs perfectly without any error. here is the configuration code.
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudience = Configuration.GetSection("Jwt").GetSection("Issuer").Value,
ValidIssuer = Configuration.GetSection("Jwt").GetSection("Issuer").Value,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("Jwt").GetSection("Key").Value))
};
});
and this is the error
Please any solution?
You can modify as per below.
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudience = Configuration.GetSection("Jwt").GetSection("Issuer").Value,
ValidIssuer = Configuration.GetSection("Jwt").GetSection("Issuer").Value,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("Jwt").GetSection("Key").Value))
};
});
I am building an ASP.Net Core API and am using JWT for authentication.
I have the following configuration:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(option =>
{
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidateAudience = true,
ValidateIssuer = true,
ValidateActor = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuers = Global.Issuers,
ValidAudiences = Global.Audiences,
IssuerSigningKey = Global.symmetricSecurityKey
};
});
}
As you can see, I want to use JWT and only JWT.
For a few hours I was pulling my hair out trying to figure out why I was constantly getting a 401 on any actions with the [Authorize] attribute.
I finally ended up trying [Authorize(AuthenticationSchemes = "Bearer")] and it worked!
So what gives?!
How can i figure out what other authentication schemes are challenging?
Do I have to explicitly disable the default scheme (cookie)?
I would like to avoid having to specify the AuthenticationSchemes on all my Authorize tags.
Thanks!