Search code examples
keycloakfetch-apiserver-side-renderingaccess-tokennuxt3.js

Retrieve an oidc access token from Nuxt 3 app


I tried to retrieve a simple token from an idp in my Nuxt 3 fresh app. To do that I've created a vue page which calls my ssr API to get the token. But when I call the idp I get a fetch failed response.

With my postman that work perfectly and I don't know why that doesn't work here.

I'm new in nuxt and oidc world. I surrely don't do something correctly but I don't know what... Maybe fetching method or I missing something in my header/body request?

EDITED

Here is my view page:

<h1>Home Page</h1>

  <div>
    <button @click="getToken">Get Token</button>
    <p>{{ token }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const token = ref(null);

const getToken = async () => {
  try {
    const response = await $fetch('/api/token');
    const data = await response.json();
    token.value = data;
  } catch (error) {
    console.error('Error fetching token:', error);
  }
};
</script>

Here is my SSR api (server/api/token.js):

export default defineEventHandler(async (event) => {

  try {
    const token  = await fetch (
        `https://.../token`,
        { 
            headers: {
            'Content-Type': 'application/json',
            } ,
            method : 'POST', 
            body : JSON.stringify({
                'client_id': "****",
                'client_secret': "****",
                'grant_type': "password",
                'username': "****",
                'password': "****",
            })
        }
      );

    return token;
  
  } catch (error) {

      console.log(error);
    sendError(event, createError({
      statusCode: 500,
      statusMessage: 'Internal Server Error: ',
      data: {
          error: error.message,
          stack: error.stack,
      }
    }));
  }

})

I have now a Missing form parameter: grant_type

Error 400 : 
{
    "error": "invalid_request",
    "error_description": "Missing form parameter: grant_type"
}

body content: {"client_id":"****","client_secret":"****","grant_type":"password","username":"****","password":"****"}


Solution

  • I finally get the token by using URLSearchParams and set again application/x-www-form-urlencoded instead of using JSON.stringify with application/json. I don't undestand why with application/json I got an Invalid request : Missing form parameter: grant_type that I was correctly set in the body.

    Here is my final code to retrieve the token :

    export default defineEventHandler(async (event) => {
      try {
        const token  = await fetch(`https://****/realms/test/protocol/openid-connect/token`,
          { 
            method : 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({
              'client_id': "****",
              'client_secret': "****",
              'grant_type': "password",
              'username': "****",
              'password': "****"
            })
          });
    
        return token;
      } catch (error) {
        sendError(event, createError({
          statusCode: 500,
          statusMessage: 'Internal Server Error: ',
          data: {
              error: error.message,
              stack: error.stack,
          }
        }));
      }
    
    })
    

    Thanks to @C3roe to help me to understand my problem.