azard / egg-oauth2-server Goto Github PK
View Code? Open in Web Editor NEW:star2: OAuth2 server plugin for egg.js based on node-oauth2-server
License: MIT License
:star2: OAuth2 server plugin for egg.js based on node-oauth2-server
License: MIT License
config
config.oAuth2Server = {
debug: appInfo.env === 'local',
grants: ['password'],
accessTokenLifetime: null,
refreshTokenLifetime: null
}
Error
nodejs.invalid_argument: Missing parameter: `accessTokenLifetime`
at new InvalidArgumentError (/Volumes/Mac/Projects/Node/liubangback/node_modules/oauth2-server/lib/errors/invalid-argument-error.js:21:14)
at new TokenHandler (/Volumes/Mac/Projects/Node/liubangback/node_modules/oauth2-server/lib/handlers/token-handler.js:43:11)
at OAuth2Server.token (/Volumes/Mac/Projects/Node/liubangback/node_modules/oauth2-server/lib/server.js:74:10)
at Object.<anonymous> (/Volumes/Mac/Projects/Node/liubangback/node_modules/egg-oauth2-server/lib/server.js:82:36)
at Generator.next (<anonymous>)
at Object.dispatch (/Volumes/Mac/Projects/Node/liubangback/node_modules/koa-router/lib/router.js:334:5)
at dispatch.next (<anonymous>)
at onFulfilled (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:65:19)
at /Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:54:5
at new Promise (<anonymous>)
at Object.co (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:50:10)
at Object.toPromise (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:118:63)
at next (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:99:29)
at onFulfilled (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:69:7)
at /Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:54:5
at new Promise (<anonymous>)
at Object.co (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:50:10)
at Object.toPromise (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:118:63)
at next (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:99:29)
at onFulfilled (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:69:7)
at /Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:54:5
at new Promise (<anonymous>)
at Object.co (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:50:10)
at Object.toPromise (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:118:63)
at next (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:99:29)
at onFulfilled (/Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:69:7)
at /Volumes/Mac/Projects/Node/liubangback/node_modules/co/index.js:54:5
at new Promise (<anonymous>)
设置accessTokenLifetime refreshTokenLifetime 时区差个小时,如何处理
原来代码如下:
const user = yield server.options.model.getUser(
username,
password,
);
password后面多了个逗号
在oauth.js里面无法调用app , 我怎么在里面调用app.model的方法呢?
got a warning saying the name is different from plugin config name. logs attached below
[egg:loader] pluginName(oauth2Server) is different from pluginConfigName(oauth2-server)
大神您好,鉴权之后,如何在 controlle r 里面获取用户 ID 呀?
I found on some occasions, the Model being instantiated with the last request context, then I found this:
egg-oauth2-server/lib/server.js
Line 86 in 2d10b76
You should never save ctx
in application
ever. This is my fix:
{
getServer(ctx) {
if (!ctx[SERVER]) {
const { config, model: Model } = this;
const model = new Model(ctx);
ctx[SERVER] = new AuthServer(Object.assign(config, { model }));
return ctx[SERVER];
}
return ctx[SERVER];
}
}
018-07-29 15:50:49,771 ERROR 84272 [-/::1/-/8ms GET /user/token] nodejs.AssertionError [ERR_ASSERTION]: status code must be a number
在文档说明中有revoceToken的实现,但是再实例的抽象中没有logout之类的方法,是不是缺少了关于logout的实现?还是有别的什么用法?
fetch('http://127.0.0.1:7001/user/token',{method: 'POST', mode:'cors',credentials: 'include',headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization: 'Basic bXlfYXBwOm15X3NlY3JldA=='},body:'username=egg-oauth2-server&password=azard&grant_type=password'}) .then(function(res){return res.json()}).then(function(res){console.log(res)})
下面的Authorization是上一个接口的token_type + access_token
;
fetch('http://127.0.0.1:7001/user/authenticate',{method: 'GET', mode:'cors',credentials: 'include',headers:{Authorization: 'Bearer 51375d61bc4f4f7e9661d9a71f0745441024ee7c'}}) .then(function(res){return res.json()}).then(function(res){console.log(res)})
返回错误
{"error":"server_error","error_description":"Server error: `accessTokenExpiresAt` must be a Date instance"}
好像是格式有问题
1.路由要怎么写才能触发到这个传入fresh_token获取新的access_token
2.路由要怎么写能调用到revokeToken()
获取token body里面传哪些参数呢,希望文档可以写下
{
"error": "invalid_client",
"error_description": "Invalid client: cannot retrieve client credentials"
}
I have try egg-auth2-server as shown in test.
But I got the error message : "Missing parameter: grant_type
" with my request as follows:
request(
${host}/user/token, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Authorization: 'Basic bXlfYXBwOm15X3NlY3JldA==', }, data: { grant_type: 'password', username: 'egg-oauth2-server', password: 'azard', }, });
'oauth.js' and 'config.default.js' are the same as shown in test dir.
Wish to get some help, thanks.
RT.
参考:
(已经提交PR,代码见分支)
Can I use Client Credentials? I don't see a case.
authorization-code
有没有这种方式的简单例子?
实在看不明白服务端怎么配置和客户端怎么配合。
在 egg.js 中使用在获取token的saveToken之后会报如下错误
egg: 2.0.0
node: 8.9.0
os: mac 10.13.1
2017-11-29 03:22:00,577 ERROR 58549 [-/::1/-/126ms POST /login] nodejs.TypeError: undefined is not a function
at Object.<anonymous> (/Users/ole3021/ducklab/ci-backend/node_modules/egg-oauth2-server/lib/server.js:102:20)
at Generator.next (<anonymous>)
at onFulfilled (/Users/ole3021/ducklab/ci-backend/node_modules/co/index.js:65:19)
at <anonymous>
经初步排查错误代码发生在lib/server.js
中第101行的if (token) { yield* next; }
, 其中next不是可yield的generator函数,而是ctx对象。
修正方法可使用if(token) ctx.body = token
来替代(初步解决方法)
问题应该是对egg新版本的适配问题, 刚刚发现, 有时间的话会提pr,另外希望可以尽快适配并做好测试。:)
集成后一直报这个错误,检查了下,没配置错啊,有知道怎么回事的吗
我把server端这几个方法全部复写完毕了,现在发现不知道客户端怎么去请求调用了,能给个客户端调用的demo吗?
both
should be acceptable
是否可以考虑允许使用 app/extend/oauth.ts。
当我的项目是用 ts 来编写的时候 dev/debug 比较方便点。
What replaceResponse
do exactly?
https://github.com/Azard/egg-oauth2-server/blob/master/lib/server.js#L15-L31
Why we cannot do simply const response = new Response(ctx.response);
instead of const response = new Response(replaceResponse(ctx.response));
?
追踪代码发现是ctx.response.headers.hasOwnProperty,hasOwnProperty不是一个函数。但是不知道怎么解决
2017-09-21 16:37:56,696 ERROR 32793 [-/127.0.0.1/-/10737ms GET /user/token] nodejs.TypeError: options.headers.hasOwnProperty is not a function
at new Response (/Users/tusm/github/mygithub/egg-cms/node_modules/oauth2-server/lib/response.js:16:25)
at Object. (/Users/tusm/github/mygithub/egg-cms/node_modules/egg-oauth2-server/lib/server.js:63:24)
at Generator.next ()
at Object.dispatch (/Users/tusm/github/mygithub/egg-cms/node_modules/koa-router/lib/router.js:334:12)
at dispatch.next ()
at onFulfilled (/Users/tusm/github/mygithub/egg-cms/node_modules/co/index.js:65:19)
at /Users/tusm/github/mygithub/egg-cms/node_modules/co/index.js:54:5
at Promise ()
at Object.co (/Users/tusm/github/mygithub/egg-cms/node_modules/co/index.js:50:10)
// Store the headers in lower case.
for (var field in options.headers) {
if (options.headers.hasOwnProperty(field)) {
this.headers[field.toLowerCase()] = options.headers[field];
}
}
typeof this.ctx.response.headers
object
typeof this.ctx.response.proto
object
typeof this.ctx.response.headers.proto
undefined
tips: egg issues
app/extend/oauth.js
中提供策略遇到问题:
egg-oauth2-server
职责:
app.oauth2Server.use(StrategyClass)
use
里面可以调用 loadToContext
等把 class 注册到 ctxapp.oauth2Server.Strategy
基类
// {app_root}/app.js
module.exports = app => {
const Strategy = require('./lib/oauth2_strategy');
app.oauth2Server.use(Strategy);
}
// {app_root}/lib/oauth2_strategy.js
module.exports = app => {
return class MyStrategy extends app.oauth2Server.Strategy {
constructor(ctx) {
super(ctx);
}
* getAccessToken() {
return yield ctx.service.xxx();
}
}
}
oauth2_strategy.js
可以独立为二级插件的方式egg-oauth2-server-firebase
/ egg-oauth2-server-alibaba
app.js
中 use
下即可// {app_root}/app.js
module.exports = app => {
const Strategy = require('./lib/oauth2_strategy');
app.oauth2Server.use(Strategy);
}
// {app_root}/lib/oauth2_strategy.js
module.exports = app => {
return class MyStrategy extends app.oauth2Server.Strategy {
constructor(ctx) {
super(ctx);
}
* getAccessToken() {
return yield ctx.service.xxx();
}
}
}
See https://github.com/Azard/egg-oauth2-server/blob/master/app.js#L11-L13
It is not possible to have multiple model , it's nice to have a configuration
config/config.default.js
oAuth2Server: {
debug: true,
grants: [ 'password', 'authorization_code', 'refresh_token' ],
accessTokenLifetime: 7200,
refreshTokenLifetime: 1209600
}
get token response
{
"accessToken": "1a4e7b8531f274fce992d33cabe62b4545327e7f",
"accessTokenExpiresAt": "2018-10-15T04:03:13.164Z",
"refreshToken": "b9c95fba7f1e9112e12d0f25ead5162e88c305a3",
"refreshTokenExpiresAt": "2018-09-29T04:03:13.164Z",
...
}
accessTokenExpiresAt 比createdAt时间大了一个月
extend/oauth.js
implementation need check format when plugin init.
您好:
想请教一下
AuthorizeHandler.prototype.getClient = function(request) {
var clientId = request.body.client_id || request.query.client_id;
if (!clientId) {
throw new InvalidRequestError('Missing parameter: client_id
');
}
if (!is.vschar(clientId)) {
throw new InvalidRequestError('Invalid parameter: client_id
');
}
var redirectUri = request.body.redirect_uri || request.query.redirect_uri;
if (redirectUri && !is.uri(redirectUri)) {
throw new InvalidRequestError('Invalid request: redirect_uri
is not a valid URI');
}
return promisify(this.model.getClient, 2).call(this.model, clientId, null)
.then(function(client) {
if (!client) {
throw new InvalidClientError('Invalid client: client credentials are invalid');
}
if (!client.grants) {
throw new InvalidClientError('Invalid client: missing client `grants`');
}
if (!_.includes(client.grants, 'authorization_code')) {
throw new UnauthorizedClientError('Unauthorized client: `grant_type` is invalid');
}
if (!client.redirectUris || 0 === client.redirectUris.length) {
throw new InvalidClientError('Invalid client: missing client `redirectUri`');
}
if (redirectUri && !_.includes(client.redirectUris, redirectUri)) {
throw new InvalidClientError('Invalid client: `redirect_uri` does not match client value');
}
return client;
});
};
在鉴权第一步的时候,首先会调用getClient方法获取我们注册的app信息,这里会验证grants这个属性,我不太理解这个属性到底有什么含义,或者说是他的意义体现在哪里?
因为我现在也在做一个鉴权的服务,其中应用信息是另一个项目进行创建注册的,在创建应用的时候,grants这个属性现在是必须要的,而且值也是固定的几个值,就是不太理解为什么要验证这个属性
when use egg-oauth2-server plugin as global middleware:
// app/middleware/auth.js
module.exports = options => {
return async (ctx, next) => {
try {
const auth = await ctx.app.oAuth2Server.authenticate();
console.log(auth);
await next();
} catch (err) {
ctx.logger.error(err);
}
};
};
// config/config.default.js
config.middleware = [ 'auth' ];
then output: [AsyncFunction]
when use authenticate()
in egg controller:
// app/controller/debug.js
async index() {
const { app, ctx } = this;
const res = await app.oAuth2Server.authenticate();
ctx.body = res;
}
then throw:
{
"code": "ERR_INVALID_ARG_TYPE",
"message": "The \"string\" argument must be one of type string, Buffer, or ArrayBuffer. Received type undefined",
"stack": "TypeError [ERR_INVALID_ARG_TYPE]: The \"string\" argument must be one of type string, Buffer, or ArrayBuffer. Received type undefined\n at Function.byteLength (buffer.js:494:11)\n at respond (D:\\Develop\\projects\\zhifu\\api2\\node_modules\\koa\\lib\\application.js:245:25)\n at handleResponse (D:\\Develop\\projects\\zhifu\\api2\\node_modules\\koa\\lib\\application.js:149:34)\n at processTicksAndRejections (internal/process/task_queues.js:85:5)",
"name": "TypeError",
"status": 500
}
node-oauth2-server support implicit grant mode now, so is this plugin supported? BTW, if I want to use more than one mode, how do I define the router?
this.ctx can't be changed on each request after constructed.
module.exports = (app) => {
class Model {
constructor(ctx) {
this.ctx = ctx;
}
test() {
console.log(this.ctx.request.query);
}
}
return Model;
};
非常赞,感谢回馈。
以下是几点建议:
exports['oauth2-server']
改为 exports.oauth2Server
exports.oauth2Server = {
debug: process.env.NODE_ENV !== 'production',
grants: [ 'password' ],
model: oauth_model(app),
};
exports.oauth2Server = {
enable: true,
package: 'egg-oauth2-server',
};
model
不用用户手动初始化,通过 Loader API 自动加载,可以参考 egg-sequelize 和 egg-view-nunjucks 的实现
app.js 里面的 console.log
可以改为 app.coreLogger
,参见 日志
debug: process.env.NODE_ENV !== 'production'
可以考虑直接读取 app.config.env === 'local'
做转换
agent.js
没用可以去掉
index.js
也是多余的,你是用了 simple 那个 boilerplate ?应该用 plugin 那个,建议用 egg-boilerplate-plugin
重新初始化下,现在看到有不少不需要的代码,如 package.json 的 scripts 等。
我想问下,这个token的存储是存储在数据库里面吗 如果多台服务器要怎么取出这个token相关信息
请问调用authorize()这个函数,目前是把网页直接返回,有没有办法返回URL
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.