我想让OpenID connect在我的little luminus项目中工作。我对luminus / ring / compojure的工作流程有点新意见(主要来自django,flask和servlets)。我已经成功地重定向到Google,所以我从谷歌那里得到了“代码”,但是我需要在登录用户之前再向Google提出一个请求,这个调用需要用户不参与的另一个回调,所以我需要像承诺一样暂停用户的请求,但我不确定该部分在compojure中是如何工作的。
; this is my code that redirects them to Google, where they accept
(defn login [params]
(let [google-oauth2-client-id (System/getenv "GOOGLE_OAUTH2_CLIENT_ID")
base-url "https://accounts.google.com/o/oauth2/auth"
args {"client_id" google-oauth2-client-id
"response_type" "code"
"scope" "openid email"
"redirect_uri" "http://localhost:3000/oauth2Callback"
"state" "anti-forgery here"}]
(assert google-oauth2-client-id "can't find GOOGLE_OAUTH2_CLIENT_ID in environment")
(redirect (str base-url "?" (make-query-string args)))
)
)
; this is my code handling Google's first response
(defn oauth2-callback [params]
; params has the code to send to Google
; here I should send another request to google that comes back to another callback like oauth2-token-callback that processes the request to the user in the current context
(redirect "/youreloggedin")
)
在这种方法结束时,我应该向用户发送一条消息,说明他们已经登录,但我需要等到请求回来。如何在luminus中处理此工作流程?
解决。我没有意识到我可以忽略回调参数。
(client/post "https://www.googleapis.com/oauth2/v3/token"
{:headers {"X-Api-Version" "2"}
:content-type :application/x-www-form-urlencoded
:form-params {:code (params :code)
:client_id (System/getenv "GOOGLE_OAUTH2_CLIENT_ID")
:client_secret (System/getenv "GOOGLE_OAUTH2_CLIENT_SECRET")
:redirect_uri "http://localhost:3000/oauth2Callback" ; ignored
:grant_type "authorization_code"
}
:as :auto ; decode the body straight to hash (if possible)
})
答案 0 :(得分:1)
根据Google的网络服务器OAuth2 here的文档,该流程包含以下步骤:
如果我正确理解了您的问题,第3步不一定涉及对您的服务器的回调,您只需使用HTTP客户端向Google执行请求即可。我最近在此project中为GitHub实施了OAuth2,第3步已在此function中实施:
(defn callback
"Handles the callback from GitHub OAuth flow."
[code]
(let [params {:form-params {:client_id client-id
:client_secret client-secret
:code code}}
{:keys [body]} (client/post access-token-url params) ;; This is doing the POST
;; request to GitHub.
token ((qs-map body) "access_token")] ;; Getting the token from
;; the response here.
{:status 302
:headers {"location" "/repos"
"set-cookie" (str "token=" token ";Path=/")}}))
我使用clj-http作为HTTP客户端,但其他任何人都会这样做。