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...