[keycloak-user] Frontend connecting to middleware protected by keycloak-nodejs-connect (intended usage)

Rudresh Shashikant rudreshsj at gmail.com
Wed May 30 19:33:51 EDT 2018


Need to share some context and setup before asking my question, so please
excuse the wall of text. =)

My app:
`frontend` is a SPA served as a static resource from NGINX (http://frontend)
`keycloak` server running on http://keycloak
`middleware` is a NodeJS app that frontend communicates with as API
endpoint (eg: http://middleware). Middleware is using
keycloak-nodejs-connect (https://github.com/keycloak/keycloak-nodejs-connect)
to protect the API endpoint

setup code in middleware looks like this:
```
const session = require('express-session')
const memoryStore = new session.MemoryStore()

app.use(session({
  secret: 'mySecret',
  resave: false,
  saveUninitialized: true,
  store: memoryStore
}))

const keycloak = require('./auth/keycloak')
app.use(keycloak.middleware({
  logout: '/logout'
}))
```

The setup in auth/keycloak.js is:
```
const keycloakConfig = {
  'realm': 'realmName',
  'auth-server-url': `http://keycloak/auth`,
  'ssl-required': 'external',
  'resource': 'clientName',
  'credentials': {
    'secret': 'aaaaaaaa-bbbb-cccc-dddd-1a49c9dfbbef'
  }
}

module.exports = new Keycloak({store: memoryStore, responseType: 'code'},
keycloakConfig)
```

when a user clicks "/login" link from frontend, the frontend spawns a new
tab and the new tab calls http://middleware/login. The motivation is for
the existing state in UI to not be touched, all redirects etc happen in a
new window. The code in middleware looks like this:
```
app.get('/login', keycloak.protect(), (req, res) => {
  const keycloakTokens = JSON.parse(req.session['keycloak-token'])
  const userInfo = JSON.stringify(decodeToken(keycloakTokens))
  res.status(200).send(`<html><head>
        <script type="text/javascript">
            window.opener.postMessage(${userInfo}, 'http://frontend')
            window.close()
        </script>
    </head></html>`)
})

const decodeToken = ({id_token}) => {
  const payload = JSON.parse(atob(id_token.split('.')[1]))
  return payload
}
```

So the idea is that after the OIDC dance, the middleware will respond
asking the new tab to postMessage to the opener (parent) with the contents
of the id_token JWT.

Assumption 1: the session in the cookie connect.sid is what the middleware
uses to ensure the user is still authenticated. Is this assumption accurate?

there is a event listener in frontend that watches for the `postMessage`
and saves the information sent (id_token) to localStorage.

Question 1: is this a correct way of doing login given the setup described
above?

I think i'm definitely missing something because another protected route in
middleware causes redirect to keycloak again telling me that middleware
does not know the frontend is authenticated.

Question 2: how would logout work in this case? just clear the browser
cookies?

I tried the example app (
https://github.com/keycloak/keycloak-nodejs-connect/tree/master/example)
but that has a different architecture, the browser points to the middleware
domain.

please let me know if you are looking for more code snippets or details.
Happy to provide.

Regards,
Rudy.


More information about the keycloak-user mailing list