You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SvelteKitAuth集成Cognito时如何获取access_token与id_token?

问题背景

我正在开发一个SvelteKit应用,使用Cognito作为身份认证提供商。调用AWS的IsAuthorizedWithToken API时,需要提供已登录用户的access_token或id_token,希望在+page.server.ts文件中获取这些令牌。

当前+page.server.ts中的代码:

// somefolder/+page.server.ts

export async function load({ locals }) {
    const session = await locals.getSession();
    const { id_token, access_token } = session

    // 使用id_token、access_token
}

受NextAuth获取提供商令牌的方法启发,我使用jwt回调在用户登录时获取令牌,控制台日志确认session中存在令牌。但刷新页面后,令牌变为undefined,尽管用户仍处于登录状态,且能访问session中的user.email等属性,推断令牌仅在登录时可用,后续请求无法获取。

当前hooks.server.ts中的代码:

// hooks.server.ts

import { SvelteKitAuth } from '@auth/sveltekit';
import Cognito from '@auth/core/providers/cognito';
import { AUTH_SECRET, COGNITO_USER_POOL_ID, COGNITO_CLIENT_SECRET } from '$env/static/private';
import { PUBLIC_COGNITO_CLIENT_ID } from '$env/static/public';
import type { Handle } from '@sveltejs/kit';

export const handle = SvelteKitAuth({
    secret: AUTH_SECRET,
    providers: [
        Cognito({
            clientId: PUBLIC_COGNITO_CLIENT_ID,
            clientSecret: COGNITO_CLIENT_SECRET,
            issuer: `https://cognito-idp.us-east-1.amazonaws.com/${COGNITO_USER_POOL_ID}`
        })
    ],
    callbacks: {
        async session({ session, token }) {
            session.user && (session.user.sub = token.sub);
            session.access_token = token.accessToken as string;
            session.id_token = token.id_token as string;
            console.log(session);
            return session;
        },
        async jwt({ token, account }) {
            if (account) {
                token.access_token = account.access_token;
                token.id_token = account.id_token;
            }
            return token;
        }
    }
}) satisfies Handle;
问题
  • Q1:为何令牌仅在用户登录时可用,后续请求无法获取?SvelteKitAuth对令牌做了什么处理?
  • Q2:在+page.server.ts中获取令牌的正确方式是什么?
解答

Q1:原因分析

  1. JWT回调逻辑漏洞:Auth.js的jwt回调仅在用户首次登录时会传入account参数(包含Cognito返回的令牌),此时你将令牌存入了token对象。但刷新页面时,jwt回调会被再次调用,但account参数为undefined,你的代码没有保留token中已有的令牌字段,导致刷新后token里的令牌丢失。
  2. 字段名称不匹配:jwt回调中存储的是token.access_token和token.id_token,但session回调中错误地读取token.accessToken(大小写不一致),直接导致session中无法正确获取令牌。
  3. SvelteKitAuth存储机制:SvelteKitAuth默认将JWT加密后存在客户端Cookie中,每次请求会解析这个JWT得到token对象。如果token里没有持久化令牌,刷新后自然无法从session中拿到。

Q2:正确解决方法

步骤1:修正jwt回调,持久化令牌

修改jwt回调,确保即使没有account参数,也返回包含已有令牌的token对象:

async jwt({ token, account }) {
    // 首次登录时,从account中获取令牌并存入token
    if (account) {
        token.access_token = account.access_token;
        token.id_token = account.id_token;
    }
    // 直接返回token,保留已有的令牌字段
    return token;
}

步骤2:修正session回调的字段名称

将session回调中的token.accessToken改为token.access_token,与jwt回调中的存储字段一致:

async session({ session, token }) {
    session.user && (session.user.sub = token.sub);
    // 修正字段名称,匹配jwt中存储的key
    session.access_token = token.access_token as string;
    session.id_token = token.id_token as string;
    return session;
}

步骤3:验证+page.server.ts中的获取逻辑

保持+page.server.ts中的代码不变,刷新页面后,session中的access_token和id_token就能正常获取:

// somefolder/+page.server.ts

export async function load({ locals }) {
    const session = await locals.getSession();
    const { id_token, access_token } = session

    // 正常使用id_token、access_token
}

额外注意事项

确保AUTH_SECRET环境变量配置正确,它是Auth.js加密JWT的密钥,如果配置错误会导致JWT解析失败,进而无法获取令牌。

内容的提问来源于stack exchange,提问作者bluprince13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:35:34