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天前
|
安全 Java 数据库
SpringSecurity+JWT前后端分离架构登录认证
在SpringSecurity实现前后端分离登录token认证详解_springsecurity前后端分离登录认证-CSDN博客基础上进行重构,实现前后端分离架构登录认证,基本思想相同,借鉴开源Gitee代码进行改造,具有更好的代码规范。
186 1
|
5月前
|
SQL API Go
go-zero jwt 鉴权快速实战
go-zero jwt 鉴权快速实战
|
12月前
|
存储 JSON NoSQL
手把手教大家在 gRPC 中使用 JWT 完成身份校验
手把手教大家在 gRPC 中使用 JWT 完成身份校验
|
存储 JSON 算法
go使用JWT进行跨域认证最全教学
go使用JWT进行跨域认证最全教学
120 0
|
存储 JSON 安全
(12)go-micro微服务JWT跨域认证
(12)go-micro微服务JWT跨域认证
105 0
|
JSON 数据可视化 安全
JWT 鉴权插件上线!让你的 API 更安全!
API鉴权是保证API安全性和可用性的一项重要措施。通过API鉴权,系统可以对用户或者应用进行有效的身份认证和权限管理。 除了我们之前更新的 Basic Auth 鉴权插件,这次给大家带来 JWT 鉴权插件。
JWT 鉴权插件上线!让你的 API 更安全!
|
数据安全/隐私保护
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
310 0
eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?
|
XML 存储 JSON
gin框架学习-JWT认证
由于 JSON 不像 XML 那样冗长,因此在对其进行编码时,它的大小也更小,这使得 JWT 比 SAML 更紧凑。这使得 JWT 成为在 HTML 和 HTTP 环境中传递的不错选择。
214 0
gin框架学习-JWT认证
|
JSON 算法 安全
使用jwt来保护你的接口服务
使用jwt来保护你的接口服务
98 0
|
JSON 安全 Java
JWT快速入门
JSON Web Token,是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间。该信息可以被验证和信任,因为它是的。:JWT最常见的场景的授权认证,一旦用户登录之后,后续每个请求都会包含JWT,系统处理每次用户请求之前,都会先进行JWT安全校验,通过之后再进行处理。由三部分组成,它们之间用圆点(.)连接。
185 0
JWT快速入门