skywalker-kiwi#02131
skywalker-kiwi#02131
Explore posts from servers
KKinde
Created by Spleen on 7/14/2024 in #💻┃support
How can I get the users JWT token after logging when using the Nuxt module?
[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables. When I added the above code to my app.vue to add token handling globally, this occurred. It appears as though my useKindeClient() composable calls are returning a null client, despite being logged in - bizarre.
4 replies
KKinde
Created by skywalker-kiwi#02131 on 7/1/2024 in #💻┃support
Webhook Validation
public async Task<Result<EventResponse>> GetEventAsync(string eventId, string accessToken, CancellationToken cancellationToken)
{
_logger.Information("Getting webhook {Id}", eventId);
try
{
HttpClient client = _clientFactory.CreateClient(ClientName);
string endpoint = $"{_kindeSettings.Domain}/api/v1/events/{eventId}";
bool createUri = Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri);
if (!createUri)
{
_logger.Error("The uri was invalid");
return Result<EventResponse>.Fail(new Error(400, "The webhook endpoint was invalid"));

}
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint);
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken);
HttpResponseMessage response = await client.SendAsync(requestMessage, cancellationToken);
response.EnsureSuccessStatusCode();
JsonSerializerOptions options = _jsonOptionsFactory.CreateOptions(ClientName);
EventResponse responseValue = await response.Content.ReadFromJsonAsync<EventResponse>(options: options, cancellationToken) ?? throw new InvalidDataException("The json response was invalid");
_logger.Information("Successfully retrieved webhook value");
return Result<EventResponse>.SucceedWithValue(responseValue);
}
catch (Exception exception)
{
_logger.Error(exception, exception.Message);
return Result<EventResponse>.Fail(new Error(500, "The webhook could not be retrieved"));
}
}
public async Task<Result<EventResponse>> GetEventAsync(string eventId, string accessToken, CancellationToken cancellationToken)
{
_logger.Information("Getting webhook {Id}", eventId);
try
{
HttpClient client = _clientFactory.CreateClient(ClientName);
string endpoint = $"{_kindeSettings.Domain}/api/v1/events/{eventId}";
bool createUri = Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri);
if (!createUri)
{
_logger.Error("The uri was invalid");
return Result<EventResponse>.Fail(new Error(400, "The webhook endpoint was invalid"));

}
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint);
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken);
HttpResponseMessage response = await client.SendAsync(requestMessage, cancellationToken);
response.EnsureSuccessStatusCode();
JsonSerializerOptions options = _jsonOptionsFactory.CreateOptions(ClientName);
EventResponse responseValue = await response.Content.ReadFromJsonAsync<EventResponse>(options: options, cancellationToken) ?? throw new InvalidDataException("The json response was invalid");
_logger.Information("Successfully retrieved webhook value");
return Result<EventResponse>.SucceedWithValue(responseValue);
}
catch (Exception exception)
{
_logger.Error(exception, exception.Message);
return Result<EventResponse>.Fail(new Error(500, "The webhook could not be retrieved"));
}
}
10 replies
KKinde
Created by skywalker-kiwi#02131 on 7/1/2024 in #💻┃support
Webhook Validation
Hey @Daniel_Kinde, so I implemented the suggestion above. I tried using my m2m token with read:events enabled as a permission, and I get a 403 response. I am setting the token as a bearer token Authorization header value. I then tried giving my m2m app all the scopes available and I still get a 403. Any suggestions as to what's up with that? See below for implementation 😃
10 replies
KKinde
Created by Spleen on 7/14/2024 in #💻┃support
How can I get the users JWT token after logging when using the Nuxt module?
There is a composable called useKindeClient. There is an async method called getToken(). Use that to get your jwt. I realise that intellisense/documentation is severely lacking...
4 replies
KKinde
Created by skywalker-kiwi#02131 on 7/1/2024 in #💻┃support
Webhook Validation
Ah cool, thanks. That clarifies things
10 replies
KKinde
Created by skywalker-kiwi#02131 on 7/1/2024 in #💻┃support
Webhook Validation
Thanks @Andre @ Kinde . That explains things a bit more. The flow I am trying to achieve is: user registers -> triggers webhook -> backend receives webhook payload and adds user to database -> returns 200 status code. As it is the webhook triggering my custom endpoint and not a user, there is not a token being passed in. As a user is registering and they don't have an access token yet, what token do I use to hit that events endpoint? I assume it could be an admin token?
10 replies
KKinde
Created by skywalker-kiwi#02131 on 7/1/2024 in #💻┃support
Webhook Validation
[HttpPost("register")]
public async Task<Results<Ok, UnauthorizedHttpResult, BadRequest, ProblemHttpResult>> RegisterAccount(CancellationToken cToken = default)
{
string content = string.Empty;
using (MemoryStream ms = new MemoryStream())
{
await HttpContext.Request.Body.CopyToAsync(ms);
byte[] bytes = ms.ToArray();
content = Encoding.UTF8.GetString(bytes);
}
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
RSA rsa = await Utils.GetRSAFromJwks(_kindeSettings.Domain);
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = _kindeSettings.Issuer,
ValidAudience = _kindeSettings.Audience,
IssuerSigningKey = new RsaSecurityKey(rsa)
};
try
{
JwtSecurityToken jwtToken = handler.ReadJwtToken(content);
string payload = jwtToken.Payload.SerializeToJson();
JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
PropertyNameCaseInsensitive = true
};

RegisterAccountWebhookBody? deserialisedResponse = JsonSerializer.Deserialize<RegisterAccountWebhookBody>(payload, options);
if(deserialisedResponse == null)
{
throw new InvalidDataException("The web request body was invalid");
}
bool isValid = await _authenticationService.ValidateWebhook(deserialisedResponse.EventId, deserialisedResponse.Timestamp, content, cToken);
}
catch(Exception ex)
{
_logger.LogError(ex, ex.Message);
return TypedResults.Problem("The webhook could not be validated");
}
return TypedResults.Ok();
}
[HttpPost("register")]
public async Task<Results<Ok, UnauthorizedHttpResult, BadRequest, ProblemHttpResult>> RegisterAccount(CancellationToken cToken = default)
{
string content = string.Empty;
using (MemoryStream ms = new MemoryStream())
{
await HttpContext.Request.Body.CopyToAsync(ms);
byte[] bytes = ms.ToArray();
content = Encoding.UTF8.GetString(bytes);
}
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
RSA rsa = await Utils.GetRSAFromJwks(_kindeSettings.Domain);
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = _kindeSettings.Issuer,
ValidAudience = _kindeSettings.Audience,
IssuerSigningKey = new RsaSecurityKey(rsa)
};
try
{
JwtSecurityToken jwtToken = handler.ReadJwtToken(content);
string payload = jwtToken.Payload.SerializeToJson();
JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
PropertyNameCaseInsensitive = true
};

RegisterAccountWebhookBody? deserialisedResponse = JsonSerializer.Deserialize<RegisterAccountWebhookBody>(payload, options);
if(deserialisedResponse == null)
{
throw new InvalidDataException("The web request body was invalid");
}
bool isValid = await _authenticationService.ValidateWebhook(deserialisedResponse.EventId, deserialisedResponse.Timestamp, content, cToken);
}
catch(Exception ex)
{
_logger.LogError(ex, ex.Message);
return TypedResults.Problem("The webhook could not be validated");
}
return TypedResults.Ok();
}
10 replies
KKinde
Created by skywalker-kiwi#02131 on 7/1/2024 in #💻┃support
Webhook Validation
I am validating the JWT against my open-id config as I would with any other JWT and so is there a need to validate webhook again (see below):
10 replies
KKinde
Created by LIFE on 12/6/2023 in #💻┃support
Resolving auth in back-end (.NET) with token retrieved from front-end (React)
49 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
Awesome, thanks for that. I’ll give it a go and see if that helps too
14 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(async options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtIssuer, ValidAudience = jwtAudience, IssuerSigningKey = new RsaSecurityKey(rsa) }; options.SaveToken = true; options.Authority = jwtIssuer; options.Audience = jwtAudience; options.MapInboundClaims = false; options.TokenValidationParameters.NameClaimType = "sub"; options.IncludeErrorDetails = true; }); This was the final config in Program.cs
14 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
The issue has been resolved: I added this method to my program.cs
async Task<RSA> GetRSA(string domain)
{
using (HttpClient client = new HttpClient())
{
string fullEndpoint = $"{domain}/.well-known/jwks.json";
string jwksJson = await client.GetStringAsync(fullEndpoint);
JsonDocument jwks = JsonDocument.Parse(jwksJson);

JsonElement key = jwks.RootElement.GetProperty("keys")[0];
byte[] n = Base64UrlEncoder.DecodeBytes(key.GetProperty("n").GetString());
byte[] e = Base64UrlEncoder.DecodeBytes(key.GetProperty("e").GetString());

RSAParameters rsaParameters = new RSAParameters { Modulus = n, Exponent = e };
RSA rsa = RSA.Create(rsaParameters);
return rsa;
}

}
async Task<RSA> GetRSA(string domain)
{
using (HttpClient client = new HttpClient())
{
string fullEndpoint = $"{domain}/.well-known/jwks.json";
string jwksJson = await client.GetStringAsync(fullEndpoint);
JsonDocument jwks = JsonDocument.Parse(jwksJson);

JsonElement key = jwks.RootElement.GetProperty("keys")[0];
byte[] n = Base64UrlEncoder.DecodeBytes(key.GetProperty("n").GetString());
byte[] e = Base64UrlEncoder.DecodeBytes(key.GetProperty("e").GetString());

RSAParameters rsaParameters = new RSAParameters { Modulus = n, Exponent = e };
RSA rsa = RSA.Create(rsaParameters);
return rsa;
}

}
This gets the RSA from the jwks endpoint. I realised that I had one-half of my signing key stored, hence the key issue. More so a nooby thing on my end, not being 100% on how JWTs work 🫠 I also removed the Authorize attribute from my controller as this still causes errors.... not sure if that is intended or not. But now I can hit my controller and the user is authenticated with valid claims returning
14 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
This is the error that occurs when I have an authorize attribute on the controller. When there isn't one, I just get a user object where the claims are empty and the IsAuthorized value is false
14 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
There is an Authorize attribute on the controller, yes. In terms of configuration, it has updated as per the suggestions made here: https://discord.com/channels/1070212618549219328/1181922100806680646 It looks like:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.Authority = jwtIssuer;
options.Audience = jwtAudience;
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = "sub";
options.IncludeErrorDetails = true;
});
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.Authority = jwtIssuer;
options.Audience = jwtAudience;
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = "sub";
options.IncludeErrorDetails = true;
});
When I send the request through both postman and swagger, I get a 401 unauthorised response, along with the message "signing key not found". I have checked my token to make sure the iss and aud values are set, and they are. My jwt issuer is https://summt.kinde.com and my audience is https://summt.kinde.com/api
14 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
*kinde
14 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
The jwt issuer is my base kindle url. The jwt audience is base_url/api The signing key has been received from the .well-known/jwks endpoint
14 replies
KKinde
Created by LIFE on 12/6/2023 in #💻┃support
Resolving auth in back-end (.NET) with token retrieved from front-end (React)
Not that it should matter, but I am using .NET8. Does that make a difference?
49 replies
KKinde
Created by LIFE on 12/6/2023 in #💻┃support
Resolving auth in back-end (.NET) with token retrieved from front-end (React)
Okay, I just put in the above settings and my request context is still show unauthorized
49 replies
KKinde
Created by LIFE on 12/6/2023 in #💻┃support
Resolving auth in back-end (.NET) with token retrieved from front-end (React)
https://discord.com/channels/1070212618549219328/1251154108845527153 Here is what I have tried.... after following everything in this post: no luck, sadly
49 replies
KKinde
Created by skywalker-kiwi#02131 on 6/14/2024 in #💻┃support
ASP.NET API not validating token
string issuer = _configuration.GetSection("KindeSettings")["Issuer"];
_configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
string issuer = _configuration.GetSection("KindeSettings")["Issuer"];
_configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
This is how I have configured my ConfigurationManager
14 replies