DEV Community

Johannes Lichtenberger
Johannes Lichtenberger

Posted on β€’ Edited on

OAuth2 auth with Nuxt.js/Vue.js (frontend), Vert.x (backend for BL) and Keycloak (auth server) πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Hi all,

I need help with a Nuxt.js based frontend, which should use OAuth2 authentication code flow for authorization. Basically I don't want to use a SessionHandler and a CookieHandler on the Vert.x server side to prevent having to store state on the server (for scalability reasons in the future).

  1. Basically I have a button which should execute a GET request on click to https://localhost:9443/user/authenticate.
  2. On the server side the route will redirect to Keycloak for a login site. Then keycloak will redirect back to a given URL.
  3. The frontend will now have to extract the generated "code" from Keycloak and make another POST request to https://localhost:9443/token to get a JWT token.

Something like this:

axios.post('https://localhost:9443/token', {
  "code": this.code,
   "redirect_uri": this.redirect_uri //extra meta data needed
}).then(response => {
  var access_token = JSON.parse(response.request.response).access_token
  this.createNewResource(access_token)
})

Basically it should work like this Gist of a React component

However, I'm totally stuck as I'm super new to the frontend stuff.

It is this issue:

Vue.js Auth Component #31

We need a component, which extracts the code from the redirected to URL (from the OAuth2 auth code flow) and exchange this code with a token (/token) endpoint on the SirixDB HTTP-Server. This token then needs to be sent in subsequent requests, so we can probably store it in the store!?

I've tried some things in a branch, but I'm currently getting an internal server error (500) from Node.js and I have no clue why.

The Node.js server is running on port 3005 so I had all sorts of issues with CORS and a self signed certificate (for testing purposes)...

Setting up the SirixDB HTTP-Server and Keycloak should be doable via docker-compose. Have a look at the REST-API documentation.

Maybe someone has done a similar login already with Nuxt.js, would be great πŸ’š

Update:24.10.: Added a CORS-Handler on the Vert.x server. Now I'm running into a docker problem: How do I address a host, which is not in the docker-network (the Nuxt.js application / the Node.js server running on localhost:3005):

GET http://keycloak:8080/auth/realms/sirixdb/protocol/openid-connect/auth?redirect_uri=http%3A%2F%2Fkeycloak%3A3005&response_type=code&client_id=sirix net::ERR_NAME_RESOLUTION_FAILED
commons.app.js:1001 Uncaught (in promise) Error: Network Error
    at createError (commons.app.js:1001)
    at XMLHttpRequest.handleError (commons.app.js:536)
createError @ commons.app.js:1001
handleError @ commons.app.js:536
Promise.then (async)
login @ index.js:42
click @ index.js:82
invokeWithErrorHandling @ commons.app.js:15696
invoker @ commons.app.js:16021
invokeWithErrorHandling @ commons.app.js:15696
Vue.$emit @ commons.app.js:17719
handleClick @ vendors.app.js:15399
invokeWithErrorHandling @ commons.app.js:15696
invoker @ commons.app.js:16021
original._wrapper @ commons.app.js:20744

kind regards
Johannes

Top comments (11)

Collapse
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

I've managed to use the Nuxt.js axios module now. I got rid of the internal server error. However, axiom for instance doesn't seem to use the baseURL specified.

Collapse
Β 
zspine profile image
M#3 β€’

Hi

I am not a vue expert and I have started to use vue very recently (switched from ng 1). But I also gone through the same type of issues and most of the time I had no clue over certain errors.

  1. Did you update the base url inside the nuxt.config.js?
  axios: {
    baseURL: 'http://example.test'
  },

** Changes to nuxt.config.js wont be detected until you restart the prcoess.

P.S.
I would highly recommend the dotenv module for easier env level configurations
github.com/nuxt-community/dotenv-m...

Collapse
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

Okay, Update: I had to add the browserBaseURL:

browserBaseURL: '127.0.0.1:9443'

However, the strange thing is

this.$axios
  .$get("/user/authorize", {})
  .then((res: any) => {
    console.log(res);
  });

This somehow produces an OPTIONS HTTP-request instead of a GET HTTP-request.

Collapse
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

It seems the whole axios module configuration isn't recognized:

  axios: {
    baseURL: 'https://127.0.0.1:9443',
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    proxyHeaders: true,
    proxy: true
  }

And request is sent to localhost:3005 instead with headers:

Accept  
application/json, text/plain, */*
Accept-Encoding 
gzip, deflate
Accept-Language 
en-US,en;q=0.5
Connection  
keep-alive
Cookie  
co_SId=76771689452D3D85F5940E3…local; auth.redirect=%2Fquery
DNT 
1
Host    
localhost:3005
Referer 
http://localhost:3005/login
User-Agent  
Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/69.0

Code is simply:

import { Component, Prop, Vue } from "vue-property-decorator";

@Component
export default class Login extends Vue {
  private login(): void {
    console.log("bla")
    this.$axios
      .$get("/user/authorize", {})
      .then((res: any) => {
        console.log(res);
      });
  }
}
Collapse
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

Yes: github.com/sirixdb/sirix-web-front...

Yeah, I'm trying to learn Nuxt.js, Vue.js, TypeScript and D3.js, but I'm eager to learn :-)

Thread Thread
Β 
zspine profile image
M#3 β€’

Mhh.. couldn't find anything odd (but I am not familiar with TypeScript (ES only)

Here is my working setup (minimal code)
gist.github.com/zspine/efa32262b12...

Thread Thread
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

Oh wow, can you make a PR maybe? :-)

I think Vert.x also has to send an HTTP-Header for CORS, to allow any origin: Access-Control-Allow-Origin: *

And the error is different with Chrome (I've used Firefox until now):
GET 127.0.0.1:9443/user/authorize net::ERR_CERT_AUTHORITY_INVALID

because of a self-signed certificate :(

However, so with your code it's already working!? πŸ‘ That would be beyond awesome :)

Thread Thread
Β 
zspine profile image
M#3 β€’

I wish I can be more helpful but unfortunately busy with a deadline. :( That was just a copy paste from my current project and it uses server side httponly cookie based authentication.

I think your custom axios plugin doing the right thing with "new https.Agent" configuration. You can apply the same thing to nuxt axios module.

Thread Thread
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

aww, thanks for the hints :)

Collapse
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

Hmm, does someone, know why the host could not be resolved when the Vert.x server redirects to Keycloak?

keycloak:8080/auth/realms/sirixdb/...

At least in the docker network it is for instance reachable by the server service (Vert.x based HTTP-Server), but not from the "frontend backend server", that is Node.js.

My docker-compose file:

version: '3'
services:
  waitforkeycloak:
    image: dadarek/wait-for-dependencies
    depends_on:
      - keycloak
    command: keycloak:8080
  keycloak:
    image: jboss/keycloak
    ports:
      - 8080:8080
    environment:
      - KEYCLOAK_USER=admin
      - KEYCLOAK_PASSWORD=admin
      - KEYCLOAK_LOGLEVEL=DEBUG
      - KEYCLOAK_IMPORT=/opt/keycloak/realm-export.json
    restart: always
    volumes:
      - ./sirix/bundles/sirix-rest-api/src/test/resources/realm-export.json:/opt/keycloak/realm-export.json
    command:
      - "-b 0.0.0.0"
      - "-bmanagement 0.0.0.0"
  server:
    build: ./sirix
    image: sirixdb/sirix
    ports:
      - "9443:9443"
    restart: always
    volumes:
      - /opt/sirix
      - ./sirix/bundles/sirix-rest-api/src/main/resources/cert.pem:/opt/sirix/sirix-data/cert.pem
      - ./sirix/bundles/sirix-rest-api/src/main/resources/key.pem:/opt/sirix/sirix-data/key.pem
      - ./sirix/bundles/sirix-rest-api/src/main/resources/sirix-conf.json:/opt/sirix/sirix-conf.json
    depends_on:
      - keycloak
  frontend:
    build: ./sirix-web-frontend
    image: sirixdb/sirix-web-frontend
    ports:
      - "3005:3005"
    restart: always
    volumes:
      - /usr/src/nuxt-app
    depends_on:
      - server
      - keycloak
Collapse
Β 
johanneslichtenberger profile image
Johannes Lichtenberger β€’

I've added a section in the README how to set things up with docker-compose...