Next api example #44
Comments
Hi @webdeb , Thanks for your feedback. Unfortunately I don't have any working example for the API integration part, this module is focused more towards the Frontend one and so I didn't add any API examples. I might look into this but I don't have a clear timeframe, in the meanwhile I'd suggest you to have a look at the official |
No problem, I just thought, because of the next package here, that you maybe also tried to secure next's api routes. I'll see if I can put a small POC together. |
OK, just a small POC (I've used express, instead of nextjs api routes), anyway maybe someone will find it useful. // auth.js
const session = require("express-session")
const Keycloak = require("keycloak-connect")
const kcConfig = {
realm: "<REALM>",
"auth-server-url": "https://<KEYCLOAK>/auth",
"ssl-required": "external",
"public-client": true,
"confidential-port": 0,
}
const memoryStore = new session.MemoryStore()
const keycloak = new Keycloak({ store: memoryStore }, kcConfig)
const sessionMiddleware = session({
secret: "mySecret",
resave: false,
saveUninitialized: true,
store: memoryStore,
})
module.exports = {
keycloak,
sessionMiddleware,
} Custom server const express = require("express")
const next = require("next")
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== "production"
const { sessionMiddleware, keycloak } = require("./auth") // the file above
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.use(sessionMiddleware)
server.use(keycloak.middleware())
server.all("*", handle)
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
}) withUser.js // Middleware import { keycloak } from "./auth"
const protect = keycloak.protect((token, request) => {
request.user = { ...token.content, userId: token.content.sub }
return true
})
export default handler => async (req, res) => {
protect(req, res, () => handler(req, res))
} some api/route.js import withUser from "withUser.js"
const route = (req, res) => {
console.log(req.user)
res.json({ success: true, url: "" })
}
export default withUser(route) |
@panz3r please ping me, if you find a good solution with plain next-api-routes. Thank you |
Hi @webdeb , I had some time to experiment with the integration of So it's only needed to implement the following files:
import session from 'express-session';
import Keycloak from 'keycloak-connect';
const kcConfig = {
realm: "<REALM>",
"auth-server-url": "https://<KEYCLOAK>/auth",
"ssl-required": "external",
"public-client": true,
"confidential-port": 0,
}
const memoryStore = new session.MemoryStore();
const keycloak = new Keycloak({ store: memoryStore }, kcConfig);
const sessionMiddleware = session({
secret: 'mySecret',
resave: false,
saveUninitialized: true,
store: memoryStore,
});
export { keycloak, sessionMiddleware };
import nextConnect from 'next-connect';
import {
keycloak,
sessionMiddleware,
} from '../../../middlewares/keycloak-auth';
const handler = nextConnect();
handler
.use(sessionMiddleware)
.use('/', ...keycloak.middleware()) // Must be set this way since 'keycloak.middleware()' returns an array
.use(keycloak.protect())
.get((req, res) => {
console.log('Keycloak data', req.kauth); // contains Keycloak user data, if authenticated
try {
res.status(200).json({});
} catch (err) {
res.status(500).json({ statusCode: 500, message: err.message });
}
});
export default handler; This is still based on reusing the existing |
@panz3r cool, this looks nice. I guess some parts could be shared. like
Thank you, I did't know about |
@webdeb , Yes, it could be reused as per // Define and export a keycloakHandler inside keycloak-auth.js
const keycloakHandler = nextConnect().use(sessionMiddleware).use('/', ...keycloak.middleware());
// use it where needed
const handler = nextConnect();
handler.use(keycloakHandler).use(keycloak.protect()).use((req, res, next) => {
req.hello = 'world';
// call next if you want to proceed to next chain
next();
}); Hope this helps, I'm going to close this issue and add a reference inside the docs. |
I've been trying to add this API auth example to the UI based nextjs example, so that when you login from the webUI subsequent API calls will be authenticated. However, it doesn't look like the APIs are able to pickup the current login state of the web routes. I'm wondering if it's because the ssr provider is saving the token in the kcToken cookie, whereas this example is looking for the token in memoryStore. Would be great to see an end-to-end example of nextJS with the API paths integrated. |
This does not work in my case because upon calling the protect middleware my request object is of a different kind, eg. request.protocol is undefined. Therefore the redirectUri is not valid. Did you encounter a similar problem? |
This does not work anymore. It will give you "access denied". Also I found out the node-js back-end adapter is no longer supported https://www.keycloak.org/2022/02/adapter-deprecation |
Hi, currently, you have some great examples for the frontend part.
I am looking to secure some api parts of my next api with keycloak.
Do you have a working example, that could be made public?
Thank you
The text was updated successfully, but these errors were encountered: