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

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

hydra 是什麼呢?html

  • 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的服務端框架咯,開箱即用.node

OAuth是撒? QQ互聯知道麼?微信受權登陸知道麼?mysql

擴展閱讀:理解OAuth 2.0:阮一峯git

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

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

本文結束...docker


開始手把手教你跑hydra server

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

準備PostgreSQL 數據庫/MySQL數據庫

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

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

啓動數據庫啦!!!windows

哦,啓動以前先建立一個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再說了..

嗯,本文結束.

相關文章
相關標籤/搜索