I am trying to authenticate a user with Auth0 service using SvelteKit, on the server side but keep getting the error invalid_token
, cannot read properties of undefined
:
outer {
error: 'invalid_token',
errorDescription: "Cannot read properties of undefined (reading 'XMLHttpRequest')"
}
The login endpoint:
import * as auth0 from "auth0-js";
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function post({ request }) {
const body = await request.json();
const hash = body.hash;
console.log("Sign-in.ts", hash);
// Initialize the Auth0 application
var webAuth = new auth0.WebAuth({
domain: '<domain>',
clientID: '>clientid>'
});
// Parse the URL and extract the Access Token
webAuth.parseHash({hash: hash, state: "rtre4", nonce: "er324"}, function (err, authResult) {
if (err) {
return console.log("outer", err);
}
webAuth.client.userInfo(authResult.accessToken, function (innerErr, user) {
// This method will make a request to the /userinfo endpoint
// and return the user object, which contains the user's information,
// similar to the response below.
if (innerErr) {
return console.log("inner", innerErr);
}
console.log(user);
});
});
return {
status: 200,
body: {
message: "OK"
}
};
};
I can successfully log the user in and redirect the user to my /login route with the access and id tokens as hash in the url.
Next I am trying to get the user details. I want to get the user details in the server, so I send the complete hash to my /api/login.ts
endpoint with a POST
request, and call the auth0-js
function parseHash
in the server endpoint, which fails. The same code works on the client-side, though.
The landing page:
<script lang="ts">
import { onMount } from 'svelte';
onMount(async () => {
const hash = window.location.hash;
const response = await fetch("/api/sign-in", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
hash: hash
})
});
console.log(response);
});
</script>
<div class="content">
<p>Redirecting, please wait...</p>
</div>
Therefore I am thinking either the cookie somehow changes during stringifying it, or Sveltekit does not have XmlHttpRequest, but does anyone has further insight?
Thanks to Andreas's comments, I realized that XmlHttpRequest
is a browser feature that does not exist in a server. For this reason, I have implemented a manual request to the Auth0 endpoint using the token I get from the page to get the user details:
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function post({ request }) {
/**
* auth0.WebAuth does not work on server side because it uses XmlHttpRequest, which is unavailable on server
*/
const body = await request.json();
const token = body.accessToken;
const response = await fetch("https://<app Auth0 address>/userinfo", {
method: "GET",
headers: {
"Content-Type":"application/json",
"Authorization": `Bearer ${token}`},
});
const userData = await response.json();
console.log(userData);
};
};
I am still calling the method webAuth.parseHash
in the client-side where auth0.js works, because this method also validates the tokens automatically. After validation, I am POST
ing the access token to the endpoint.