DEV Community

Cover image for Implementing OpenID Connect (OIDC) Authentication with Nuxt 3

Implementing OpenID Connect (OIDC) Authentication with Nuxt 3

Welker Arantes Ferreira on January 30, 2023

Intro Recently i started migrating an application from Nuxt 2 to Nuxt 3, but when i faced the authentication part i got a little lost si...
Collapse
 
kingside88 profile image
Kingside88 • Edited

Thank you for your're tutorial.
For now I am strugeling to implement it because in this file:
// /middleware/auth.global.ts
It redirects me the whole time. Because the user is always null.
if (!user && !authFlowRoutes.includes(to.path)) {
services.$auth.signInRedirect()
} else {
authStore.setUpUserCredentials(user)
}

I use keycloak for this and implemented it with KeycloakJs and sidebase/nuxt-auth. But I would prefer to use it server side.
If someone is interested in Nuxt3 with KeycloakJs, you could check my ready to go demo: github.com/Kingside88/nuxt3-primev...

Any chance you could provide a demo Github repo?

Collapse
 
taikio profile image
Welker Arantes Ferreira

Hi,

I will provide a Github repo as soon as possible

Collapse
 
kingside88 profile image
Kingside88

I did it for you, if you want you can begin there.
But in the example I get the error: window is not defined

Image description
github.com/Kingside88/nuxt3-oidc-c...

Thread Thread
 
taikio profile image
Welker Arantes Ferreira

I published an example project on my Github, you can access it through this link: github.com/taikio/nuxt-3-oidc-auth

Collapse
 
mauricio_andrade profile image
Maurício Andrade Albuquerque

I wrote another article with some modifications:

Collapse
 
radonyizsolt profile image
Zsolt Rádonyi

Hi!
I am having a small trouble with this. I am trying to get the user profile data in my components, but it seems like when I first login for a short time it is not available yet. Once I refresh everything is available. Is there any way I can make sure that the authStore.setUpUserCredentials is finished before the middleware let's it through?

Thank you!

Collapse
 
gavinie profile image
GavinIE

Hi Welker, thanks for the article. Did you ever switch to using environment variables? I am struggling to get that working correctly. Thanks

Collapse
 
taikio profile image
Welker Arantes Ferreira

Hi Gavin,

To use environment variables in Nuxt 3 you need to follow these steps:

1 - create an .env file with the environment variables. Ex:

BASE_URL=http://api.identity-server.com
Enter fullscreen mode Exit fullscreen mode

2 - in the nuxt.config file you need to set the values ​​inside the runtimeConfig property. By default these values ​​are only accessible on the server side, if you want to access the values ​​in Vuejs components define them inside the public property.
EX:

export default defineNuxtConfig({
  runtimeConfig: {
    baseUrl: process.env.BASE_URL,
    public: {
      publicValue: ' '
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

3 - In the Vuejs component or in the endpoint access the values ​​through the composable useRuntimeConfig.
Ex:

const config = useRuntimeConfig()
Enter fullscreen mode Exit fullscreen mode

For more detailed information take a look at the official Nuxt documentation:

nuxt.com/docs/api/composables/use-...

Collapse
 
gavinie profile image
GavinIE

Thanks very much. I have it configured like this currently and was just wondering if there was a way to implement this solution without needing to place that information in the public runtimeConfig.

I will keep looking and check in if I find a way to move that config to a more secure place.

Thread Thread
 
taikio profile image
Welker Arantes Ferreira

In my case, to make it safer, I did it like this:

1 - I created an endpoint within the Nuxt project itself and check if there is a Secret Key in the request header:

// /server/api/settings.ts
import { sendError, createError } from "h3";

export default defineEventHandler((event) => {
  const authorizationHeader = getHeader(event, "authorization");

  if (
    !authorizationHeader ||
    authorizationHeader !== "SECRET_KEY"
  ) {
    return sendError(
      event,
      createError({ statusCode: 401, statusMessage: "Missing API key" })
    );
  }

  const runtimeConfig = useRuntimeConfig();

  return runtimeConfig;
});
Enter fullscreen mode Exit fullscreen mode

2 - I created a service to fetch this data. Then I make the request in the application startup middleware and store it in the store:

// /services/settings/index.ts
import { ISettings } from "./types";

export default class SettingsService {
  private apiKey: string;

  constructor() {
    this.apiKey = "SECRET_KEY";
  }

  async get(): Promise<ISettings> {
    const headers = { authorization: this.apiKey };

    const result = await $fetch<ISettings>("/api/settings", {
      method: "get",
      headers,
    });

    return result;
  }
}
Enter fullscreen mode Exit fullscreen mode
// /middleware/auth-middleware.global.ts
export default defineNuxtRouteMiddleware(async (to, _from) => {
    ...
    const settings = await services.$settings.get()
    settingsStore.setSettings(settings)
})
Enter fullscreen mode Exit fullscreen mode
Collapse
 
victorneves profile image
Victor Neves

Hi Welker

There is any way to make this work also with SSR?

Thanks