You need to enable JavaScript to run this app. Vue3 基于AWS Amplify实现Cognito用户认证及OAuth令牌获取
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 基于AWS Amplify实现Cognito用户认证及OAuth令牌获取

Vue3 + AWS Amplify + Cognito 认证落地方案

核心问题回应

  • 完全可以在Vue3项目中单独使用AWS Amplify的认证模块,不需要引入完整的UI组件包,仅靠@aws-amplify/auth就能完成从登录、状态检查到令牌自动刷新的全流程,目前已有大量生产项目落地该方案。
  • 对接Cognito OAuth2流程不需要强制走页面重定向跳转,通过原生的Auth模块调用就能直接用用户名密码完成认证,拿到可用于调用AWS API Gateway的访问令牌,全程可在单页应用内完成交互,不需要跳出当前站点。

现有代码无法正常运行的核心原因

  • 自定义元素未注册:Vue3默认会把模板里的非内置标签当成本地组件解析,你直接编写的amplify-authenticator、amplify-sign-in这类第三方自定义标签,没有经过注册流程会直接被Vue忽略,根本不会渲染对应的UI,这就是你看不到登录、登出按钮的直接原因。
  • 存储配置错误:你在配置里给cookieStorage设置的domain是Cognito的托管域名(*.amazoncognito.com),受浏览器跨域安全规则限制,当前localhost站点根本不允许向其他第三方域名写入cookie,这会导致认证状态完全无法持久化,每次页面加载都读不到之前的登录态,始终显示未登录。
  • 插件挂载方式错误:Vue3的app.use()方法仅支持第一个参数为插件实例,后续传入的参数会被当成插件的初始化参数,而非依次注册插件。你原来的写法把Amplify、Auth作为参数传给了vuex的store插件,根本没有触发Amplify的内部初始化逻辑,相当于只导入了依赖包,没有完成真正的运行时绑定。

分步实现可正常运行的认证流程

1. 修正main.js初始化逻辑

把原有错误的配置、挂载逻辑替换为如下代码,重点修正存储配置、自定义元素规则、初始化顺序:

import { createApp } from 'vue'
import App from './App.vue'
import { createStore } from 'vuex'
import { Amplify } from 'aws-amplify'
import { Auth } from '@aws-amplify/auth'

Amplify.configure({
  Auth: {
    identityPoolId: 'eu-central-1_REST-OF-ID',
    region: 'eu-central-1',
    userPoolWebClientId: '4t49u0pu0skkREST-OF-ID',
    mandatorySignIn: false,
    // 移除指向Cognito域名的cookieStorage配置,本地开发用默认localStorage存储状态
    storage: window.localStorage,
    authenticationFlowType: 'USER_PASSWORD_AUTH',
    oauth: {
      domain: 'PREFIX.auth.eu-central-1.amazoncognito.com',
      scope: ['phone', 'email', 'profile', 'openid', 'aws.cognito.signin.user.admin'],
      redirectSignIn: 'http://localhost:3000/',
      redirectSignOut: 'http://localhost:3000/',
      responseType: 'code'
    }
  }
})

const store = createStore({
  state() {
    return {
      entries: [],
      authState: 'loading' // 新增认证状态字段,用于控制UI渲染
    }
  },
  mutations: {
    addTime(state, item) {
      state.entries.push(item);
    },
    setAuthState(state, payload) {
      state.authState = payload
    }
  }
})

const app = createApp(App)
// 告诉Vue所有以amplify-开头的标签是外部自定义元素,不要当成本地组件解析
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('amplify-')
app.use(store)
app.mount("#app")

2. 手动实现登录交互,获取OAuth2令牌

如果不想依赖Amplify自带的UI组件,完全可以自己编写登录表单,直接调用Auth模块方法完成认证,这种方式可控性更强,也不会出现组件渲染异常的问题。
在需要的业务组件中引入Auth模块,编写核心逻辑:

import { Auth } from '@aws-amplify/auth'

export default {
  data() {
    return {
      username: '',
      password: '',
      isLoading: false,
      errorMsg: ''
    }
  },
  async mounted() {
    // 页面加载时检查已有登录态
    try {
      const currentSession = await Auth.currentSession()
      // 拿到的JWT令牌直接可以用于调用API Gateway
      const accessToken = currentSession.getAccessToken().getJwtToken()
      const idToken = currentSession.getIdToken().getJwtToken()
      this.$store.commit('setAuthState', 'signedIn')
      // 将令牌存在store中,后续请求时直接读取并加到请求头
    } catch (e) {
      this.$store.commit('setAuthState', 'signIn')
    }
  },
  methods: {
    async handleLogin() {
      this.isLoading = true
      this.errorMsg = ''
      try {
        // 传入用户名密码完成认证
        await Auth.signIn(this.username, this.password)
        // 登录成功后直接拉取会话,拿到全套OAuth2令牌
        const session = await Auth.currentSession()
        const accessToken = session.getAccessToken().getJwtToken()
        // 调用API Gateway时,在请求头加上 `Authorization: ${accessToken}` 即可通过鉴权
        this.$store.commit('setAuthState', 'signedIn')
      } catch (e) {
        this.errorMsg = e.message
      } finally {
        this.isLoading = false
      }
    },
    async handleLogout() {
      await Auth.signOut()
      this.$store.commit('setAuthState', 'signIn')
    }
  }
}

3. UI渲染逻辑修正

在模板中根据store存储的认证状态手动渲染登录、登出按钮,不需要依赖Amplify的authenticator组件:

<template>
  <div v-if="$store.state.authState === 'loading'">状态加载中...</div>
  <div v-else-if="$store.state.authState === 'signIn'">
    <input v-model="username" placeholder="用户名" />
    <input v-model="password" type="password" placeholder="密码" />
    <button @click="handleLogin" :disabled="isLoading">登录</button>
    <p v-if="errorMsg" style="color: red">{{ errorMsg }}</p>
  </div>
  <div v-else>
    <p>当前已登录</p>
    <button @click="handleLogout">登出</button>
  </div>
</template>

关键注意事项

  • Cognito用户池的对应应用客户端必须在AWS控制台开启USER_PASSWORD_AUTH认证流,否则调用登录接口会直接返回权限错误。
  • 本地开发场景不要配置指向Cognito托管域名的cookie存储,浏览器跨域安全策略会直接阻断状态写入,用默认的localStorage存储状态是最稳定的方案。
  • Auth模块内部已经自动处理了令牌刷新、过期续期的全流程,拿到的Access Token不需要额外走OAuth的code换token步骤,直接读取JWT值加到API请求头即可使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.11 10:27:03