從 JWT 到 Token,再到 Auth0
上次在寫那篇〈Firebase Dynamic Links Analytics API 取得短網址分析資料〉時,看見 Google 用了 JWT,身邊的同事最近也有人講用過 JWT。查了一下,是 Json Web Token,啊~原來最近接的幾個 API,要一直用到 token 就是從這來的。
是,說實話,前端這領域太廣了,也許你/妳早就用 JWT 很久了,但 August 確實是最近才知道這玩意兒~
在看 JWT 說明文件時,就看到右上方標示「Crafted by Auth0」,點進 Auth0 的網站,才發現他們家有做會員註冊、登入的第三方功能。
覺得有趣,而且免費方案可以支援到 7000 名會員數,哇塞,手上有 7000 名會員,出去就可以橫著走了吧~
一時心動,就看了他們這項功能,試著接了一下,覺得厲害,猜想之後有機會用到,怕之後要用時忘了,就決定寫成這一篇。
Universal Login
這篇筆記文會實作一個,用 Auth0 的 Universal Login 功能,來進行會員的註冊、登入。
Universal Login,就是註冊、登入框會直接是他們家產出來的,像這樣:
登入完後,再轉到我們指定的網址。
預設社群登入的部份只有 Google,上面截圖的 LINE 登入是 August 另外從後台加上去的,本篇也會寫到。
簡單的說,Universal Login 就是 Auth0 統包登入頁的那段,頁面網域的部份,免費方案是 Auth0 的子網域,如果要客製成自己的網域,就要付費啦~
因為註冊、登入的頁面是 Auth0 的,因此修改密碼也會是用他們家的,也就是說,會員資料會有一份在他們家,當然,我們可以在使用者註冊後的 callback 裡,寫一段傳到我們自己的資料庫上,但,他們家的後台是會有一份的,這點請注意。
這篇實作出來的頁面,在這裡:
https://letswritetw.github.io/letswrite-auth0-login/
請注意,當你/妳註冊成會員後,就真的會是本站 Let’s Write 的會員喔。
目前會員…還沒想到要幹麻,應該就是跟之前 LINE 登入 那篇一樣,等 August 哪天設計完電子報後,有了新文章就會發一份電子報給會員這樣 🤣。
也因為 Auth0 的登入框,本身就可以用 LINE 登入了,因此本站側邊的 LINE 登入也會改用 Auth0。
Auth0 Universal Login 步驟
這邊先整理出需要的步驟。
後台設定部份
- 註冊 Auth0,設定基本資訊
- 取得 Domain、Client ID
- 設定登入、登出後,轉址的白名單
- 設定 Login box的樣式
程式碼部份
- 製作一個簡單的頁面,包含登入前、登入後
- 引用或 import createAuth0Client
- 取得 Auth0 config
- 判斷是否登入,登入就取得使用者資訊跟 access_token
程式碼部份是用原生 JavaScript,原本想用 Vue.js 的,後來想想原生 JavaScript 走到哪都能用,而且文件提供的範例也都是原生,就決定是他了。
註冊 Auth0,設定基本資訊
進到 Auth0 的官網:https://auth0.com/
點選右上角的 Sign Up,就會進到註冊頁:
其實這個註冊頁的右邊那塊,就會很像是他們 Universal Login 的內容,提供了輸入帳密的方式,或是直接用社群帳號註冊成會員。
填完帳密,或是選擇了社群的方式,下一步就是要設定自己的網域跟地區:
如果是有付費的方案,就可以在註冊完成後,選擇自己的網域。
註冊的最後一步就是選擇你是公司用或個人用:
註冊完成,會進到會員的首頁,建議是先到 Settings 頁面去設定基本的資訊:
Settings 就是在編輯帳號的基本資訊:
這邊比較疑惑的是最底部的 Language 這邊,原本以為改成中文後,登入的頁面就會顯示成中文了,但 August 這邊改完,實際上頁面沒有更著改。
基本資訊設定完,下一步就是取得必要的 Domain、Client ID。
取得 Domain、Client ID
用 Auth0 的 Universal Login,第一步初始化 Auth 就要抓取 Domain、Client ID,這兩個值要存成一個 JSON 檔。
要取得這兩個值,首先必須要先建立一組應用程式,首頁上點擊左側或是中間區塊的 Applications:
進到 Applications 的頁面,會看見 Auth0 會預設先開好一個 App:
點進去後,就會看到 Domain、Client ID這兩個值,同時,一些空白的地方我們也可以填一填。
這些空白的地方,其中就有我們設定部份的第三步:
設定登入、登出後,轉址的白名單
如果我們進行登入後要轉去的網址,以及登出後要轉去的網址,沒有寫在 App 這邊白名單的話,Auth0 就會無法讓使用者註冊、登入。
這邊比較困惑的,是「Application Type」這項,看完文件的說明後,其實也沒完全理解,後來選了 Regular web app,說明文件的部份可看這邊:Applications in Auth0
從 App 的設定頁面中,我們可以找到 Domain、Client ID 這兩項,把它存成一個名為「auth_config.json」的檔案,檔案內容會是這樣:
{ "domain": "這邊是domain的值", "clientId": "這邊是client id的值" }
這個 JSON 檔案要放在根目錄。另外,這個 JSON 檔會是公開的,因此如果想加其他東西,不要加私密的資訊。
設定 Login box 的樣式
Auth0 的 Universal Login 是走他們的登入頁面,而他們的服務也提供了一些可以客製的項目。
一樣在 Auth0 的登入後首頁,點選中間第一大塊的 Customize,或是左側選單的 Universal Login:
Universal Login 的頁面,就是在編輯登入頁面。
第一個「Settings」頁籤,可以選擇要的主要樣式、換 Logo、換色系。
第二個「Login」頁籤,就可以更動程式碼了。這邊 August 手動更改了語言為中文,如下:
// 原本 var language; // 改成 var language = 'zh-TW';
這邊的更動,都可以按 Preview 看結果。
第三個「Password Reset」頁籤,就是更動會員要修改密碼時的頁面,如果要中文化,就是改「dict」底下物件的值。
第四個「Multi-factor Authentication」頁籤就是做二階段驗證的,本篇還沒用到二階段驗證,這先不用。
以上四步都設定完後,接下來就是進入到程式碼的部份了。
製作一個簡單的頁面
預計是製作一個,登入前就放一個登入按鈕,登入後就秀出一張卡片寫著登入者的資訊。
因為版型簡單,而且登入後的資訊用 JS 寫進頁面裡,所以就都做在一頁上。
比較要注意的是,登入、登出這兩個按鈕,加上了各自的id,主要是拿來觸發 click 事件用。HTML body 的部份如下:
HTML 部份完成,接下來新增一支 JS 的檔案,開始寫 JS。
引用或 import createAuth0Client
JS 一開始要先引用 Auth0 的 JS,可以用 ES6 import 的方式,也可以直接在頁面上引用 CDN。
引用 CDN
HTML 上直接新增一行:
<script src="https://cdn.auth0.com/js/auth0-spa-js/1.2/auth0-spa-js.production.js"></script>
import
用 ES6 import 的話,要先用 npm 安裝:
npm install --save @auth0/auth0-spa-js
接著就可以在 JS 檔中引用了:
import createAuth0Client from '@auth0/auth0-spa-js';
async polyfill
因為登入部份的 JS,需要用到 ES7 的 Async,August 是用 CodeKit 這套編譯器,還需要引用 polyfill 才能編譯。
Async 在 IE 也是不支援的,一樣需要引用 polyfill。
Async polyfill 也可以用 import 或是 CDN 的方式。
CDN
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js"></script>
import
npm install --save @babel/polyfill
import "@babel/polyfill";
取得 Auth0 config
JS 一開始要先寫取得 Auth0 config 的 function,fetch 我們之前建的 auth_config.json,並將 auth0 初始化。
判斷是否登入,登入就取得資訊
因為使用者是在 Auth0 的頁面上做註冊、登入的動作,是用 Auth0 的 function 來判斷是否登入這段。
使用者登入回來後,網址會帶上 code
、state
這兩個參數,文件中的範例碼有做清掉參數的動作:
if(query.includes("code=") && query.includes("state=")) { // 執行登入後的動作 await auth0.handleRedirectCallback(); // 清掉網址參數 window.history.replaceState({}, document.title, pathname); }
看說明文件,auth0.handleRedirectCallback()
是可以跟後端要回 token 回來。實際在寫的時候,原本以為不用這行,但一刪除,就會發現使用者確實登入了,但JS卻判定使用者尚未登入,因此還是寫了上去。
要判斷使用者是否登入,用這個 function:
await auth0.isAuthenticated();
登入會回傳 true
,未登入回傳 false
。
使用者登入後,可以取得 access_token
、userProfile
:
// 取得 access_token let accessToken = await auth0.getTokenSilently(); // 取得登入者資訊 const user = await auth0.getUser();
最後是要寫按下登入、登出按鈕的 function,主要就是執行轉址。
這一段的程式碼整理如下:
完整的程式碼有放在 GitHub 上,本篇的文未會附上網址。
加入 LINE 登入
Auth0 在社群登入的部份,除了預設有的 Google,還可以加上其他社群登入。
在 Auth0 的首頁,按下左側選單的「Connections」,再點它第二層的「Social」:
進到 Social 頁面後,就會看到可以連接的社群登入列表,很洋洋灑灑的的大串:
因為 August 已經接通了 LINE,因此 LINE 是打開的狀態。
大部份的社群登入,都要輸入 Client id,所以這邊 Auth0 預設只開了 Google。
LINE 登入一樣要取得 Channel ID、Channel Secret,取得的方式請看這篇:
取得 ID 跟 Secret 後,點擊列表中的 LINE,就會出現一個燈箱:
按下 SAVE 後,登入頁就會加上 LINE 登入的按鈕,但還要再做一個步驟才能執行。
這一步就是 LINE Developers 要加上 callback URL,URL 的白名單要加入 Auth0。
進到 LINE Developers 的後台,我們建立的 App,在 callback URL 那邊要新增這行:
https://你的網域.auth0.com/login/callback
「你的網域.auth0.com」這邊就是填上我們在 Auth0 取得的 Domain。
因為 August 的頁面是用 GitHub Pages,因此把頁面的網址也加了進去。
以上完成後,就可以執行 LINE 註冊、登入。
Auth0 後台看會員狀況
當有會員註冊、登入,Auth0 的後台可以看到。
點選首頁左側選單的 Users & Roles,再點第二層的 Users:
會看見會員的列表,包含是用什麼方式註冊、登入次數、最後登入時間。
如果再點擊每一位會員進去,可以再看到註冊時間、用什麼瀏覽器註冊、可以擁有什麼權限…等,這邊屬於比較多的個人資訊,就不截圖了。
Let’s Write 加入會員頁、原始檔
歡迎大家加入 Let’s Write 會員,目前只想到以後可以收到最新文章的電子報…就這樣 XD,所以是免費加入的呀~
會員從這加:
https://letswritetw.github.io/letswrite-auth0-login/
本篇的原始檔也放在 GitHub 上了:
https://github.com/letswritetw/letswrite-auth0-login
我想問一下,請問回傳的url是什麼?