sanic的openid提供程序框架
sanic-openid-connect-provider的Python项目详细描述
这是一个正在进行的工作,阿尔法阶段我会说。如果有人觉得这个有用/想用,就不要提我会 我很乐意把它修好,这样对我以外的人真的很有帮助。
上次我检查时,它通过了大约82/93的openid连接 勾选webfinger,dynamic info discovery时出现的提供程序认证测试, dynamic client registration并选择code响应类型。
它对于授权代码流非常有用。仍然需要大量的重新设计和清理,但我 尝试将其插入到各种后端,如dynamodb/redis,用于令牌/客户端存储。
文档和示例将很快提供。
前提条件
该包要求使用并配置sanic_jinja2和sanic_session。
测试
如上所述,它通过了我运行过的大多数openid测试。以下是我尚未通过的考试
签名+加密
还没有弄清楚为什么userinfo enc/sig还不能工作。
- OP-IDToken-SigEnc
- OP-UserInfo-SigEnc
- OP-request_uri-SigEnc
索赔
还没到这一步
- OP-claims-acr-essential
- OP-claims-acr-voluntary
- OP-claims-acr=1
弹出窗口
不显示在弹出框中
- OP-display-popup
其他请求参数
还没处理好。
- OP-Req-acr_values
键旋转
需要一些方法来旋转键
- OP-Rotation-OP-Enc
- OP-Rotation-OP-Sig
- OP-Rotation-RP-Enc
- OP-Rotation-RP-Sig
密钥创建
RSA密钥
openssl genrsa -nodes -out rsa.pem 4096
ecdsa密钥
openssl ecparam -name prime256v1 -genkey -noout -out ec.pem openssl ec -in ec.pem -pubout -out ec.pub
openid connect节点示例
应用js
/* * * Note: This example is a "full" example that registers a new client with the OIDC server each time. This returns a client ID and secret. * In reality, you should only register once per service and then save the client information for future use. * I would advise using this script to register your client and test it - It will console.log the ID and secret which you can then hardcode: * https://github.com/panva/node-openid-client#manually-recommended * * In production, I import a modified version of this script with promise support. Make sure it's finished discovery before defining your * error handlers! *///******* Config constconfig={/* jshint ignore:start *///Server we're going to auth with authServer:"https://authserver",//Access token provided by admin for initial registration initialAccessToken:"dcb89d4c-fec4-11e8-8eb2-f2801f1b9fd1",//Listen port port:3000,//All the settings required to register our client registration:{//IDP prefers ES256 encryption id_token_signed_response_alg:'ES256',//Array of all potential redirect URI's redirect_uris:["http://127.0.0.1:3000/callback","http://127.0.0.1/callback"],//String space-delimited list of all potentially required scopes scope:"openid email profile",grant_types:['authorization_code'],application_type:'web',//Name of client - For reference only client_name:'Some client',subject_type:'public',response_types:["code"]},auth:{//uri the IDP redirects to after authentication - Must be in the array above redirect_uri:"http://127.0.0.1:3000/callback",//Scopes we want for authentication scope:"openid email profile",id_token_signed_response_alg:'ES256'}/* jshint ignore:end */}//******* End Config const{Issuer}=require('openid-client');const{Strategy}=require('openid-client');constsession=require('express-session');constexpress=require('express');constapp=express();constpassport=require('passport');// Set up Express sessions in memory - Please don't do this in production, use something to store your sessions // so we can load balance. app.use(session({secret:'asupersecretpassword',resave:true,saveUninitialized:true}));//Make sure to initialise before we start discovery app.use(passport.initialize());app.use(passport.session());//Discover settings from OID server Issuer.discover(config.authServer).then(customIssuer=>{constopts={initialAccessToken:config.initialAccessToken};constmetadata=config.registration;// You only need to do client registration once (ever) - You should do it during development and then hardcode the client id and secret // Below is an example of a hardcoded client, rather than a client that registers each time // See more in the docs: https://github.com/panva/node-openid-client#manually-recommended // const client = new customIssuer.Client({ // client_id: '83fc3323d3c045a4', // client_secret: '7f9b5e1721a244c989d011839595b766', // id_token_signed_response_alg: 'ES256' // }); customIssuer.Client.register(metadata,opts).then(client=>{console.log("!!!!! Save this information for re-use later! !!!!!")console.log("Client ID: "+client.client_id)console.log("Client Secret: "+client.client_secret)console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")console.log("Metadata: "+JSON.stringify(client.metadata,null,2))constparams=config.auth;// Setting up our strategy + validation function passport.use('oidc',newStrategy({client,params,passReqToCallback:null,sessionKey:null,usePKCE:false},(tokenset,userinfo,done)=>{returndone(null,userinfo)}));passport.serializeUser((user,done)=>{// This is where you'd get any extra locally-stored data from the database or something for accessing in req.user done(null,user);});passport.deserializeUser((user,done)=>{done(null,user);});// GET /login will start authentication app.get('/login',passport.authenticate('oidc'));// GET /callback redirected from IDP with code app.get('/callback',passport.authenticate('oidc',{successRedirect:'/',failureRedirect:'/login'}));// Force every other request to check if user is authed, if not then redirect to /login and start auth app.use((req,res,next)=>{if(!req.user){res.redirect('/login');}else{next();}})// Example authenticated endpoint app.get('/',(req,res)=>{console.log(`User ${req.user.name} has logged in.`);res.send(req.user);})app.listen(config.port,()=>console.log(`Example app listening on port ${config.port}!`))});})
package.json
{"name":"openidtest","version":"1.0.0","description":"","main":"app.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"author":"","license":"ISC","dependencies":{"express":"^4.16.4","express-session":"^1.15.6","passport":"^0.4.0","passport-openid-connect":"^0.1.0"}}