令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。
(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。
(2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。
(3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。
上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。
Four ways to get the token
- 授权码(authorization-code)
- 隐藏式(implicit)
- 密码式(password):
- 客户端凭证(client credentials)
A simple demo about third-party login
In config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const GITHUB_OAUTH_URL = 'https://github.com/login/oauth/authorize' const SCOPE = 'user'
const github = { request_token_url: 'https://github.com/login/oauth/access_token', client_id: '7719dcc449a12e7f83f4', client_secret: '42771ea51b4a3afac6ab67cae5cd8b924f81c7fc', }
module.exports = { github, GITHUB_OAUTH_URL, OAUTH_URL: `${GITHUB_OAUTH_URL}?client_id=${github.client_id}&scope=${SCOPE}`, }
|
In server/auth.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| const axios = require('axios') const config = require('../config')
const { client_id, client_secret, request_token_url } = config.github
module.exports = (server) => { server.use(async (ctx, next) => { if (ctx.path === '/auth') { console.log(ctx.path) const { code } = ctx.query if (code) { const result = await axios({ method: 'POST', url: request_token_url, data: { client_id, client_secret, code, }, headers: { Accept: 'application/json', }, })
if (result.status === 200 && (result.data && !result.data.error)) { ctx.session.githubAuth = result.data
const { access_token, token_type } = result.data const { data: userInfo } = await axios({ method: 'GET', url: 'https://api.github.com/user', headers: { Authorization: `${token_type} ${access_token}`, }, })
ctx.session.userInfo = userInfo ctx.redirect((ctx.session && ctx.session.urlBeforeOAuth) || '/') ctx.session.urlBeforeOAuth = '' } else { ctx.body = `request token failed ${result.data && result.data.error}` } } else { ctx.body = 'code not exist' } } else { await next() } }) }
|