每周開源項目分享-年輕人的第一個OAuth2.0 Server:hydra


年輕人的第一個OAuth2.0 Server:hydra

hydra 是什么呢?

  • OpenID Connect certified OAuth2 Server - cloud native, security-first, open source API security for your infrastructure. Written in Go. SDKs for any language.

講人話的話就是一個OAuth2.0的服務端框架咯,開箱即用.

OAuth是撒? QQ互聯知道么?微信授權登錄知道么?

擴展閱讀:理解OAuth 2.0:阮一峰

開源地址:https://github.com/ory/hydra

文檔地址:https://www.ory.sh/docs/guides/master/hydra/

本文結束...





































開始手把手教你跑hydra server

  • 全程Docker部署,請自行准備相關環境.

准備PostgreSQL 數據庫/MySQL數據庫

hydra支持PostgreSQL/MySQL,任君選擇.

官網指導教程使用的是PostgreSQL,下面我也抄過來了,同時提供MySQL的相關操作.

啟動數據庫啦!!!

哦,啟動之前先創建一個docker 網絡.

docker network create hydraguide

啟動 PostgreSQL,如下

docker run \
  --network hydraguide \
  --name ory-hydra-example--postgres \
  -e POSTGRES_USER=hydra \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=hydra \
  -d postgres:9.6

或者啟動MySQL

docker run -p 3306:3306 \
 --network hydraguide \
 --name hydra-mysql --restart=always \
 -v ~/docker-data/hydra-mysql/data/:/var/lib/mysql \
 -e MYSQL_ROOT_PASSWORD=123 -d mysql:5.7

啟動好了自行驗證一下數據庫是不是正確啟動和能連接上去了.

准備hydra相關環境變量

# The system secret can only be set against a fresh database. Key rotation is currently not supported. This
# secret is used to encrypt the database and needs to be set to the same value every time the process (re-)starts.
# You can use /dev/urandom to generate a secret. But make sure that the secret must be the same anytime you define it.
# You could, for example, store the value somewhere.
$ export SYSTEM_SECRET=$(export LC_CTYPE=C; cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
#
# Alternatively you can obviously just set a secret:
# $ export SYSTEM_SECRET=this_needs_to_be_the_same_always_and_also_very_$3cuR3-._

# The database url points us at the postgres instance. This could also be an ephermal in-memory database (`export DATABASE_URL=memory`)
# or a MySQL URI.
$ export DATABASE_URL=postgres://hydra:secret@ory-hydra-example--postgres:5432/hydra?sslmode=disable

# MySQL的配置,host.docker.internal為宿主機IP,mysql容器的內部IP或者hydra-mysql也可以用

$ export DATABASE_URL=mysql://root:123@tcp(host.docker.internal/mysql容器的內部IP/hydra-mysql:3306)/hydra?parseTime=true

  • SYSTEM_SECRET 是hydra啟動時加密數據庫使用的,Mac/Linux直接使用上面的方法設置即可,windows環境下設置一下環境變量?大概是這樣.

  • DATABASE_URL 是數據庫連接配置,postgres和mysql 二選一即可.

執行遷移數據庫腳本

hydra自帶的,直接執行即可.

docker run -it --rm \
  --network hydraguide \
  oryd/hydra:v1.0.0-beta.5 \
  migrate sql $DATABASE_URL

正常執行的話,應該如下:

Applying `client` SQL migrations...
Applied 0 `client` SQL migrations.
Applying `oauth2` SQL migrations...
Applied 0 `oauth2` SQL migrations.
Applying `jwk` SQL migrations...
Applied 0 `jwk` SQL migrations.
Applying `consent` SQL migrations...
Applied 0 `consent` SQL migrations.
Migration successful! Applied a total of 0 SQL migrations.
Migration successful!

數據庫好了,我們現在可以開始搞服務端了.

啟動hydra 服務端

docker run -d \
  --name ory-hydra-example--hydra \
  --network hydraguide \
  -p 9000:4444 \
  -e SYSTEM_SECRET=$SYSTEM_SECRET \
  -e DATABASE_URL=$DATABASE_URL \
  -e OAUTH2_ISSUER_URL=https://localhost:9000/ \
  -e OAUTH2_CONSENT_URL=http://localhost:9020/consent \
  -e OAUTH2_LOGIN_URL=http://localhost:9020/login \
  oryd/hydra:v1.0.0-beta.5 serve

這里我們留意幾個傳入給容器的環境變量.

  • OAUTH2_ISSUER_URL hydra所在的地址

  • OAUTH2_CONSENT_URL 授權頁面地址

  • OAUTH2_LOGIN_URL 登錄頁面地址

假裝大家都了解OAuth2.0的流程的情況下,其實這里就流程基本就是:

XX應用請求授權

-> 跳轉到OAUTH2_LOGIN_URL地址

-> 登錄成功

->跳轉到OAUTH2_CONSENT_URL授權頁面

-> 授權成功

->回調XX應用地址並且返回相關授權code/token

-> XX應用使用code/token獲取用戶信息或者其他操作

啟動之后看一下logs是不是hydra是不是正常啟動.

常見問題:"Could not fetch private signing key for OpenID Connect - did you forget to run "hydra migrate sql" or forget to set the SYSTEM_SECRET?" error="unexpected end of JSON input"

確認一下SYSTEM_SECRET有沒有正常設置呀,實在不行直接在docker run的時候帶入.

正常啟動的話,日志如下:


Thank you for using ORY Hydra!

Take security seriously and subscribe to the ORY newsletter. Stay on top of new patches and security insights.

>> Subscribe now: http://eepurl.com/di390P <<
time="2018-08-09T10:23:50Z" level=info msg="Connected to SQL!"
time="2018-08-09T10:23:50Z" level=info msg="JSON Web Key Set hydra.openid.id-token does not exist yet, generating new key pair..."
time="2018-08-09T10:23:51Z" level=info msg="Setting up Prometheus middleware"
time="2018-08-09T10:23:51Z" level=info msg="Transmission of telemetry data is enabled, to learn more go to: https://www.ory.sh/docs/guides/latest/telemetry/"
time="2018-08-09T10:23:51Z" level=info msg="Detected local environment, skipping telemetry commit"
time="2018-08-09T10:23:51Z" level=info msg="Detected local environment, skipping telemetry commit"
time="2018-08-09T10:23:51Z" level=info msg="JSON Web Key Set hydra.https-tls does not exist yet, generating new key pair..."
time="2018-08-09T10:23:55Z" level=info msg="Setting up http server on :4444"

這時候去訪問:https://localhost:9000/.well-known/jwks.json

理論上是能正常輸出結果的.

這個時候說明我們的hydra已經正常跑起來了.

登錄/授權樣例網站啟動

docker run -d \
  --name ory-hydra-example--consent \
  -p 9020:3000 \
  --network hydraguide \
  -e HYDRA_URL=https://ory-hydra-example--hydra:4444 \
  -e NODE_TLS_REJECT_UNAUTHORIZED=0 \
  oryd/hydra-login-consent-node:v1.0.0-beta.5

在上面我們提過,XX應用請求授權的時候,首先是跳轉到統一登錄頁面,

這個本質是是一個統一用戶中心的應用,需要我們自行開發的.

hydra官方提供一個樣例給我們來測試用,node.js寫的.

項目地址:https://github.com/ory/hydra-login-consent-node

這里就是在啟動這個登錄/授權樣例網站了.

PS:我用dotnet core也實現了一套完整的用戶中心授權網站,過幾天空了整理一下開源發出來.

創建oauth client 客戶端

docker run --rm -it \
  -e HYDRA_URL=https://ory-hydra-example--hydra:4444 \
  --network hydraguide \
  oryd/hydra:v1.0.0-beta.5 \
  clients create --skip-tls-verify \
    --id facebook-photo-backup \
    --secret some-secret \
    --grant-types authorization_code,refresh_token,client_credentials,implicit \
    --response-types token,code,id_token \
    --scope openid,offline,photos.read \
    --callbacks http://127.0.0.1:9010/callback

沒什么說的,留意一下callbacks地址即可.

其實就是XX互聯里面的XX應用的一些信息.

測試hydra oauth整體授權流程

啟動一個請求授權的APP,如下:

docker run --rm -it \
  --network hydraguide \
  -p 9010:9010 \
  oryd/hydra:v1.0.0-beta.5 \
  token user --skip-tls-verify \
    --port 9010 \
    --auth-url https://localhost:9000/oauth2/auth \
    --token-url https://ory-hydra-example--hydra:4444/oauth2/token \
    --client-id facebook-photo-backup \
    --client-secret some-secret \
    --scope openid,offline,photos.read

啟動之后訪問http://127.0.0.1:9010/

大概會看到:

Welcome to the example OAuth 2.0 Consumer
This example requests an OAuth 2.0 Access, Refresh, and OpenID Connect ID Token from the OAuth 2.0 Server (ORY Hydra). To initiate the flow, click the "Authorize Application" button.

Authorize application

點擊 Authorize application 立即調整到登錄頁面.

登錄頁其實就是我們上面啟動的node.js的的登錄頁面,即:http://localhost:9020/login?login_challenge=XXX

輸入賬號密碼之后會跳到授權頁面,即:http://localhost:9020/consent?consent_challenge=XXXX

授權選好了之后點擊"" 允許授權,立即跳轉回到回調地址,同時顯示access token相關信息.

Access Token: SwMfFOSHEFpiChmBvRtFLTeaPzCh-TNEXtxTfibgmdw.AgqJrWyn1VlH4FouUucBJSDsmcwOGDI3cHpuy2sDrpI
Refresh Token: 48pXaTrBoXl9JxkweFgQV6frEYPwrkE6BaY8U5mymbo.ZuZe68sqX6wtRTk9k1cKBNPJxQzEBEb0G86tT_WVzCg
Expires in: 2018-08-09 11:46:14.9905228 +0000 UTC m=+3843.912315001
ID Token: eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzo3MzBhZDc4ZC04ODJmLTQzNzItYTRhMi05NTE2NDdlNTk0ZTciLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsiZmFjZWJvb2stcGhvdG8tYmFja3VwIl0sImF1dGhfdGltZSI6MTUzMzgxMTUyMSwiZXhwIjoxNTMzODE1MTc1LCJpYXQiOjE1MzM4MTE1NzUsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjkwMDAvIiwianRpIjoiOGFkMWE2ZTYtZWY3NC00MTM2LThmODUtMGU0N2FhYWYxZjY1Iiwibm9uY2UiOiJkcXBrcXlkaG1iZXZhdXNtYXJzdWxjcW0iLCJyYXQiOjE1MzM4MTE0MTMsInN1YiI6ImZvb0BiYXIuY29tIn0.euqVspiSeYvMonrwHSPxhfXaCOoYtfP5S5_dJLg6zeQ-Kw6rRJfQRh2ddMiaZBOHdRrQLGHouNSd5SCWP4DgKjr6eA4YKmiTNvDKt0ktIBfTROs5HKOIp9NHLSCL636m10lEVAGJEnL2jwVn5JeNjYmn4nRqOqPBfAxmqFYu-RuHk3HP4w9cKAK2tUBvwUkjH7PBkZ4MZI3AgvK985iPxZWkiyJAn4QPSAidenlQqQJXc7kpYpvP6wauk-nWxid6p0GRL1MozEV1Kok6Nqiw5BtEhuuC3Saijezr-G7Va6SwgTe731huzM6xRH_ovh2x4gayQu-qFX6bT8gjvLh6otQbqEa11nNc0gXIauKds2FF8mD65k9-tnFvbs3T7fJS6wu3LOm9VAtCB78CiTH92E7sbGXaQRC9nsB6LCCteoBPYa8e-dYZxXZHPdWP9tDNc3t2Zr1Lg5bljpWXmFcLllO6gSTqhKiT0otQaQgLDm9GvSeobEaCYRmgk50FdGz4z4Sngek6JJBWHNDo16zuJMScLxIdUfhK9LtLpIsL7w7F01GRMkcriowloRM85qO3V-Dq6REY6VzAe3OkT3_0bxsbU_fzFEIbpDcXdq8hchkEq3aAp48dqXb0WE4R7Iwl4JhjDKiQFxP4-Wk5rPqRyRs7rWiDUxS9v29c88pXd6E

這個時候我們使用Access Token去調用userinfo API,即可正常獲取到用戶信息.

curl -X GET \
  https://localhost:9000/userinfo \
  -H 'authorization: Bearer SwMfFOSHEFpiChmBvRtFLTeaPzCh-TNEXtxTfibgmdw.AgqJrWyn1VlH4FouUucBJSDsmcwOGDI3cHpuy2sDrpI' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'postman-token: fecb7032-db0a-bb1b-a61b-de22add7e5bc'

用戶信息如下:

{
    "sub": "foo@bar.com"
}

為什么這里用戶信息只有一個sub呢?

因為他們實現ory-hydra-example--consent的時候什么都沒加進去,

具體應該怎么做等我下次分享dotnet core實現 login-consent再說了..

嗯,本文結束.


免責聲明!

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



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