dsb-norge / vue-keycloak-js

A Keycloak plugin for Vue 2
https://www.dsb.no
ISC License
272 stars 99 forks source link

how to define $keycloak on vue 3 using JavaScript #145

Open rkrajukhunt opened 2 years ago

rkrajukhunt commented 2 years ago

how I can convert this into js in Vue 3

// Allow usage of this.$keycloak in components declare module '@vue/runtime-core' { interface ComponentCustomProperties { $keycloak: VueKeycloakInstance } }

DavidzMwangi commented 2 years ago

Hello @rkrajukhunt did you get a solution to this?

baltom commented 2 years ago

I haven't really tested this. But i would think that you wouldn't really have to convert it to javascript. It is to allow typescript to know that there is something on the Vue component called $keycloak and what type it has. Javascript dont need to know that to be able to use it.

rkrajukhunt commented 2 years ago

@baltom did this lib handle redirect to mobile app too

i am using a keycloak with quasar, i build app using capacitor like a ionic

redirection is working fine with keycloak to web app, i am stuck in redirect to mobile app

can you help me out

baltom commented 2 years ago

@rkrajukhunt Have never tried before i'm afraid. Maybe someone else has any experience

dl74i commented 2 years ago

I have tried and failed.

    if (Platform.is.cordova || Platform.is.capacitor) {
      initOptions = {
        ...initOptions,
        adapter: 'cordova',
        // redirectUri: 'https://myapp.local/',
//        redirectUri: 'android-app://local.myapp/https/local.myapp/login'
        redirectUri: 'android-app://'
      }
    }

It's just not working. But this issue isn't about this, right?

stratosgear commented 2 years ago

Have the same issue! Cannot get access to the instance of $keycloak. All examples are using Typescript but I want a plain javascript one! :(

baltom commented 2 years ago

Have the same issue! Cannot get access to the instance of $keycloak. All examples are using Typescript but I want a plain javascript one! :(

In templates you should be able to reference $keycloak without having to do anything (other than installing the plugin of course) however if using it from script tag its not located on the Vue object as in vue2. It's on globalProperties (https://github.com/dsb-norge/vue-keycloak-js/blob/main/src/index.ts#L102) which is on the app context. or you could inject it into your script https://vuejs.org/guide/components/provide-inject.html

stratosgear commented 2 years ago

Thanks @baltom for the direct pointers to the code where things are implemented.

Unfortunately I am still not sure how to properly access the $keycloak var. In my case (using latest Quasar with latest vue) the $keycloak var does not resolve from either the template section neither the script section of my .vue files.

Only "hack" that I was able to come with (that I am sure that any day now will reveal some limitation) was to do define a custom kc var likewise (marked as HACK HERE below):

import VueKeyCloak from "@dsb-norge/vue-keycloak-js";
import { boot } from "quasar/wrappers";
import { api } from "boot/axios";

// HACK HERE
var kc = null;

export default boot(async ({ app, router, store }) => {
  async function tokenInterceptor() {
    api.interceptors.request.use(
      (config) => {
        config.headers.Authorization = `Bearer ${app.config.globalProperties.$keycloak.token}`;
        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
  }

  return new Promise((resolve) => {
    app.use(VueKeyCloak, {
      init: {
        onLoad: "login-required",
        flow: "standard",
        pkceMethod: "S256",
        silentCheckSsoRedirectUri:
          window.location.origin + "/silent-check-sso.html",
        checkLoginIframe: false, // otherwise it would reload the window every so seconds
      },
      config: {
        url: process.env.KEYCLOAK_HOST,
        realm: process.env.KEYCLOAK_REALM,
        clientId: process.env.KEYCLOAK_CLIENT_ID,
      },
      // initOptions: {
      //   // pkceMethod: 'S256',
      //   // must match to the configured value in keycloak
      //   // redirectUri: 'http://localhost:4200/your_url',
      //   // this will solved the error
      //   checkLoginIframe: false,
      // },
      onReady: (keycloak) => {
        tokenInterceptor();
        resolve();
        // HACK HERE
        kc = keycloak;
      },
    });
  });
});

// declare module "@vue/runtime-core" {
//   interface ComponentCustomProperties {
//     $keycloak: VueKeycloakInstance;
//   }
// }

// HACK HERE
export { kc };

then in my .vue files:

<script setup>
import { kc } from "boot/keycloak";
...
...

which allows me to use kc from both the template and script section.

If you could be a little more detailed and give me the reference to the $keycloak when you mention:

It's on globalProperties (https://github.com/dsb-norge/vue-keycloak-js/blob/main/src/index.ts#L102) which is on the app context.

that would be great! You mean access it like: app.config.globalProperties.$keycloak ? Where would I get access to app from a random .vue file?

Thanks once more! I would really like to remove my "hack" from above! (Here is a pre-emptive :beer:, btw)

jra11 commented 2 years ago

To @stratosgear :

This is what I did:

In my boot file (Quasar):

onReady: (keycloak) => {
        tokenInterceptor()
        app.provide('keycloak', keycloak)
        resolve()
      }

In my vue components (setup function):

const kc = inject('keycloak')

You'll need to import inject from Vue.

It works, but what I do not understand is that it's already in the vue-keycloak-js source code. However injecting it in Vue component is not working, don't know why.

https://github.com/dsb-norge/vue-keycloak-js/blob/main/src/index.ts#L104

idc77 commented 1 year ago

@jra11 according to https://vuejs.org/guide/components/provide-inject.html#working-with-symbol-keys one would have to import the symbol, but where is that symbol located? https://github.com/dsb-norge/vue-keycloak-js/blob/main/src/index.ts#L12 says it's not exported, it's just const KeycloakSymbol

idc77 commented 1 year ago

see #161

import {defineComponent,inject} from 'vue'
import VueKeyCloak from '@dsb-norge/vue-keycloak-js'

export default defineComponent({
  name: 'MainLayout',
  setup() {
    const symbol = VueKeyCloak.KeycloakSymbol
    const kc = inject(symbol)
    console.log(kc.tokenParsed)
  }
})

even if the IDE complains that

Argument type symbol is not assignable to parameter type InjectionKey<unknown> | string
Type symbol is not assignable to type string
 Type symbol is not assignable to type InjectionKey<unknown>