Create custom .well-known\openid-configuration in .net core - asp.net-core

I'm new in JWT authentification, so maybe what i want to do is wrong.
I'm using asymmetric RSA key pair to sign and validate JWT.
In my startup.cs I've :
public void ConfigureServices(IServiceCollection services) {
services.AddControllers();
services.AddSingleton<RsaSecurityKey>(provider => {
RSA rsa = RSA.Create();
rsa.ImportRSAPublicKey(
source: Convert.FromBase64String(configuration["Jwt:PublicKey"]),
bytesRead: out int _
);
return new RsaSecurityKey(rsa);
});
services.AddAuthentication()
.AddJwtBearer("Asymmetric", options => {
SecurityKey rsa = services.BuildServiceProvider().GetRequiredService<RsaSecurityKey>();
options.TokenValidationParameters = new TokenValidationParameters {
IssuerSigningKey = rsa,
ValidAudience = "audience-test",
ValidIssuer = "test-issuer",
RequireSignedTokens = true,
RequireExpirationTime = true,
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true,
};
});
}
To generate my token I've in my controller :
[HttpPost]
[Route("Asymmetric")]
public IActionResult GenerateTokenAsymmetric()
{
using RSA rsa = RSA.Create();
rsa.ImportRSAPrivateKey(
source: Convert.FromBase64String(_configuration["Jwt:PrivateKey"]),
bytesRead: out int _);
var signingCredentials = new SigningCredentials(
key: new RsaSecurityKey(rsa),
algorithm: SecurityAlgorithms.RsaSha256
);
DateTime jwtDate = DateTime.Now;
var jwt = new JwtSecurityToken(
audience: "test-audience",
issuer: "test-issuer",
claims: new Claim[] { new Claim(ClaimTypes.NameIdentifier, "John") },
notBefore: jwtDate,
expires: jwtDate.AddMinutes(1),
signingCredentials: signingCredentials
);
string token = new JwtSecurityTokenHandler().WriteToken(jwt);
return Ok(new
{
jwt = token
});
}
As you see it, my public key is stored in my appsettings.
I would like to use options.MetadataAddress so that my client can download metadata about my api and retrieve public key to validate token.
My question is :
It is possible to create a custom .well-known/openid-configuration in .net core ? Or I must to use IdentityServer for example ?
Thanks for help

I don't think it is is that hard to create your own static "fake" .well-known/openid-configuration page. But at at the same time, having a dedicates token service like IdentityServer will give you advantages when your system grows. Don't forget you also need to create the JWKS endpoint as well. As the AddJwBearer handler makes requests to both.
Also you doing it all by your self also opens up potential security issues that is already fixed/solved in the existing solutions.

Related

Can't get asp .net core 2.2 to validate my JWT

(TL;DR: check the last update)
The first issue with this is that the API has changed between the different versions of .net core.
The second one is that every example I find online is slightly different with not real authoritative answer as to what does what; rather I keep finding posts with 'oh, changing this worked for me', but it looks like everyone is, like me, experimenting with it rather than having a full understanding.
Anyhow, here is the code:
Services.AddAuthentication(A =>
{
A.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
A.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(O =>
{
O.RequireHttpsMetadata = false;
O.SaveToken = true;
O.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(AuthJWTPublicKey)),
ValidateIssuer = false,
ValidateAudience = false
};
});
I have a valid JWT but any call to my controller results in an immediate error 401.
I have tried to decorate the controller with:
[Authorize]
[Authorize(Roles = "offline_access")]
[Authorize(AuthenticationSchemes =
JwtBearerDefaults.AuthenticationScheme, Roles = "offline_access")]
but no luck
The JWT content is:
{
"jti":"837c2dd1-cca5-491e-84a4-b17429366df5",
"exp":1558355152,
"nbf":0,
"iat":1558354852,
"iss":"xxxx",
"aud":"account",
"sub":"4ed1c313-c692-44db-86d3-7605f3e2c2c1",
"typ":"Bearer",
"azp":"test-app",
"auth_time":1558354850,
"session_state":"e40c9a95-ae8a-4d6e-b2a4-ad5e833867ea",
"acr":"1",
"realm_access":{
"roles":[
"offline_access",
"uma_authorization"
]
},
"resource_access":{
"account":{
"roles":[
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope":"openid email profile",
"email_verified":true,
"name":"firstd6d05 last29954",
"preferred_username":"xxxx",
"given_name":"firstd6d05",
"family_name":"last29954",
"email":"xxxx",
"group":[
"/Administrators"
]
}
My goal is purely to verify the signature of the JWT (and eventually it's expiration) and have access to the token in the controller.
I am passing the JWT through the header, under 'Authorization' and with the text 'Bearer' in front of the token.
What am I missing?
Following the answer below, I did the following change:
I added:
Services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
and then added the following class with a break
internal class ClaimsTransformer : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
Debugger.Break();
}
}
but I am still getting a 401 with the Keycloak token; so it looks like it doesn't get to the claims transformer before being rejected.
I added the debug output of ASP.
It is at: https://pastebin.com/qvGsQG6j
The relevant part seems to be:
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
=> ConnectionId:0HLN4CPASJL8F => RequestId:0HLN4CPASJL8F:00000001 RequestPath:/helpers/log => Test.WebControllers.HelpersController.GetLog (Test)
Authorization failed.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Info:Authorization failed.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Info:Authorization failed.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
=> ConnectionId:0HLN4CPASJL8F => RequestId:0HLN4CPASJL8F:00000001 RequestPath:/helpers/log => Test.WebControllers.HelpersController.GetLog (Test)
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Info:Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Info:Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
=> ConnectionId:0HLN4CPASJL8F => RequestId:0HLN4CPASJL8F:00000001 RequestPath:/helpers/log => Test.WebControllers.HelpersController.GetLog (Test)
This specific line may explain the issue:
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'
but 'failed' seems a bit vague to me.
Last test:
I have this token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoibXkgbmFtZSIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6Im5vQGVtYWlsLmNvbSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvZXhwaXJhdGlvbiI6IjA1LzMxLzIwMTkgMDA6MTM6MjAiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zaWQiOiI3Y2FjZjdiNS04NjY5LTQ2OWUtOTg4NS1kNDgwNGYyOGNjNGEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA5LzA5L2lkZW50aXR5L2NsYWltcy9hY3RvciI6ImQyZjZiNzI0LWE0ZjktNGJkZC1hNjQ3LTRkM2UxYTU5NjhkZSIsIm5iZiI6MTU1OTE3NTIwMCwiZXhwIjoxNTU5MjYxNjAwLCJpc3MiOiJ0ZXN0IiwiYXVkIjoidGVzdC1hcHAifQ.y42RUvMM69aDTvCydoU3mOKu2giub6OvKpd-RNVmom4
with the key:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjayVuqZOuKK38rhsRwrRGzVcv/7b4fHXrzpol3K5TTAPttNUaQvCKQD7BQN+V8nvkBsQcxPk5ONnxzbFb/npENC4UtwK5J6iiVrinE7sDrWZQNo9LkwbuG9x0fuuf8U3H2CnwZEfFaf2kbU1v7XosNGi+aYASupvhwoiJtK+17ZPloxSQy3Qny2tQWi7Dh/Cr5+m5JBy6HeGLq2cq+oalFYzrGGmQXndLtJpBZgrPd7nR6lJSMiRcJtcpxTJbYTEVVXoB0SR1bPmYYB/6y7klVDVedTow+1mwZrDMrbRiTBPSifCIBs3rxLQaL207blg+kj+EVLED5fZSOBlOyTOYQIDAQAB
it decodes to (as tested by jwt.io):
{
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "my name",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "no#email.com",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration": "05/31/2019 00:13:20",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid": "7cacf7b5-8669-469e-9885-d4804f28cc4a",
"http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor": "d2f6b724-a4f9-4bdd-a647-4d3e1a5968de",
"nbf": 1559175200,
"exp": 1559261600,
"iss": "test",
"aud": "test-app"
}
it is generated by the following code:
var Expiration = DateTime.UtcNow + TimeSpan.FromDays(1);
var Identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "my name"),
new Claim(ClaimTypes.Email, "no#email.com"),
new Claim(ClaimTypes.Expiration, Expiration.ToString(CultureInfo.InvariantCulture)),
new Claim(ClaimTypes.Sid, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.Actor, Guid.NewGuid().ToString()),
});
var Token = new JwtSecurityToken
(
issuer: "test",
audience: "test-app",
claims: Identity.Claims,
notBefore: DateTime.UtcNow,
expires: Expiration,
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_JwtRsaPublicKey)), SecurityAlgorithms.HmacSha256)
);
var TokenString = new JwtSecurityTokenHandler().WriteToken(Token);
return TokenString;
In asp, I have the following code:
Services.AddAuthentication(A =>
{
A.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
A.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(O =>
{
O.RequireHttpsMetadata = false;
O.SaveToken = true;
O.IncludeErrorDetails = true;
O.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(AuthJWTPublicKey)),
ValidateIssuer = false,
ValidateAudience = false
};
});
and I have a controller method with:
[Authorize]
But I keep getting a 401, no matter what I try, I get a 401...
Even if I set ValidateIssuerSigningKey to false. I get a 401
The setup is:
In ConfigureServices, I have:
Services.AddMvc()
and the code above
In Configure, I have:
Application.UseAuthentication();
Application.UseMvc(Routes => { Routes.MapRoute("default_route", "{controller}/{action}/{id?}"); });
According to dotnet/corefx:
public static class ClaimTypes
{
internal const string ClaimTypeNamespace ="http://schemas.microsoft.com/ws/2008/06/identity/claims";
....
public const string Role = ClaimTypeNamespace + "/role";
...
The const ClaimTypes.Role is http://schemas.microsoft.com/ws/2008/06/identity/claims/role
Note your controller requires a role of offline_access:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Roles = "offline_access")]
In other words, it expects the decoded JWT has a property of http://schemas.microsoft.com/ws/2008/06/identity/claims/role to configure the roles:
{
"nbf": ...,
"exp": ...,
"iss": ...,
"aud": ...,
...,
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role": [
"offline_access",
"...other roles"
],
}
However, you configure the roles in the following way:
"realm_access":{
"roles":[
"offline_access",
"uma_authorization"
]
},
The easiest way is rebuild the token to config a role of offline_access:
ClaimsIdentity identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name,"1024"),
new Claim(ClaimTypes.Role,"offline_access"),
new Claim(ClaimTypes.Role,"...other roles"),
// ... other claims
});
var token = new JwtSecurityToken
(
issuer: _issuer,
audience: _audience,
claims: identity.Claims,
expires: expiry,
notBefore: DateTime.UtcNow,
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(mykeyname)),
SecurityAlgorithms.HmacSha256)
);
var tokenStr = tokenHandler.WriteToken(token);
Or you could transform the keycloak's style claim to Microsoft's style by registering a custom IClaimsTransformation, see a Sample by ASP.NET Core Team https://github.com/aspnet/AspNetCore/blob/658b37d2bd3b0da2c07e25b53fa5c97ce8d656d3/src/Security/samples/ClaimsTransformation/Startup.cs#L34
I am not sure what is stored in the variable but it looks like it's not a private token:
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(AuthJWTPublicKey)),
This is as far as I know a private symmetric key, perhaps you are passing a wrong value in there?
You can modify keycloak configuration for JWT creation to map the roles to "roles" item instead grouping under "realm_access".
This can be done by adding a Mapper in Keycloak client.
This works for me:
Keycloak Mapper
You can also create a second Mapper for "User Client Role". Just select "User Client Role" for Mapper Type.

Multiple JWT bearer authentication in .net core 2.1 - Claims issue

Project: .net core 2.1 APIs
In my project I have a requirement to include 2 JWT bearer authentication.
a) We create token JWT internally and use it for authentication
b) We get JWT token from external third party and need to get this authenticated as well.
I tried following code in start up:
services.AddAuthentication( )
.AddJwtBearer("InteralBearer", options =>
{
SymmetricSecurityKey key = TokenGenerator.GenerateKey();
options.Audience = "***************";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "***************",
ValidateAudience = true,
ValidAudience = "***************",
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateLifetime = true
};
})
.AddJwtBearer("ExternalBearer", options =>
{
options.Audience = "***************";
options.Authority = "***************";
});
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("ExternalBearer", "InteralBearer")
.Build();
options.AddPolicy("Applicant", new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("ExternalBearer", "InteralBearer")
.RequireClaim("role", "Applicant")
.Build());
});
In my controller I have:
[ApiController]
[Authorize(Policy = "Applicant")]
public class ApplicantController : ApplicantAbstract
{
}
I also have custom autorization filter:
public class SelfAuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
ClaimsPrincipal principal = context.HttpContext.User;
........
}
}
When I above set up, issue is, context.HttpContext.User does not return any claims as part of "Identity" object in the request. I am expecting "Claims" object to have different claims which is already configured.
Every thing works fine if I have either "InternalBearer" or "ExternalBearer", but not both.
What am I doing wrong here?

JwtBearer asp net core get signing key from api

Is it possible to configure JwtBearer from asp.net-core that it can take signing key (in my case public key) required to verify is user is authorized?
I have somehing like this:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.BackchannelHttpHandler = new HttpClientHandler();
o.MetadataAddress = "http://auth-server.local.com/api";
o.Authority = "http://localhost:5000";
o.Audience = "http://localhost:5001";
o.RequireHttpsMetadata = false;
o.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = "here should be public key exposed by my auth api server"
ValidIssuer = "http://localhost:5000",
ValidAudience = "http://loclhost:5001"
};
})
;
but my client does not call my auth api in order to obtain public key.
The code you have there just tells your applications that you want to USE JWT Tokens for authentication and what parameters to validate incoming requests (with tokens) with.
You need to setup and endpoint now to issue those tokens.. or "public key" as you put it.
Your code (notice the "mysecret" in the issuer)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.BackchannelHttpHandler = new HttpClientHandler();
o.MetadataAddress = "http://auth-server.local.com/api";
o.Authority = "http://localhost:5000";
o.Audience = "http://localhost:5001";
o.RequireHttpsMetadata = false;
o.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = "MySecret"
ValidIssuer = "http://localhost:5000",
ValidAudience = "http://loclhost:5001"
};
})
;
Now in a controller:
public class AccountController : Controller
{
[HttpGet]
public IActionResult getKey()
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MySecret"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "http://localhost:5000",
audience: "http://localhost:5001",
expires: DateTime.Now.AddYears(10),
signingCredentials: creds);
return Json(token);
}
}
Notice how in the services.. You set the private key to "MySecret" - this tells the application that any token used with a request.. must be signed with this value. Otherwise it rejects it.
In the controller.. We create a key with the same "MySecret" and issue it at host/account/getkey
Now - just add the [Authorize] tag to any function or controller you want to protect.
[Authorize]
[HttpPost]
public IActionResult Test()
{
}
EDIT: It appears you want some kind of permanent token. Just set the expires field in the new JWTtoken() line to expire in 1000 years or whatever and publicly broadcast that to whomever you want. Albiet - this is an insecure authorization model.

ASP.Net Core - JWT Authentication with WebAPI and MVC Frontend not working

The Project consists of two Parts:
ASP.Net Core API
ASP.Net Core MVC Frontend
Basically, what I want to do is authentication via JWT. So the API issues JWT and the MVC Frontend uses Identity with the claims and roles declared in the JWT.
Startup.cs in the API:
private const string SecretKey = "my_Secret_Key";
private readonly SymmetricSecurityKey _signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey));
#region JWT Auth
// jwt wire up
// Get options from app settings
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy(Constants.Policies.ApiAccess, policy => policy.RequireClaim(Constants.JwtClaimIdentifiers.Rol, Constants.JwtClaims.ApiAccess));
});
#endregion
JWT Generation:
public async Task<string> GenerateEncodedToken(string userName)
{
User user = _userManager.GetUserByUserName(userName);
List<string> userRoles = _userManager.GetRoles(user.Guid);
var claimsToEncode = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim("web", user.WebId),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
new Claim(Constants.JwtClaimIdentifiers.Rol,Constants.JwtClaims.ApiAccess),
};
// Create the JWT security token and encode it.
var jwt = new JwtSecurityToken(
issuer: _jwtOptions.Issuer,
audience: _jwtOptions.Audience,
claims: claimsToEncode,
notBefore: _jwtOptions.NotBefore,
expires: _jwtOptions.Expiration,
signingCredentials: _jwtOptions.SigningCredentials);
jwt.Payload.Add("roles", userRoles.ToArray());
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}
Authorization works like a charm with this in the API.
Now I want to do the following:
Implement the same in the Frontend, so that:
MVC Frontend receives Credentials, send them to the API, get Token, and Authorize with the Claims and Roles in the Token.
I tried several things, but none of them worked so far.
What do I have to insert in the Startup.cs in the Frontend so that Identity checks not against the secret key (which the Frontend is not allowed to have) but against a public key? Or do I have to implement a Endpoint in the API which validates the JWT remotely?
When you get the token in web client, you can store it in a session object and send that whenever you are requesting something from the webapi

.Net Core JWT generation does not seem to work, what am I doing wrong?

I'm trying to generate a Json Web Token (JWT) using System.IdentityModel.Tokens.Jwt and the following code:
public static string GenerateToken()
{
var now = DateTime.UtcNow;
var key = Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS");
var securityKey = new SymmetricSecurityKey(key);
var claims = new[]
{
new Claim("user_id", "John Doe"),
new Claim("name", "some-guid-will-go-here"),
new Claim("admin", "true", ClaimValueTypes.Boolean)
};
var jwt = new JwtSecurityTokenHandler().CreateJwtSecurityToken(
issuer: "example.com",
audience: "example.com",
subject: new ClaimsIdentity(claims),
expires: now.AddMinutes(30),
notBefore: now,
issuedAt: now,
signingCredentials: new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256),
encryptingCredentials: new EncryptingCredentials(securityKey, JwtConstants.DirectKeyUseAlg, SecurityAlgorithms.Aes256CbcHmacSha512)
);
var token = new JwtSecurityTokenHandler().WriteToken(jwt);
return new JwtSecurityTokenHandler().WriteToken(jwt);
}
When I run the function GenerateToken() it returns a token looking like this:
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwidHlwIjoiSldUIn0..EYFD_3JkBLjHFUPfFul-HQ.GP6QX0DAT7xb8rcvAH-1gKVKx2pUpMldHq4UkRevpPF8G7uzlcbMQQtkvavCIfrQ339bOxqBu9Sk9OOnMfq4xcsLs2v9qrlUKM7virT9wf4PcrnywO15xCQcdEFcN2ED4dbmn8mFJpE7jguvIuPHoZM6sYcjvwQS5Xl6vWBFVOFanF0EXauGOhVwmfcU5lCn4Y2cRjM7qD5WY5BuItvlsUEFcYQJsHOfupgdth-cTkTiihUU92R1lQla81WiXyGmS1hJZ4NJk87HUnBYQKBH9JHgJ-_F3x2seQkgCPLTCJmU7YFU_JR8mjlcu97Tl-BHWxn-z1EOpqPTCK1yPXZ6mYXrTy1ber0f8yd1hao9dvbwL3-u689YL3LnntNIV89L1jr0V-emvkTO2GE8k6z-YQ.kzjDt0foAswdWqTsEOPW4e8QbP4XOoKrmxJX0hBozlc
and when I try to validate that token using jwt.io it won't work. I can't get the payload from the token and I can't use the secret to validate or decrypt the token.
Am I doing something wrong or why isn't it working? What am I missing?
Add the following lines to your ConfigureServices(IServiceCollection services) in Startup.cs
services.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = (string)Configuration.GetSection("JwtToken").GetValue(typeof(string), "Issuer"),
ValidAudience = (string)Configuration.GetSection("JwtToken").GetValue(typeof(string), "Audience"),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS")),
TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS")),
ClockSkew = TimeSpan.FromMinutes(0),
};
});