2014-12-08 13 views
2

我想让我的小luminus项目中的OpenID连接工作。我对luminus/ring/compojure(主要来自django,flask和servlets)的工作流程有点新颖。我已成功重定向到Google,因此我从Google获取“代码”,但在登录用户之前需要再向Google发出一个请求,并且此调用需要另一个用户未参与的回调,因此我需要将用户的请求搁置为承诺,但我不确定该部分是如何在组合中起作用的。已解决:在compojure中实现oauth2,在响应用户的请求之前,如何等待第二个oauth2回调?

; 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) 
      }) 

回答

1

基于文档谷歌的OAuth2以Web服务器here时,流程包括以下步骤:

  1. 您的应用程序重定向浏览器谷歌的网址;该URL包含查询参数,用于指示所请求访问的类型。
  2. 结果是一个授权码,Google会以查询字符串的形式返回到您的应用程序。
  3. 在收到授权码后,您的应用程序可以将代码(以及客户端ID和客户端密钥)交换为访问令牌,并且在某些情况下还会更新令牌。

如果我正确理解你的问题,第3步不一定涉及到你的服务器的回调,你可以只使用HTTP客户端向Google执行请求。我最近在这个project实现OAuth2以GitHub上,步骤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客户端,但任何其他会做。

相关问题