接下來要來做比較複雜的任務了,我們將會把 Hydra 和 Laravel 兩個服務整合。
這裡會有兩個要注意的問題:一開始的 Hydra 只是快速體驗用的,我們要來認真從頭把這個服務架起來,這個問題只是單純建置上的問題,今天能夠解決。
另一個問題是,Laravel 的功能會把「登入過程」和「登入前後」中間加入 Hydra 的 OpenID Connect 流程。如果要使用相同的 Laravel 的程式碼時,必須要注意處理 Session 和 Cookie 的過程,因為有可能會在登入前寫入 Session 或 Cookie 然後在登入後使用,但登入的過程不應該使用到這些內容。原因在於,OpenID Connect 是應用在跨網域的身分驗證流程,在這個場景下,登入過程是無法取得登入前後的 Session 或 Cookie。
接下來的應用程式的系統會很複雜,因此這裡要好好思考接下來的選擇。有兩種方法可以達成這個目的,一個是在本機起服務,透過不同的 port 來區分不同的服務;另一個是使用 Docker,但一樣會有 port 的問題。
接下來會使用本機起服務的方法來完成,可以了解 Hydra 服務是如何啟動的,接著在本機起 Hydra 服務與 PHP 服務來完成串接的任務,而 Database 一樣會使用 Docker 啟動。
首先新增 database/schema/hydra.sql
的程式,加上 Hydra 的 Database:
-- hydra.sql
CREATE DATABASE IF NOT EXISTS `hydra` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
接著把 Container 砍掉重啟,應該就會有對應的資料庫了:
# 移除 container 以及 volume 並重新啟動
❯ docker-compose down -v
❯ docker-compose up -d
# 記得要跑 Laravel migration
❯ php artisan migrate
註記:這裡開始會改使用 MariaDB 執行,其實差異不大。
# 使用 Homebrew 官方的 tap
# https://formulae.brew.sh/formula/ory-hydra
# https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/ory-hydra.rb
❯ brew install ory-hydra
❯ hydra version
Version: v1.11.10
Git Hash: 1a6c22070fc9550796c14b271e816be1dd1b8d78
Build Time: 2022-08-25T12:53:06Z
# 使用 Hydra 官方的 tap
# https://github.com/ory/homebrew-tap
❯ brew install ory/tap/hydra
❯ hydra version
Version: v1.11.10
Git Hash: 1a6c22070fc9550796c14b271e816be1dd1b8d78
Build Time: 2022-08-25T12:53:06Z
啟動服務的方法,在昨天的 quickstart.yml
裡面有寫,如下:
❯ hydra serve all --dangerous-force-http
FATA[2022-09-22T15:40:11+08:00] dsn must be set audience=application service_name=Ory Hydra service_version=v1.11.10
hydra serve all
指的就是同時啟動 Public API 以及 Admin API, --dangerous-force-http
代表強制使用 HTTP 而非 HTTPS。只是它現在執行起來有發生問題,問題在於沒有設定 DSN(Data Source Name,指 DB 的位址)。這個在 quickstart-mysql.yml 裡面也有寫,不過這是用在 Docker 的環境裡,在本機就需要調整一下:
# Docker
DSN=mysql://root:secret@tcp(mysqld:3306)/mysql?max_conns=20&max_idle_conns=4
# Local
DSN=ysql://root:secret@tcp(localhost:3306)/hydra?max_conns=20&max_idle_conns=4
Docker 是用環境變數的方法做 DSN 設定,只要像下面一樣執行指令即可達成一樣的目的:
❯ DSN="mysql://root:secret@tcp(localhost:3306)/hydra?max_conns=20&max_idle_conns=4" hydra serve all
INFO[2022-09-23T23:03:31+08:00] No tracer configured - skipping tracing setup audience=application service_name=Ory Hydra service_version=v1.11.10
[mysql] 2022/09/23 23:03:31 packets.go:37: unexpected EOF
[mysql] 2022/09/23 23:03:31 packets.go:37: unexpected EOF
[mysql] 2022/09/23 23:03:31 packets.go:37: unexpected EOF
...
FATA[2022-09-23T23:05:37+08:00] Could not ensure that signing keys for "hydra.openid.id-token" exists. If you are running against a persistent SQL database this is most likely because your "secrets.system" ("SECRETS_SYSTEM" environment variable) is not set or changed. When running with an SQL database backend you need to make sure that the secret is set and stays the same, unless when doing key rotation. This may also happen when you forget to run "hydra migrate sql"..
從訊息可以了解程式讀取表失敗了,因為目前資料庫並沒有跑 migration,因此來執行一下,指令可以參考 quickstart.yml
:
❯ DSN="mysql://root:secret@tcp(localhost:3306)/hydra?max_conns=20&max_idle_conns=4" hydra migrate sql -e --yes
...
Successfully applied migrations!
❯ DSN="mysql://root:secret@tcp(localhost:3306)/hydra?max_conns=20&max_idle_conns=4" hydra serve all --dangerous-force-http
...
INFO[2022-09-23T23:18:10+08:00] Setting up http server on :4444 audience=application service_name=Ory Hydra service_version=v1.11.10
WARN[2022-09-23T23:18:10+08:00] HTTPS disabled. Never do this in production. audience=application service_name=Ory Hydra service_version=v1.11.10
INFO[2022-09-23T23:18:10+08:00] Setting up http server on :4445 audience=application service_name=Ory Hydra service_version=v1.11.10
看到 4444 與 4445 port 已被打開,就代表完成了,可以呼叫下面這個 API 做測試:
❯ curl http://127.0.0.1:4444/health/ready
{"status":"ok"}
❯ curl http://127.0.0.1:4445/health/ready
{"status":"ok"}
到這邊為止,Hydra 就算啟動完成了。
設定可以參考這裡,以下是今天會用到的內容:
log:
level: debug
dsn: "mysql://root:secret@tcp(localhost:3306)/hydra?max_conns=20&max_idle_conns=4"
secrets:
system:
- this-is-the-primary-secret
這裡會看到有個設定是 secrets.system
。這個用途是類似系統要啟動的主要密碼,如果沒給的話會隨機產生,因此在重新啟動的時候會產生另一把 secret 造成啟動失敗。透過設定檔保存這個密碼是其中一個方法。
現在如果重新啟動的話,應該會失敗,因此需要把 Docker Container 砍掉再重啟,然後 Migration 建立後再啟動服務:
# 重新啟動 DB
❯ docker-compose down -v
❯ docker-compose up -d
# 重新啟動 Hydra
❯ hydra -c hydra.yml migrate sql -e --yes
❯ hydra serve all -c hydra.yml --dangerous-force-http
今天先把服務建置好即可,明天就可以開始來串接了。