写点什么

在 onelogin 中使用 OpenId Connect Authentication Flow

发布于: 2021 年 01 月 05 日

简介

onelogin 是一个优秀的 SSO(Single Sign-On)服务提供商,我们可以借助 onelogin 的服务,轻松构建 SSO 程序。


之前我们也讲过了,构建 SSO 的通用协议一般有两种,OpenID connect 和 SAML。今天我们将会通过一个具体的例子来讲解一下怎么在 onelogin 中使用 OpenID connect 中的 Authentication Flow 来进行 SSO 认证。


OpenId Connect 和 Authentication Flow 简介

OpenID Connect 是构建在 OAuth 2.0 协议之上的。它允许客户端基于授权服务器或者身份提供商(IdP)来进行用户的身份认证,并获取到用户的基本信息。


OpenID Connect 提供了 RESTful HTTP API,并使用 Json 作为数据的传递格式。


我们可以很容易的使用 onelogin 作为 Identity Provider (IdP)来进行 SSO 认证。


今天我们要讲的是如何使用 onelogin 来实现 Authentication Flow。我们知道 OpenId Connect 有很多种模式。


今天介绍的是 Authorization Code 模式。



Authorization Code 流程的步骤如下:


客户端准备身份认证请求,请求里包含所需要的参数


客户端发送请求到授权服务器


授权服务器对最红用户进行身份认证


授权服务得最终用户的统一/授权


授权服务器把最终用户发送回客户端,同时带着授权码


客户端使用授权码向 Token 端点请求一个响应


客户端接收到响应,响应的 Body 里面包含在和 ID Token 和 Access Token


客户端验证 ID Token,并获得用户的一些身份信息


onelogin 的配置工作

如果需要在我们的应用程序中使用 onelogin,需要做一些配置工作。我们来具体看一下。


首先我们需要在 onelogin 中注册一个账号。


注册 onelogin 是免费的,可以配置 3 个 app 和 25 个用户。做测试使用是足够了。


注册的流程就不多讲了。注册完毕之后,我们就可以在 onelogin 中创建 app 了。


在 applications tab,我们要使用 openid connect,那么就搜索 oidc:



可以看到 onelogin 可以支持多种 OIDC 的连接协议。既然是 onelogin 的界面,当然选 onelogin 的连接了。



输入应用程序的名字,点击 save。


在 configuration 一栏中,redirect URL 输入: http://localhost:3000/oauth/callback


这个是认证完之后,跳转回我们自己的 app 的 URL。



然后转到 SSO 栏,拷贝 client ID 和 client Security,修改认证方式为 POST



如果你还想创建新的 user 或者给 user 设置权限,可以自行探索 onelogin 的高级功能。


使用应用程序连接 onelogin

这里我们选择 onelogin 提供的官方 server 的例子 : https://github.com/onelogin/onelogin-oidc-node/blob/master/1.%20Auth%20Flow/


我们下载下来该程序,将 .env.sample 重命名为 .env


修改里面的变量,主要是 OIDC_CLIENT_ID,OIDC_CLIENT_SECRET,SUBDOMAIN 和 OIDC_REDIRECT_URI 这 4 个值,都是我们在 onelogin 做配置的时候设置的:


SUBDOMAIN=flydean-devOIDC_CLIENT_ID=a3446600-f263-0138-3235-122333243433OIDC_CLIENT_SECRET=**********OIDC_REDIRECT_URI=http://localhost:3000/oauth/callback
复制代码

然后运行 npm intall; npm start 启动 nodejs 服务即可。


官方的例子是使用的 nodejs+express 框架和 Passport-OpenIdConnect 模块来和 onelogin 进行交互的。


我们看下交互的流程。


  1. 用浏览器打开 http://localhost:3000,进入 app 的主页面:



  1. 点 login 将会跳转到 onelogin 的授权登录页面:



我们看下网络请求:



可以看到,前面几个状态码都是 302,重定向。


从 localhost:3000 的 login 页面重定向到:


https://flydean-dev.onelogin.com/oidc/2/auth?response_type=code&client_id=a3446600-f263-0138-3235-064d76eee9d3178911&redirect_uri=http://localhost:3000/oauth/callback&scope=openid profile&state=ohC1Fi0n0YTDELBtNmePDGvb
复制代码

大家可以看到,这个重定向添加了 oidc 协议中需要添加的参数,比如 respnse_type=code 代表的是使用 Authorization Code 模式。而 client_id 就是我们配置的 client id。 redirect_uri 也是配置的返回链接。


scope 表示认证范围,state 是一个唯一标记,用来防刷。


然后又重定向到:


https://flydean-dev.onelogin.com/trust/openid-connect/v2?client_id=a3446600-f263-0138-3235-064d76eee9d3178911&grant=cbec20f1-f1d8-4733-9a6f-e98471edfc13
复制代码

这一步是 onelogin 校验了上一步传来的参数,然后进行的再次跳转。


然后又重定向到:


https://flydean-dev.onelogin.com/login
复制代码

这是自定义域名的登录页面。


https://flydean-dev.onelogin.com/login2/?return=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmkiOiJodHRwczovL2ZseWRlYW4tZGV2Lm9uZWxvZ2luLmNvbS90cnVzdC9vcGVuaWQtY29ubmVjdC92Mj9jbGllbnRfaWQ9YTM0NDY2MDAtZjI2My0wMTM4LTMyMzUtMDY0ZDc2ZWVlOWQzMTc4OTExXHUwMDI2Z3JhbnQ9Y2JlYzIwZjEtZjFkOC00NzMzLTlhNmYtZTk4NDcxZWRmYzEzIiwibm90aWZpY2F0aW9uIjp7Im1lc3NhZ2UiOiJDb25uZWN0aW5nIHRvICoqT3BlbklkIENvbm5lY3QgKE9JREMpKioiLCJpY29uIjoiY29ubmVjdGlvbiIsInR5cGUiOiJpbmZvIn0sImlzcyI6Ik1PTk9SQUlMIiwiYXVkIjoiQUNDRVNTIiwiZXhwIjoxNjAyOTIwNjM0LCJwYXJhbXMiOnt9LCJtZXRob2QiOiJnZXQifQ.hoUjh18mehtBSCINkoGOSDwJFHDBBl_nn47RMSizPfw
复制代码

然后 onelogin 对参数进行加密处理,返回了大家能够看到的页面。


  1. 输入我们的用户名密码



点击继续。


  1. 认证成功后,调整到用户信息页面



我们可以看到内部也是经历了一系列的转发调用工作:



我们需要关心的是下面的 callback:


http://localhost:3000/oauth/callback?code=2PVdwgQkNip883hql_ub9w3Byug&state=ohC1Fi0n0YTDELBtNmePDGvb
复制代码

可以看到在 callback 中,我们获取到了 code,后面可以使用这个 code 和 onelogin 进行交互。


  1. 点击 profile,我们将会尝试从 onelogin 获取到用户的信息



我们关注下请求的链接:


http://localhost:3000/users/profile
复制代码

这一步实际上会在后台通过 code 去请求 onelogin 的用户信息。


程序中的关键步骤

这个官方的认证程序是用 nodejs 和 express 构建的,认证框架主要用的是 passport 和 passport-openidconnect。


我们看下关键代码。


passport 配置使用 onelogin:


// Configure the OpenId Connect Strategy// with credentials obtained from OneLoginpassport.use(new OneLoginStrategy({  issuer: baseUri,  clientID: process.env.OIDC_CLIENT_ID,  clientSecret: process.env.OIDC_CLIENT_SECRET,  authorizationURL: `{baseUri}/auth`,  userInfoURL: `{baseUri}/me`,  tokenURL: `${baseUri}/token`,  callbackURL: process.env.OIDC_REDIRECT_URI,  passReqToCallback: true},function(req, issuer, userId, profile, accessToken, refreshToken, params, cb) {
console.log('issuer:', issuer); console.log('userId:', userId); console.log('accessToken:', accessToken); console.log('refreshToken:', refreshToken); console.log('params:', params);
req.session.accessToken = accessToken;
return cb(null, profile);}));
复制代码

从上面代码中可以看到,拿到 accessToken 之后,是存放在 session 中的。


使用 session 存储认证信息:


app.use(session({  secret: 'secret squirrel',  resave: false,  saveUninitialized: true}))
复制代码

login 的逻辑操作:


app.get('/login', passport.authenticate('openidconnect', {  successReturnToOrRedirect: "/",  scope: 'profile'}));
复制代码

callback 的逻辑操作:


app.get('/oauth/callback', passport.authenticate('openidconnect', {  callback: true,  successReturnToOrRedirect: '/users',  failureRedirect: '/'}))
复制代码

获取用户 profile 操作:


router.get('/profile', function(req, res, next) {  request.get(    `https://${ process.env.SUBDOMAIN }.onelogin.com/oidc/2/me`,       {    'auth': {      'bearer': req.session.accessToken    }  },function(err, respose, body){
console.log('User Info') console.log(body);
res.render('profile', { title: 'Profile', user: JSON.parse(body) });
});});
复制代码

使用 session 中的 accessToken 来获取用户的信息。


总结

一个简单的 SSO 程序就搭建完成了。通过 passport 模块来获取 accessToken 信息,并存储在 session 中。


passport 模块支持很多种 Strategy,包括 openID,Local,BrowserID,Facebook,Google,Twitter 等。我们可以使用它来适配不同的认证服务。


本文作者:flydean 程序那些事

本文链接:http://www.flydean.com/openid-connnect-with-onelogin/

本文来源:flydean 的博客

欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!


发布于: 2021 年 01 月 05 日阅读数: 18
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
在onelogin中使用OpenId Connect Authentication Flow