如何在服务器端使用 SvelteKit 获取 Auth0 中的用户详细信息
How can I get the user details in Auth0 using SvelteKit on the server side
我正在尝试在服务器端使用 SvelteKit 通过 Auth0 服务对用户进行身份验证,但不断收到错误 invalid_token
、cannot read properties of undefined
:
outer {
error: 'invalid_token',
errorDescription: "Cannot read properties of undefined (reading 'XMLHttpRequest')"
}
登录端点:
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"
}
};
};
我可以成功登录用户并将用户重定向到我的 /login 路由,访问和 ID 令牌作为 url 中的散列。
接下来我试图获取用户详细信息。我想在服务器中获取用户详细信息,因此我使用 POST
请求将完整的哈希发送到我的 /api/login.ts
端点,并调用 auth0-js
函数 parseHash
服务器端点,失败。不过,相同的代码适用于客户端。
着陆页:
<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>
因此我认为要么 cookie 在字符串化过程中以某种方式发生了变化,要么 Sveltekit 没有 XmlHttpRequest,但是有人有进一步的见解吗?
感谢 Andreas 的评论,我意识到 XmlHttpRequest
是服务器中不存在的浏览器功能。出于这个原因,我使用从页面获取的令牌实现了对 Auth0 端点的手动请求以获取用户详细信息:
/** @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);
};
};
我仍然在 client-side 中调用方法 webAuth.parseHash
,其中 auth0.js 有效,因为此方法还会自动验证令牌。验证后,我POST
将访问令牌发送到端点。
如果您的 cookie 中有 JWT 令牌,您可以解码 JWT cookie 以获取用户信息
你可以这样做:
import * as cookie from 'cookie';
import Buffer from 'buffer';
export const handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
if(!cookies.id_token) {
return await resolve(event);
}
const base64Payload = cookies.id_token.split('.')[1];
const decodedJWTToken = base64Payload ? Buffer.Buffer.from(base64Payload, 'base64') : '';
event.locals.user = decodedJWTToken ? JSON.parse(decodedJWTToken.toString()) : null
const response = await resolve(event);
return response
};
export function getSession({ locals }) {
return {
user: locals.user && {
nickname: locals.user.nickname ? locals.user.nickname : null,
email: locals.user.email ? locals.user.email : null,
sub: locals.user.sub ? locals.user.sub : null,
email_verified: locals.user.email_verified ? locals.user.email_verified : null,
picture: locals.user.picture ? locals.user.picture : null,
}
};
}
我正在尝试在服务器端使用 SvelteKit 通过 Auth0 服务对用户进行身份验证,但不断收到错误 invalid_token
、cannot read properties of undefined
:
outer {
error: 'invalid_token',
errorDescription: "Cannot read properties of undefined (reading 'XMLHttpRequest')"
}
登录端点:
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"
}
};
};
我可以成功登录用户并将用户重定向到我的 /login 路由,访问和 ID 令牌作为 url 中的散列。
接下来我试图获取用户详细信息。我想在服务器中获取用户详细信息,因此我使用 POST
请求将完整的哈希发送到我的 /api/login.ts
端点,并调用 auth0-js
函数 parseHash
服务器端点,失败。不过,相同的代码适用于客户端。
着陆页:
<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>
因此我认为要么 cookie 在字符串化过程中以某种方式发生了变化,要么 Sveltekit 没有 XmlHttpRequest,但是有人有进一步的见解吗?
感谢 Andreas 的评论,我意识到 XmlHttpRequest
是服务器中不存在的浏览器功能。出于这个原因,我使用从页面获取的令牌实现了对 Auth0 端点的手动请求以获取用户详细信息:
/** @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);
};
};
我仍然在 client-side 中调用方法 webAuth.parseHash
,其中 auth0.js 有效,因为此方法还会自动验证令牌。验证后,我POST
将访问令牌发送到端点。
如果您的 cookie 中有 JWT 令牌,您可以解码 JWT cookie 以获取用户信息 你可以这样做:
import * as cookie from 'cookie';
import Buffer from 'buffer';
export const handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
if(!cookies.id_token) {
return await resolve(event);
}
const base64Payload = cookies.id_token.split('.')[1];
const decodedJWTToken = base64Payload ? Buffer.Buffer.from(base64Payload, 'base64') : '';
event.locals.user = decodedJWTToken ? JSON.parse(decodedJWTToken.toString()) : null
const response = await resolve(event);
return response
};
export function getSession({ locals }) {
return {
user: locals.user && {
nickname: locals.user.nickname ? locals.user.nickname : null,
email: locals.user.email ? locals.user.email : null,
sub: locals.user.sub ? locals.user.sub : null,
email_verified: locals.user.email_verified ? locals.user.email_verified : null,
picture: locals.user.picture ? locals.user.picture : null,
}
};
}