1

I have a ReactJS app with axios running on top of a NodeJS backend. I also have a local Keycloak server to enable single sign on (sso) and authentication.

On the NodeJS backend I configured Keycloak Adapater as:

(...other imports...)
const session = require('express-session');
const Keycloak = require('keycloak-connect');

const CONFIG = {
    apiRoot: 'http://localhost:8033',
    serverPort: '3000'
}

const loadSpringConfig = async () => { (... do something unrelated...) }

Promise.all([loadSpringConfig()]).then(() => {
    const server = express()

    const memoryStore = new session.MemoryStore();

    // Using json config downloaded from keycloak client
    let keycloak = new Keycloak({
        store: memoryStore
    });

    // In memory session
    server.use(session({
        secret: 'extremely-secret',
        resave: false,
        saveUninitialized: false,
        store: memoryStore
    }));

    server.use(keycloak.middleware({}));
    server.use(compression())
    server.use(cookieParser())
    server.use(bodyParser.json({ limit: '50mb' }))
    server.use(bodyParser.urlencoded({ limit: '50mb', extended: true }))

    server.get('/health', (req, res) => {
        res.send("{ healthy: true }")
    })

    server.get('/secure', keycloak.protect('user'), function (req: any, res: any) {
        let keycloakToken = JSON.parse(req.session['keycloak-token']);
        let accessToken = keycloakToken.access_token;
        
        res.send(accessToken);
    });

    server.get('/config', (req, res) => {
        res.json(CONFIG)
    })

    server.use(express.static(path.join(__dirname, 'build')))

    server.get('/', (req, res) => {
        res.sendFile(path.join(__dirname, 'build', 'index.html'))
    })

    server.listen(CONFIG.serverPort, (err: Error) => {
        if (err) {
            throw err
        }
        console.log(`> Ready on http://localhost:${CONFIG.serverPort}, using api at: ${CONFIG.apiRoot}`)
    })
})

This is working as expected, when the browser goes to localhost:3000/secure it is redirected to my keycloak login page. After login successfully the browser is redirected back to my /secure endpoint with the user's access token in the response body. This is all in NodeJS.

My issue now is the ReactJS should somehow be notified that there is valid token from keycloak and use it on Axios http client to send authenticated requests to a different backend service running on a cloud server.

I am new to frontend development. What is the best way to pass the token from the NodeJS backend to the ReactJS frontend app running on the user's browser so that it can be retrieved by Axios (to send on all http requests to the external api)?

dazito
  • 7,740
  • 15
  • 75
  • 117
  • So as far as I understand, you have 3 systems that need to authenticate: the node backend, the react frontend and the cloud backend. All these systems have to talk to the key cloak server, either to get an access token or to verify an access token (that was transferred with axios). In react you could use https://www.npmjs.com/package/@react-keycloak/web to handle the auth mechanics. – Matthias Wiedemann Mar 09 '21 at 08:55

0 Answers0