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);
相关文章
|
3月前
|
JSON 数据安全/隐私保护 数据格式
Nest.js 实战 (八):基于 JWT 的路由身份认证鉴权
这篇文章介绍了身份验证的重要性和多种处理策略,重点放在了JWT(JSON Web Token)认证在Nest.js框架中的应用。文章包含了JWT认证的流程,如何在Nest.js中实现,以及如何创建JWT认证策略。包括了安装依赖,创建处理认证流程的文件,以及如何使用HttpException过滤器来处理未登录访问。
196 0
Nest.js 实战 (八):基于 JWT 的路由身份认证鉴权
|
3月前
|
关系型数据库 API Go
[golang]在Gin框架中使用JWT鉴权
[golang]在Gin框架中使用JWT鉴权
105 0
|
6月前
|
存储 JSON 前端开发
前端的JWT怎么进行用户认证?
前端的JWT怎么进行用户认证?
61 2
|
11月前
|
SQL API Go
go-zero jwt 鉴权快速实战
go-zero jwt 鉴权快速实战
198 0
EMQ
|
JSON 安全 算法
深入解析 MQTT 中基于 Token 的认证和 OAuth 2.0
本文将深入了解基于 Token 的认证和 OAuth 2.0,阐述它们的原理并展示它们在 MQTT 中的应用。
EMQ
359 0
深入解析 MQTT 中基于 Token 的认证和 OAuth 2.0
|
中间件
eggjs 怎么使用 egg-jwt 实现登录验证中间件?
eggjs 怎么使用 egg-jwt 实现登录验证中间件?
466 9
eggjs 怎么使用 egg-jwt 实现登录验证中间件?
|
数据安全/隐私保护
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
451 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 完成身份校验