使用 SvelteKit 的 Auth0 服务器端身份验证

Auth0 Server Side Authentication with SvelteKit

我知道没有官方的 Auth0 SvelteKit 插件可以直接使用,所以我尝试使用 JS 中的基本 API 函数实现手动方法进行服务器端身份验证和会话管理,使用 auth0.js 版本 9.11.

使用以下页面,我可以将用户重定向到Auth0通用登录页面,用户登录成功后重定向到我的登陆页面。我的计划是从页面上的用户令牌获取用户详细信息,然后将这些详细信息发送到服务器端点。在端点中,我会将这些详细信息保存到数据库(使用访问令牌)以进行登录会话管理,然后发送一个 HttpOnly cookie 用于 auth guards..etc.

但是,我在着陆页中不断收到以下错误消息:

Uncaught (in promise) TypeError: can't assign to property "__enableIdPInitiatedLogin" on "#access_token=eyJhbGciOi...<very long token>...BNW1uzA&scope=openid%20profile%20email&expires_in=7200&token_type=Bearer&state=rtre4": not an object

用于获取用户详细信息但不起作用的代码如下:

<script lang="ts">
    import { onMount } from 'svelte';

    onMount(async () => {
        // Initialize the Auth0 application
        var webAuth = new auth0.WebAuth({
            domain: '<domain>',
            clientID: '<clientId>'
        });
        //test
        console.log(window.location.hash);
        // Parse the URL and extract the Access Token
        webAuth.parseHash(window.location.hash, function (err, authResult) {
            if (err) {
                return console.log(err);
            }
            // webAuth.client.userInfo(authResult.accessToken, function (err, 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.
            // });
        });
    });
</script>

<svelte:head>
    <script src="https://cdn.auth0.com/js/auth0/9.11/auth0.min.js"></script>
</svelte:head>
<div class="content">
    <p>Redirecting, please wait...</p>
</div>

将用户重定向到通用登录页面的代码如下:

<script lang="ts">

    import Button from '@smui/button';

    const login = () => {
        // Initialize app - auth0 is defined as external script in <svelte:head>
            var webAuth = new auth0.WebAuth({
            domain: '<domain>,
            clientID: '<clientid>'
        });

        // Calculate URL to redirect to
        var url = webAuth.client.buildAuthorizeUrl({
            clientID: '<clientid>', // string
            responseType: 'token id_token', // code or token
            redirectUri: 'http://localhost:3000/login',
            scope: 'openid profile email',
            state: '<state>',
            nonce: '<nonce>'

        });

        window.location = url;
    }
</script>

<svelte:head>
    <script src="https://cdn.auth0.com/js/auth0/9.11/auth0.min.js"></script>
</svelte:head>

<div class="content">
    <Button on:click={login}>Login</Button>
    
</div>

EDIT 我根据 Kalana 的评论将 id_token 添加到登录 url 构造中(这也需要 nonce 参数)和根据新代码修改错误截图

经过更多的挖掘,我意识到提供给 parseHash 函数的选项需要是一个 JSON 对象。您还需要在创建登录请求时包含 id_token(感谢 Kalana 的评论),以及 nonce 参数。您也必须为 parseHash 函数提供相同的 statenonce 值。此外,此功能的 hash 是可选的;如果给出 none 它可以自动从 windows.location.hash 中获取它。

最后Auth0服务获取用户信息的工作代码如下:

<script lang="ts">
    import { onMount } from 'svelte';

    onMount(async () => {
        // Initialize the Auth0 application
        var webAuth = new auth0.WebAuth({
            domain: '<domain>',
            clientID: '<clientid>'
        });
        
        // Parse the URL and extract the Access Token
        webAuth.parseHash({state: "<sameState>", nonce: "<sameNonce>"}, function (err, authResult) {
            if (err) {
                return console.log(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(innerErr);
                    
                }
                console.log(user);
            });
        });
    });
</script>

<svelte:head>
    <script src="https://cdn.auth0.com/js/auth0/9.11/auth0.min.js"></script>
</svelte:head>
<div class="content">
    <p>Redirecting, please wait...</p>
</div>