oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)

在了解了OAuth2.0的扩展协议PKCE(细节可以在由Raycast to flomo了解到OAuth 2.0之PKCE中看到),我也想试试,尝试接入一把。

使用npm包oidc-provider,具体可以源码及文档https://github.com/panva/node-oidc-provider

配置

根据文档里面的example的express简单修改下。

修改

clients: [ { client_id: 'client_id', client_secret: 'client_secret', redirect_uris: ['http://127.0.0.1:3000/callback'], grant_types: ['refresh_token', 'authorization_code'], code_verifier: '2Ealc1zZfDjmm-RNct0U7POlQmj.-z9fFb2cuk4eZw_LyVZEMp2B.Uwl5t3RvX6RCovo7qkZdP6-HEh9-lQanPKrO_20j.7kyIzWc-7_Z3GB2HXmwCXkSflPh7AMJ59m', code_challenge: 'LVogXRp-NbtBYMm1ed88xNwvmuoanfBcbWoeKYzeOEU', } ],

配置上code_verifier 和对应的code_challenge ,

我们可以直接在线生成 => pkce-generator

直接运行node example/express.js就可以开始调试了。

在http://localhost:3000/.well-known/openid-configuration 页面我们可以看到生效的配置和被oidc-provider接管的路由地址。

获取Authorization Code

浏览器访问 http://localhost:3000/auth?client_id=client_id&redirect_uri=http://localhost:3000/callback&response_type=code&code_challenge=LVogXRp-NbtBYMm1ed88xNwvmuoanfBcbWoeKYzeOEU&code_challenge_method=S256&scope=openid profile &nonce=123 &state=321

其中的code_challenge_method=S256别忘了。

如果未发现报错的话,会出现这样的界面

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(1)

目前是没有校验登录名和密码的,随便输入即可。 点击“Sign-in”后

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(2)

点击“Continue”后

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(3)

我们可以看到已经跳转到我们之前填的redirect_uris地址,并且页面上也带上了code,这个就是authorization code。

到这里已经算完成了第一步了。

这里界面上显示有错误,是因为这个/callback路由地址我们并没有进行配置,并且oidc-provider包也没有接管此路由。

获取token

我们需要在/callback拿到的authorization code去获取最终的access_token,我们可以暂时先用postman来实现,后面会补上。

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(4)

401错误?这是为什么?

我们可以自己在项目打印下出错的信息或者直接调试定位。 我们可以在example/express.js加上console

function handleClientAutherrors({ headers: { authorization }, oidc: { body, client } }, err) { console.log('handleClientAuthErrors -> ',err, authorization, body, client); } provider.on('grant.error', handleClientAuthErrors); provider.on('introspection.error', handleClientAuthErrors); provider.on('revocation.error', handleClientAuthErrors);

因为provider会在关键节点emit消息出来,所以我们直接on一下就好

这下我们就可以看到报错的一些具体信息了

我们看到打印消息如下

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(5)

error_detail: the registered client token_endpoint_auth_method does not match the provided auth mechanism

不支持client_secret_basic ?但是我们在配置里面

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(6)

看到是支持client_secret_basic 这种方式的啊。 这个其实因为我们没有在请求头里面加上Authorization信息。

加上之后就成功了。

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(7)

code换取的token

前面我们是用postman调用的/token用authorization code换取的access_token,现在我们加上自己的/callback路由实现,以方便在/callback直接完成换取access_token过程。

// /example/routes/express.js const querystring = require('querystring'); const base64url = require('../../lib/helpers/base64url'); app.get('/callback', (req, res) => { const data = { code: req.query.code, code_verifier: '2Ealc1zZfDjmm-RNct0U7POlQmj.-z9fFb2cuk4eZw_LyVZEMp2B.Uwl5t3RvX6RCovo7qkZdP6-HEh9-lQanPKrO_20j.7kyIzWc-7_Z3GB2HXmwCXkSflPh7AMJ59m', grant_type: 'authorization_code', client_id: 'client_id', redirect_uri: 'http://localhost:3000/callback', }; axios.post('http://localhost:3000/token', querystring.stringify(data), { headers: { authorization: `Basic ${base64url.encode('client_id:client_secret')}`, 'content-type': 'application/x-www-form-urlencoded', }, }).then((result) => { console.log(result.data); res.send(result.data); }).catch((err) => { console.log('err -> ', err); res.send('error'); });

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(8)

成功完成用authorization code换取的access_token过程,有了access_token,后续就都有权限了。

补充

目前oidc-provider官方的example是允许随便输入登录名和密码,因为为了让大家快速上手,在配置里面的findAccount写的是永远都是查找到账号

oauth2.0自定义token算法(网站接入OAuth2.0扩展协议PKCE)(9)

具体代码在example/support/accout.js

这里即使找不到id也会重新生成一个Account,所以始终能成功。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页