在onelogin中使用OpenId Connect Authentication Flow


簡介

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. Auth Flow/

我們下載下來該程序,將 .env.sample 重命名為 .env

修改里面的變量,主要是OIDC_CLIENT_ID,OIDC_CLIENT_SECRET,SUBDOMAIN和OIDC_REDIRECT_URI這4個值,都是我們在onelogin做配置的時候設置的:

SUBDOMAIN=flydean-dev
OIDC_CLIENT_ID=a3446600-f263-0138-3235-122333243433
OIDC_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 OneLogin
passport.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的博客

歡迎關注我的公眾號:「程序那些事」最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM