Koa 鉴权实战 - OAuth

简介: Koa 鉴权实战 - OAuth

OAuth

使用 github OAuth 实现用户登录
前端页面 index.html

<html>

<head>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>

<body>
  <div id="app">
    <button @click='oauth()'>Login with Github</button>
    <div v-if="userInfo">
      Hello {{userInfo.name}}
      <img style="width: 50px;height: 50px;" :src="userInfo.avatar_url" />
    </div>
    <ul>
      <li v-for="(log, idx) in logs" :key="idx">{{log}}</li>
    </ul>
  </div>
  <script>

  </script>
  <script>
    axios.interceptors.request.use(
      config => {
        const token = window.localStorage.getItem("token");
        if (token) {
          // 判断是否存在 token,如果存在的话,则每个 http header 都加上 token
          config.headers.common["Authorization"] = "Bearer " + token;
        }
        return config;
      },
      err => {
        return Promise.reject(err);
      }
    );

    axios.interceptors.response.use(
      response => {
        app.logs.push(JSON.stringify(response.data));
        return response;
      },
      err => {
        app.logs.push(JSON.stringify(err));
        return Promise.reject(err);
      }
    );
    const app = new Vue({
      el: "#app",
      data: {
        logs: [],
        userInfo: null
      },
      methods: {
        async oauth() {
          window.open('/auth/github/login', '_blank')
          const intervalId = setInterval(() => {
            console.log("等待认证中..");
            if (window.localStorage.getItem("authSuccess")) {
              clearInterval(intervalId);
              window.localStorage.removeItem("authSuccess");
              this.getUser();
            }
          }, 500);
        },
        async getUser() {
          const res = await axios.get("/auth/github/userinfo");
          console.log('res:', res.data);
          this.userInfo = res.data;
        }
      }
    });
  </script>
</body>

</html>

服务端 index.js

const Koa = require('koa')
const router = require('koa-router')()
const static = require('koa-static')
const app = new Koa();
const axios = require('axios')
const querystring = require('querystring')
const jwt = require("jsonwebtoken");
const jwtAuth = require("koa-jwt");

const accessTokens = {}

const secret = "my secret";
app.use(static(__dirname + '/'));

// 从 github 注册 Oauth application 后获取 client_id 和 client_secret
const config = {
  client_id: '73a4f730f2e8cf7d5fcf',
  client_secret: '74bde1aec977bd93ac4eb8f7ab63352dbe03ce48',
}

router.get('/auth/github/login', async (ctx) => {
    // 重定向到认证接口,并配置参数
    const path = `https://github.com/login/oauth/authorize?${querystring.stringify({ client_id: config.client_id })}`;

    // 转发到 github 授权服务器
    ctx.redirect(path);
})

// Authorization callback URL
router.get('/auth/github/callback', async (ctx) => {
    console.log('callback..')
    const code = ctx.query.code;
    const params = {
        client_id: config.client_id,
        client_secret: config.client_secret,
        code: code
    }
    let res = await axios.post('https://github.com/login/oauth/access_token', params)
    const access_token = querystring.parse(res.data).access_token
    const uid = Math.random() * 99999
    accessTokens[uid] = access_token

    const token = jwt.sign(
        {
            data: uid,
            // 设置 token 过期时间,一小时后,秒为单位
            exp: Math.floor(Date.now() / 1000) + 60 * 60
        },
        secret
    )
    ctx.response.type = 'html';
    console.log('token:', token)
    ctx.response.body = ` <script>window.localStorage.setItem("authSuccess","true");window.localStorage.setItem("token","${token}");window.close();</script>`;
})

router.get('/auth/github/userinfo', jwtAuth({
    secret
}), async (ctx) => {
    // 验证通过,state.user
    console.log('jwt playload:', ctx.state.user)
    const access_token = accessTokens[ctx.state.user.data]
    res = await axios.get('https://api.github.com/user?access_token=' + access_token)
    console.log('userAccess:', res.data)
    ctx.body = res.data
})

app.use(router.routes());
app.use(router.allowedMethods());
app.listen(7001);
相关文章
|
1月前
|
JSON 数据安全/隐私保护 数据格式
Nest.js 实战 (八):基于 JWT 的路由身份认证鉴权
这篇文章介绍了身份验证的重要性和多种处理策略,重点放在了JWT(JSON Web Token)认证在Nest.js框架中的应用。文章包含了JWT认证的流程,如何在Nest.js中实现,以及如何创建JWT认证策略。包括了安装依赖,创建处理认证流程的文件,以及如何使用HttpException过滤器来处理未登录访问。
Nest.js 实战 (八):基于 JWT 的路由身份认证鉴权
|
3月前
|
存储 JSON API
在django3应用中使用现代的JWT鉴权
【6月更文挑战第8天】本文介绍流行的鉴权方式,JSON Web Tokens (JWT) 是一种验证JSON数据所有者的机制,它是一个编码的、安全的字符串,包含可信任的数据且能加密签名。无状态的令牌认证允许客户端存储令牌并将其在每次请求。
44 8
在django3应用中使用现代的JWT鉴权
|
4月前
|
存储 JSON 前端开发
前端的JWT怎么进行用户认证?
前端的JWT怎么进行用户认证?
47 2
|
9月前
|
SQL API Go
go-zero jwt 鉴权快速实战
go-zero jwt 鉴权快速实战
157 0
|
数据安全/隐私保护
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
420 0
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
|
存储 JavaScript 安全
带你一文使用NodeJS、JWT、Vue搞定基于角色的授权
在本教程中,我们将完成一个关于如何在 Node.js 中 使用 JavaScript ,并结合 JWT 认证,实现基于角色(role based)授权/访问的简单例子。
|
JSON 数据可视化 安全
JWT 鉴权插件上线!让你的 API 更安全!
API鉴权是保证API安全性和可用性的一项重要措施。通过API鉴权,系统可以对用户或者应用进行有效的身份认证和权限管理。 除了我们之前更新的 Basic Auth 鉴权插件,这次给大家带来 JWT 鉴权插件。
JWT 鉴权插件上线!让你的 API 更安全!
|
存储 JSON NoSQL
手把手教大家在 gRPC 中使用 JWT 完成身份校验
手把手教大家在 gRPC 中使用 JWT 完成身份校验
|
XML 存储 JSON
gin框架学习-JWT认证
由于 JSON 不像 XML 那样冗长,因此在对其进行编码时,它的大小也更小,这使得 JWT 比 SAML 更紧凑。这使得 JWT 成为在 HTML 和 HTTP 环境中传递的不错选择。
247 0
gin框架学习-JWT认证
|
存储 JSON 算法
【实践】手把手带你实现JWT登录鉴权
JWT的全称是JSON Web Token,他是一种基于JSON的用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成: 头信息(header), 载荷(payload):也就是消息体和签名(signature);他是一种用于身份提供者和服务提供者双方之间传递安全信息简洁的、URL安全的表述性声明规范。是一个为分布式应用环境间传递身份信息而执行的一种基于JSON的开放标准(RFC 7519),他定义了一种简洁的,自包含的方法用于通信双方之间以json对象的形式安全地传递信息。因为有数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或RSA的公私秘钥对其进行签名。
2871 0