authts / oidc-client-ts

OpenID Connect (OIDC) and OAuth2 protocol support for browser-based JavaScript applications
https://authts.github.io/oidc-client-ts/
Apache License 2.0
1.37k stars 207 forks source link

What are the requirements for silent refresh or for Vue in general? #1506

Open idc77 opened 5 months ago

idc77 commented 5 months ago

The documentation, if you can call it that, is very spartan. For Angular, there's a src/silent-callback.html, react is a completely different beast with their wrapped components. For Vue or rather Quasar, which builds upon Vue, there is no info, no example.

What do I need in order to get fully functional optional login with peridoic silent refresh working in Vue?

So far I have plugins/VueOIDCClient.js

export const VueOIDCClientSymbol = Symbol('VueOIDCClientSymbol');

plugins/VueOIDCClient.js

import {UserManager} from "oidc-client-ts";
import {VueOIDCClientSymbol} from "src/plugins/VueOIDCClientSymbol.js";

export default {
  install: (app, options) => {
    const manager = new UserManager(
      options.settings,
      options.redirectNavigator,
      options.popupNavigator,
      options.iframeNavigator
    )
    app.config.globalProperties.$manager = manager
    app.provide(VueOIDCClientSymbol, manager)
  }
}

And in boot/oidc.js (because Quasar uses boot files.

export default boot(async ({ app }) => {
  async function tokenInterceptor () {
    axios.interceptors.request.use(config => {
      config.headers.Authorization = `Bearer ${app.config.globalProperties.$manager.getUser().access_token}` //TODO: find out correct value
      return config
    }, error => {
      return Promise.reject(error)
    })
  }

  return new Promise(resolve => {
    const settings = {
      authority: process.env.OIDC_AUTHORITY,
      client_id: process.env.CLIENT_ID,
      redirect_uri: window.location.origin + window.location.pathname,
      post_logout_redirect_uri: window.location.origin,
      monitorSession: true,
    }
    app.use(VueOIDCClient, {
      settings: settings,
      redirectNavigator: undefined,
      popupNavigator: undefined,
      iframeNavigator: undefined,
    })
  })
})
//TODO: exec tokenInterceptor() on ready

^ the above is of course not complete

What fiels with what contents do I need where? In the case of Angular, I don't understand where is coming from.

It's not under assets or /src/.

In Vue, do I need to create a separate routed callback component?

idc77 commented 5 months ago

Here's what I have so far: https://github.com/idc77/quasar-oidc-client-ts-experiment

I have a dedicated route to /oidc-callback which does https://github.com/idc77/quasar-oidc-client-ts-experiment/blob/master/src/pages/SigninCallbackPage.vue

But silent? No idea. Also automatic refresh isn't working.

pamapa commented 5 months ago

Have you seen?:

Also notice, that this library supports an automatic way to do the renewing like described above:

Yes the documentation is spartanic, please feel free to provide more documentation to fill the gaps...

idc77 commented 5 months ago

Yes, I, who just stumbled upon this package should write proper elaborate documentation, as opposed to you, who is maintaining this package. Makes total sense.

idc77 commented 5 months ago

If the automatic refresh/renew was working this issue wouldn't exist.

dmeijboom commented 5 months ago

@idc77 I understand you're frustrated, but it's important to remember that contributors are volunteers who work on this in their free time. They don't owe you anything. If you want things to improve, go ahead and fix it.

dmeijboom commented 5 months ago

On topic: we don't use Vue but auto renew isn't working for us either. After debugging I found out that auto renew isn't working when the token is already expired. The SilentRenewService only adds a handler on the addAccessTokenExpiring event but not on the addAccessTokenExpired event.

~We can make a PR to fix this but it might be by design. I'm not sure if the renew flow works when the token is no longer valid (I guess it should work when either the refresh token is valid or the iFrame method is being used?).~

Edit: ^ this is obviously not going to work, I guess we'll have to implement this on our own as interaction is required when the token is already expired

klues commented 3 months ago

I'm also working on a Vue project and had the same question how to add OAuth integration to it. I've ended up using this library and writing an own service module oauthService.js handling all the things. I'm using localStorage to save the results of the authorization redirect in oauth-redirect.html and process it afterwards in oauthService.processCallbackData(). So I'm not handling the result within the Vue app, but in this external html file.

So in fact my solution isn't related to Vue at all, it's generic Javascript. I don't know if it's the best and easiest solution, but it works. Auto-renewal works if the access token expires soon (event accessTokenExpiring), but not if it's already expired. I solved this issue with a custom event handler on "accessTokenExpired". I don't know, why this isn't implemented by default - I've asked this question in an issue.