K
Kinde10mo ago
Kin

Server and Client side connection

Hello Kinde Team, I am wondering how I will go about implementing authentication for both client side and server side for full stack. My app is made using React as the frontend and Express as the backend. I successfully implemented the frontend auth using Kinde however I still need to authenticate api calls in the Express backend. I saw a little section about using the middleware but I couldn’t find the exact steps to implement this. I have written my process of authenticating, please let me know if this process is correct for Kinde’s use case.
39 Replies
Kin
KinOP10mo ago
1. User Login on Client Side: The user enters their credentials (username and password) on the client-side application built with React. Using Kinde Auth for React SDK, you handle this login request. The SDK directly interacts with Kinde’s authentication API. 2. Token Handling: Upon successful authentication, Kinde’s API responds with an authentication token (JWT). This token is typically stored in the client’s local storage or in-memory storage, depending on your security requirements. Kinde handles the token management, which simplifies the process. 3. Token Verification for Protected Routes: When the client makes a request to a protected route on your backend (built with Node.js and Express.js, for instance), you need to send this token as part of the request headers. On the server side, you should have a middleware that verifies the token’s validity. This can be done using Kinde’s libraries or other JWT validation methods. 4. Backend Response: Once the token is verified and the request is authenticated, your backend performs the necessary action and sends the response back to the client. This could be data retrieval, modification, or any other server-side logic. 5. Client-Side Handling: The client-side application, upon receiving the response, will then proceed with the appropriate actions based on the server’s response. This could involve rendering user-specific data, redirecting to a different component, etc. This is my thought process if this is generally correct, I would like assistance on implementing the middleware to my express app.
Oli - Kinde
Oli - Kinde10mo ago
Hey @Kin, Thanks for reaching out and taking the time to explain your thinking towards using Kinde for your setup. Your process for implementing authentication with Kinde in a full-stack application using React for the frontend and Express.js for the backend is generally correct. Here's a breakdown of your steps with some additional insights and recommendations based on Kinde's documentation: 1. User Login on Client Side: Correct. Users will log in using the React frontend, and the Kinde Auth React SDK will handle the authentication with Kinde's API. Upon successful login, Kinde will issue an authentication token (JWT). 2. Token Handling: Correct. The received JWT should be securely stored on the client side, typically in local storage or session storage, though the choice depends on your application's security requirements. Kinde's SDKs facilitate token management. 3. Token Verification for Protected Routes: Correct. When accessing protected routes on your backend, the client must include the JWT in the request headers. On the server side, you should implement middleware that verifies the token's validity. According to Kinde's documentation, you can use the @kinde-oss/kinde-node package for Express.js applications to easily verify the token and protect your routes. 4. Backend Response: Correct. After the token verification, your backend will process the request and respond accordingly. This ensures that only authenticated requests are processed for protected routes. 5. Client-Side Handling: Correct. The client application handles the response from the backend, which may involve rendering data, navigating to different parts of the application, or handling errors. To implement the middleware in your Express app for token verification, you can follow these steps: 1. Install the @kinde-oss/kinde-node package in your Express app:
npm install @kinde-oss/kinde-node

npm install @kinde-oss/kinde-node

2. Import and initialize the Kinde middleware in your Express app. You'll need to provide your Kinde domain to fetch the verification keys for your app:
const express = require('express');
const { kindeNode } = require('@kinde-oss/kinde-node');
const app = express();

let authenticate;

(async () => {
authenticate = await kindeNode(YOUR_KINDE_DOMAIN);
})();
const express = require('express');
const { kindeNode } = require('@kinde-oss/kinde-node');
const app = express();

let authenticate;

(async () => {
authenticate = await kindeNode(YOUR_KINDE_DOMAIN);
})();
3. Protect your routes using the authenticate middleware:
app.get('/api/protected', authenticate, (req, res) => {
res.json({ message: 'This is a protected route' });
});
app.get('/api/protected', authenticate, (req, res) => {
res.json({ message: 'This is a protected route' });
});
Replace YOUR_KINDE_DOMAIN with your actual Kinde domain. This setup ensures that only requests with a valid JWT can access your protected routes. If you have any specific questions or need further assistance, feel free to ask!
Kin
KinOP10mo ago
awesome thank you so much this is exactly what i needed. Just another clarifying question: will this require me to make a new app in my Kinde Account? @Oli - Kinde or does the package know my token since im providing my domain
Oli - Kinde
Oli - Kinde10mo ago
You would have to create 2 applications in Kinde, one for your React frontend app, and one for your Express backend
mohamed222
mohamed22210mo ago
Hi @Oli - Kinde Continuing on this. Im trying to implement this same pattern but with fastapi on my backend. Normally I would have the jwt secret and then decode the token that way, but the react app doesn't give me the secret to decode the token. Further creating a new app under the same project produces a secret that is invalid for decoding the jwt token sent by react. How would I go about doing this in python? Thanks in advance
Oli - Kinde
Oli - Kinde10mo ago
Hey @mohamed222, I can for sure help you out. To implement authentication in your FastAPI backend using Kinde, you don't need the JWT secret to decode the token. Instead, you should verify the JWT token using Kinde's public keys. This approach is more secure and aligns with best practices for handling JWTs. Here's a general process to authenticate API calls in your FastAPI backend: 1. Install Required Packages: Ensure you have fastapi, uvicorn, and kinde-python-sdk installed in your environment. If not, you can install them using pip:
pip install fastapi uvicorn kinde-python-sdk

pip install fastapi uvicorn kinde-python-sdk

2. Set Up FastAPI Application: Create your FastAPI application as usual. Define your routes and any business logic needed. 3. Authenticate Requests: For routes that require authentication, you'll need to verify the JWT token that comes from the client (React app). You can do this by extracting the token from the request headers and then using Kinde's SDK or a custom function to verify the token against Kinde's public keys. Here's a simplified example of how you might set up a route in FastAPI that requires authentication:
from fastapi import FastAPI, Depends, HTTPException
from kinde_sdk import KindeApiClient, Configuration, GrantType

app = FastAPI()

# Configure the Kinde API client
configuration = Configuration(host='https://<your_kinde_subdomain>.kinde.com')
kinde_client = KindeApiClient(
configuration=configuration,
domain='https://<your_kinde_subdomain>.kinde.com',
client_id="<CLIENT_ID>",
client_secret="<CLIENT_SECRET>",
grant_type=GrantType.CLIENT_CREDENTIALS
)

async def get_current_user(token: str = Depends(kinde_client.oauth2_scheme)):
try:
payload = kinde_client.decode_token(token)
return payload
except Exception as e:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")

@app.get("/protected")
async def protected_route(user: dict = Depends(get_current_user)):
return {"message": "This is a protected route", "user": user}
from fastapi import FastAPI, Depends, HTTPException
from kinde_sdk import KindeApiClient, Configuration, GrantType

app = FastAPI()

# Configure the Kinde API client
configuration = Configuration(host='https://<your_kinde_subdomain>.kinde.com')
kinde_client = KindeApiClient(
configuration=configuration,
domain='https://<your_kinde_subdomain>.kinde.com',
client_id="<CLIENT_ID>",
client_secret="<CLIENT_SECRET>",
grant_type=GrantType.CLIENT_CREDENTIALS
)

async def get_current_user(token: str = Depends(kinde_client.oauth2_scheme)):
try:
payload = kinde_client.decode_token(token)
return payload
except Exception as e:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")

@app.get("/protected")
async def protected_route(user: dict = Depends(get_current_user)):
return {"message": "This is a protected route", "user": user}
In this example, replace <your_kinde_subdomain>, <CLIENT_ID>, and <CLIENT_SECRET> with your actual Kinde details. The get_current_user dependency extracts the token from the request, decodes it using Kinde's SDK, and verifies it. If the token is valid, the protected route will return a message along with the user details extracted from the token. This approach ensures that only requests with a valid JWT token can access your protected routes. For more detailed information and the latest updates on using Kinde with FastAPI, please refer to the Kinde Python SDK documentation. Let me know if you have any further questions.
mohamed222
mohamed22210mo ago
ok interesting will try this out and let you know! Thanks @Oli - Kinde
Kin
KinOP9mo ago
Hello ive been trying this and its saying that: authenticate = await kindeNode('my_domain'); TypeError: kindeNode is not a function ive installed the package and the imported it and it still doesn seem to work
Oli - Kinde
Oli - Kinde9mo ago
Hi @Kin, I have reached out to a teammate to look into your issue further. Hey @Kin, Are you able to check you've got the kindeNode module export in your folders (.../node_modules/@kinde-oss/kinde-node/dist/cjs/index.js) - this would ensure that it was correctly installed - should look something like
'use strict';

const {getPem, authToken} = require('@kinde-oss/kinde-node-auth-utils').default;

const kindeNode = async (domain) => {
const pem = await getPem(domain);

return (req, callback) => {
const authHeader = req.headers.authorization;
// Remove 'Bearer ' prefix
const token = authHeader && authHeader.split(' ')[1];

return authToken(token, pem, (err, userString) => {
const user = err ? {} : JSON.parse(userString);
return callback(err, user);
});
};
};

module.exports = kindeNode;
'use strict';

const {getPem, authToken} = require('@kinde-oss/kinde-node-auth-utils').default;

const kindeNode = async (domain) => {
const pem = await getPem(domain);

return (req, callback) => {
const authHeader = req.headers.authorization;
// Remove 'Bearer ' prefix
const token = authHeader && authHeader.split(' ')[1];

return authToken(token, pem, (err, userString) => {
const user = err ? {} : JSON.parse(userString);
return callback(err, user);
});
};
};

module.exports = kindeNode;
Let me know.
Kin
KinOP9mo ago
yep its there 🙂 should I reinstall my node modules? Could not find a declaration file for module '@kinde-oss/kinde-node'. '/Users/kawai/Documents/projects/Mangetsu/backend/node_modules/@kinde-oss/kinde-node/dist/cjs/index.js' implicitly has an 'any' type. Try npm i --save-dev @types/kinde-oss__kinde-node if it exists or add a new declaration (.d.ts) file containing declare module '@kinde-oss/kinde-node';ts(7016) its also showing this at the import
Kin
KinOP9mo ago
No description
Oli - Kinde
Oli - Kinde9mo ago
Hey @Kin, It seems like you need to include declare module '@kinde-oss/kinde-node' in an your declaration .d.ts file. Let me know if this does not solve your issue.
Kin
KinOP9mo ago
To use this package do i need to have typescript? My app is a full javascript app It seems like this issue isnt getting solved even if I do this
Oli - Kinde
Oli - Kinde9mo ago
Okay I will get one of my TypeScipt/Node expert teammates to look into this and get back to you.
Kin
KinOP9mo ago
I just dont understand how kinde auth works on express like if my backend runs on port 4000 and my frontend runs on port 3000 and both ports have their own kinde config since its two different apps how are they meant to communicate with eachother?
Oli - Kinde
Oli - Kinde9mo ago
Hey @Kin, Frontend (Port 3000): Your frontend application is where your users will interact with your service. When you set up Kinde authentication here, you're essentially configuring it to handle user logins, registrations, and managing user sessions. The frontend will communicate with Kinde to authenticate users and receive tokens that represent the user's session. Backend (Port 4000): Your backend application handles the business logic, data storage, and secure operations of your service. When you set up Kinde authentication on your backend, it's configured to verify the tokens received from the frontend to ensure that requests are authenticated. Does this answer your question?
Kin
KinOP9mo ago
yes partly, So when i set like all the configurations like this in my express app const config = { clientId: process.env.KINDE_CLIENTID, issuerBaseUrl: <My kinde url> siteUrl: "http://localhost:4000", secret: process.env.KINDE_SECRET, redirectUrl: "http://localhost:4000", scope: 'openid profile email', grantType: GrantType.AUTHORIZATION_CODE, unAuthorisedUrl: 'http://localhost:4000/unauthorised', postLogoutRedirectUrl: 'http://localhost:4000', }; const client = setupKinde(config, app); How can i let my server thats connected on port 4000 verify the token that was recieved in the frontend? Do i send it over manually on my frontend? or does the kinde app connected to my backend fetch it from the kinde api? if so what would that process look like? I can't seem to depict the code that does this "transfer" or "fetching" of the token in the expressSDK
Oli - Kinde
Oli - Kinde9mo ago
Hey @Kin, To verify the token received in the frontend on your server running on port 4000, you typically need to send the token from the frontend to the backend with each request that requires authentication. This process is not automatically handled by Kinde; it requires you to manually implement the token transfer in your application's logic. Here's a general outline of how this process works: 1. Frontend Receives Token: After a successful authentication, your frontend application will receive an authentication token from Kinde. This usually happens through a redirect from Kinde's authentication service back to your application, with the token included in the URL or stored in the browser's local storage or cookies. 2. Send Token to Backend: When making requests to your backend server (running on port 4000), include the authentication token in the request headers. A common practice is to use the Authorization header with a Bearer token format. For example:
fetch('http://localhost:4000/protected-route', {
headers: {
'Authorization': `Bearer ${token}`
}
})

fetch('http://localhost:4000/protected-route', {
headers: {
'Authorization': `Bearer ${token}`
}
})

Replace ${token} with the actual token received from Kinde. 3. Backend Verifies Token: On the backend, you need to verify the token with each request to protected routes. This is where the protectRoute middleware from the Kinde Express SDK comes into play. You apply this middleware to your routes that require authentication. The middleware extracts the token from the Authorization header, verifies it, and either allows the request to proceed or returns an unauthorized response if the token is invalid. Here's an example of how you might protect a route in your Express app:
const { protectRoute } = require("@kinde-oss/kinde-node-express");

app.get("/protected-route", protectRoute, (req, res) => {
// If the request reaches here, it means the token is valid
res.send("This is a protected route");
});
const { protectRoute } = require("@kinde-oss/kinde-node-express");

app.get("/protected-route", protectRoute, (req, res) => {
// If the request reaches here, it means the token is valid
res.send("This is a protected route");
});
This setup ensures that only requests with a valid authentication token can access protected routes on your backend. The token verification process (checking the token's validity, expiration, etc.) is handled by the Kinde SDK, so you don't need to implement the verification logic yourself. Remember, the actual implementation details might vary based on your application's specific requirements and setup. The key steps are receiving the token in the frontend, sending it with requests to the backend, and verifying it on the backend.
Kin
KinOP9mo ago
I am now encountering a CORS error that i am struggling to get around
Kin
KinOP9mo ago
Access to fetch at 'https://mangetsu.kinde.com/logout?redirect=http://localhost:4000/api/jobs' (redirected from 'http://localhost:4000/api/jobs') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Kinde
Kinde
App infrastructure as a service.
Kin
KinOP9mo ago
No description
Kin
KinOP9mo ago
It seems like kinde's redirect is getting blocked by CORS
Kin
KinOP9mo ago
No description
Kin
KinOP9mo ago
router.post('/', protectRoute, createJob)
Kin
KinOP9mo ago
'https://mangetsu.kinde.com/logout?redirect=http://localhost:4000/api/jobs' Im also wondering why its redirecting me to the logout?
Kinde
Kinde
App infrastructure as a service.
Oli - Kinde
Oli - Kinde9mo ago
Hey @Kin, I have passed your CORS issue onto a teammate. We will get back to you once we have more information. Hey @Kin, What Kinde SDKs are you using? And what versions? I know you mentioned previously that your "app is made using React as the frontend and Express as the backend." I am aware that you used @kinde-oss/kinde-node module in the past, but are you using the Kinde React SDK too?
Kin
KinOP9mo ago
im currently using kinde React and kinde Express the backend of my app is node with express installed
Oli - Kinde
Oli - Kinde9mo ago
Are you using a custom domain too?
Kin
KinOP9mo ago
yes but im tryjng to get this first done on development so ive turned the custom domain off for now
Oli - Kinde
Oli - Kinde9mo ago
Okay, in that case I recommend reading this part of the React SDK documentation. You could try isDangerouslyUseLocalStorage if you are not yet willing to use a custom domain. Let me know if you have any further questions.
Kinde Docs
React SDK - Developer tools - Help center
Our developer tools provide everything you need to get started with Kinde.
Kin
KinOP9mo ago
I currently have that my backend and frontend tho is pointing to different urls
Oli - Kinde
Oli - Kinde9mo ago
You are currently using isDangerouslyUseLocalStorage?
Kin
KinOP9mo ago
yes on my react frontend can localstorage be accessed by another url?
Oli - Kinde
Oli - Kinde9mo ago
Let me get back to you on this.
Kin
KinOP9mo ago
its stored in my frontend but idk if it even communicates with my backend
Oli - Kinde
Oli - Kinde9mo ago
What versions of the Kinde SDKs are you using?
Kin
KinOP9mo ago
"version": "3.0.23" for react "version": "1.2.3", for express
Oli - Kinde
Oli - Kinde9mo ago
Hey @Kin, We have fixed CORS issues in the latest updates of the Kinde React SDK. Are you able to update the Kinde React SDK to the latest version, v3.0.28, and let me know if you are still experiencing the CORS error?
Ash
Ash8mo ago
@Kin did you fix this usse? I'm currently getting a cors error after user sign up and get reidrected
Want results from more Discord servers?
Add your server