4

网站接入OAuth 2.0扩展协议PKCE,获取access_token实战

 2 years ago
source link: https://www.daozhao.com/10501.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

网站接入OAuth 2.0扩展协议PKCE,获取access_token实战

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

网站接入OAuth 2.0扩展协议PKCE,获取access_token实战

在了解了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别忘了。

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

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

点击“Continue”后

file

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

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

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

获取token

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

file

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一下就好

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

我们看到打印消息如下 file

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

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

加上之后就成功了。

file

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');
    });

file

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

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

file

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK